FAQ: A Welcome Credit Is Not a CI Model Pin
Merge requests keep showing the same risky shortcut.
Someone pastes a free model key into CI.
Then the description calls the pipeline fully covered.
Is a welcome screen really a binding contract?
I do not think that shortcut holds up.
This FAQ is for GitLab authors wiring agent jobs.
I am not claiming a benchmark or a quota.
I am claiming something smaller you can check.
You can separate a chat credit from a job pin.
You can fail the pipeline when that pin is missing.
Why this keeps failing review
A green chat bubble feels like hard proof.
It is not proof of your merge request.
Did the job use the same model as chat?
Did the free server still accept that route today?
Those two questions carry the rest of this FAQ.
If either answer is a shrug, stop the merge.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
The operator describes MonkeyCode as an open-source project with those two offers.
I am writing as outreach, not as your on-call engineer.
The operator supplied two availability claims for this draft.
Free model access is an offer you must re-read.
A free server option is an offer you must re-read.
I will not invent model names or token totals.
I will not invent expiry dates or hardware specs.
A landing-page number is a claim, not a receipt.
Verify that claim on the current plan page.
Do that before you cite it in a review.
A chat brief is not a primary source.
Myth 1: Free tokens are a pipeline budget
Developers repeat this right after a signup email.
They say free tokens mean CI can spend them.
A dashboard bucket is not a job contract.
Your pipeline cannot see that bucket by magic.
A masked variable only proves a string exists.
It does not prove any remaining balance exists.
What you can observe
You can observe the variable name in CI settings.
You can observe a redacted key line in the log.
You can observe the HTTP status your client stored.
What you cannot observe
You cannot observe remaining credit from a green job.
You cannot observe a future reset from last week's chat.
You cannot observe a vendor total I refused to invent.
Corrected model: a budget is a written limit plus a check.
The limit lives in a file reviewers can diff.
The check fails closed when runtime evidence is missing.
Myth 2: The free server is your runner
This myth sounds practical until you draw the boxes.
A free server may host a model endpoint.
Your runner still executes the actual job script.
Those are different machines with different failure logs.
Which log would you attach to an incident review?
If you cannot name it, you do not have a receipt.
The swallowed error
If the endpoint times out, the runner may still pass.
That happens when the script swallows the error.
A rescued exception is not a successful inference.
A free host also does not store your job artifacts.
GitLab artifacts still need an artifacts key or an upload.
Do not confuse a chat host with an artifact store.
Corrected model: the server is a dependency, not the runner.
Pin the base URL in CI variables you can audit.
Record the status code beside the job name.
Myth 3: Today's free route is a model pin
Free access can change without your merge request noticing.
A default name inside an SDK is not a pin.
A missing version field is not latest stable.
It is an unknown route with a friendly label.
Would you ship a compiler with an unknown version?
I would not, and I would not ship this either.
I am not stating that any vendor will revoke access.
I am stating your YAML should not assume permanence.
Operator notes here do not include a duration.
So this workflow refuses to hard-code a duration.
Corrected model: a pin is three printable fields.
Print provider, model id, and the verification date.
If any field is empty, the job stops.
Chat success last week does not fill those fields.
A screenshot of a welcome page does not either.
Myth 4: A laptop demo is the MR widget
You ran a prompt on your laptop last night.
The answer looked sharp enough to merge today.
Does the merge request widget actually know that?
No, the widget knows jobs, reports, and artifacts.
A laptop transcript is not a JUnit file.
Paste it in a comment if you want discussion.
Do not paste it as evidence the job ran.
This is a missing receipt, not a style nit.
Keep the chat trial and the pipeline review apart.
CI variables are not the pin file
People ask why both a pin file and a secret exist.
The pin file is reviewable text in git.
The token is a secret that must not enter git.
Protected variables apply only on protected branches here.
A merge request from a fork may not see them.
Did your green test run with the secret present?
Check the job variable policy before you celebrate.
A skipped secret can look like a quiet success.
Log the presence of the variable, never its value.
# Proposal only. Do not print the secret.
if [[ -z ${MODEL_TOKEN:-} ]]; then
echo "MODEL_TOKEN is unset in this job" >&2
exit 7
fi
echo "MODEL_TOKEN is set; value withheld"
That fragment above is still only a proposal.
It proves presence, not quota, and not model identity.
Pair it with the pin file or you proved a string.
The pin check I want in the repo
I have not executed this against a live vendor quota.
Label it as a proposal, not a measured result.
Copy it, then point it at your own project.
The script only reads a local pin file.
It does not call a model, and it spends nothing.
It also refuses to source the file as shell.
Why should the checker refuse to source it?
A sourced env file can execute shell syntax.
A pin file should be data, not a script.
Proposed checker
#!/usr/bin/env bash
# Proposal only. Not executed against a live quota.
# Requires bash 4 or newer for associative arrays.
set -euo pipefail
pin_file=${1:-.ci/model-pin.env}
required=(MODEL_PROVIDER MODEL_ID MODEL_BASE_URL PIN_VERIFIED_ON)
if [[ ! -f $pin_file ]]; then
echo "missing pin file: $pin_file" >&2
exit 2
fi
declare -A pin=()
while IFS= read -r line || [[ -n $line ]]; do
if [[ $line =~ ^[[:space:]]*$ || $line =~ ^# ]]; then
continue
fi
if [[ ! $line =~ ^[A-Z0-9_]+=[^[:space:]#]+$ ]]; then
echo "bad pin line" >&2
exit 5
fi
key=${line%%=*}
value=${line#*=}
pin["$key"]="$value"
done < "$pin_file"
for key in "${required[@]}"; do
if [[ -z ${pin[$key]:-} ]]; then
echo "empty pin field: $key" >&2
exit 3
fi
done
if [[ ${pin[MODEL_BASE_URL]} != https://* ]]; then
echo "base URL must be https" >&2
exit 4
fi
if [[ ! ${pin[PIN_VERIFIED_ON]} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "verified date must be YYYY-MM-DD" >&2
exit 6
fi
echo "pin present provider=${pin[MODEL_PROVIDER]} model=${pin[MODEL_ID]} verified=${pin[PIN_VERIFIED_ON]}"
Example pin file
Replace every placeholder before you commit the file.
Do not put a raw token in this file.
Tokens stay in masked and protected CI variables.
# .ci/model-pin.env
MODEL_PROVIDER=your-provider
MODEL_ID=your-model-id
MODEL_BASE_URL=https://example.invalid/v1
PIN_VERIFIED_ON=2026-09-25
Job snippet
This job snippet is also only a proposal.
I did not run it on a shared runner.
Use an image that actually ships bash 4 or newer.
check-model-pin:
stage: test
image: bash:5.2
script:
- bash scripts/check-model-pin.sh .ci/model-pin.env
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
A failure walk without a live call
Start the walk with a missing pin file.
The checker exits 2 before any network call.
The job is red for a local reason.
Next, leave the model id empty on purpose.
The checker exits 3 and names the field.
You still have not spent a single token.
Then point the base URL at a plain http URL.
The checker exits 4 because the scheme is wrong.
A non-https endpoint should not pass this check.
Finally, set the verified date to a valid old date.
The script will pass, and that pass is incomplete.
A human still has to open today's plan page.
That walk is the test plan for this FAQ.
I have not recorded exit codes from a runner.
Treat those codes as specified behavior, not captured logs.
How I read the decision table
| Claim you heard | Evidence that would support it | If evidence is missing |
|---|---|---|
| Free model access is currently offered | Current plan page, plus a probe log you saved today | Do not cite a signup email |
| A free server option is currently offered | Current docs URL, plus the base URL in CI | Do not reuse a chat screenshot |
| This job used that model | Job log shows provider, model id, and status | Fail the review |
| Tokens remain for this pipeline | A quota response saved as an artifact today | Treat remaining credit as unknown |
| The free tier is permanent | A written term with an end or renewal rule | Assume the offer can change |
| The runner stored the answer | Artifact paths exist on that job | The chat host did not store it |
How do you read a row in this table?
If the middle cell is empty, take the right cell.
Do not negotiate the row with a green bubble.
A date inside the pin file is only a shape check.
The script does not prove the vendor page still matches.
A human still opens the plan page on review day.
Questions worth leaving on the merge request
- Where is the pin file, and who verified the date?
- Which job prints provider, model id, and status?
- What happens on HTTP 401, 429, or a timeout?
- Are prompts and logs allowed on that host?
- Which artifact would an auditor open next week?
If you cannot answer those five, do not merge the agent job.
A free offer can still be useful for a spike.
A spike is not a release gate you can trust.
Want a stricter bar than this pin check?
Add a second job that fails on any non-2xx status.
Store that status file even when the job fails.
Limits I will not talk past
This checklist does not measure model output quality.
It does not prove latency, cost, or uptime.
It does not scrape a pricing page for you.
Pricing pages change, and a stale scrape becomes a lie.
Run the probe yourself on the day you pin.
I have no fresh vendor measurement for this draft.
The script trusts the pin file you wrote.
A dishonest pin file will still pass this check.
Review that diff the way you review any contract.
Bash 4 associative arrays fail on a tiny shell.
That is why the sample image pins bash 5.2.
If your runner forbids custom images, rewrite the parser.
I am not comparing vendors or ranking free tiers.
Unsupported totals do not get repeated here as facts.
Re-check vendor docs before you publish a number.
Who should skip this workflow
Skip it if you need a signed SLA before calls.
Skip it if prompts include secrets or customer data.
Skip it if regulated text cannot leave your network.
Skip it if your policy forbids third-party inference.
Skip it if you cannot pin a documented model id.
A free server option is a convenience, not a waiver.
Use it when you are prototyping a GitLab job.
Use it when reviewers want a fail-closed pin first.
Use it when the chat trial must stay outside the gate.
Where the product mention actually belongs
MonkeyCode is relevant only as a host you might pin.
Free model access and a free server option are claims to verify.
They are not proof your pipeline is correct.
If you already have access, open today's plan page first.
Then fill the pin file with values you just read.
Let the job fail until those fields exist.
That is the whole correction I want in review.
A welcome credit is a lead, not a pin.
Do not let the first impersonate the second.
Top comments (0)