Does a zero-dollar agent run still need a paper trail?
I keep hearing the same shrug in reviews.
People treat free compute like it cannot leave scars.
That is the myth under the other myths.
A cheap run can still mutate a private repo.
A cheap run can still leak a live token.
This FAQ dumps five claims I still hear.
No latency charts. No fake percentile theater.
Just identity, pins, secrets, and merge gates.
Why this FAQ exists
Agents now spawn on boxes nobody really owns.
The invoice is empty. The blast radius is not.
Reviewers then argue from vibes instead of files.
People pair a free model with a free server.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode offers free model access and a free server option.
That pairing is fine for a throwaway lab.
It does not make the run anonymous.
Strip the product name. The myths remain.
How to read this
Treat each myth as a sentence you have said.
Read the corrected model out loud once.
Then run the receipt script before any merge.
The script is a proposed workflow, not a trophy.
I am not inventing quotas, SKUs, or timings.
Do not cite this FAQ as a capacity plan.
Myth 1: If the box is free, nobody is liable
The claim
"It is a free server, so ownership is optional."
"If it breaks, we just spin another one."
"No name exists on a zero-dollar process."
Why that claim fails
A process still has a uid on the box.
A git push still carries an author string.
A leaked token still hits a real API.
Free does not mean unattributed work.
Ephemeral does not mean consequence-free work.
Your reviewer still needs a human to ping.
Corrected mental model
Treat the free box like a named scratch runner.
Someone started it. Someone can stop it.
Record that someone before the first prompt.
# proposed: capture invocation identity
mkdir -p .run
{
echo "utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "user=$(id -un)"
echo "uid=$(id -u)"
echo "host=$(hostname)"
echo "pwd=$(pwd)"
echo "git_user=$(git config user.name || echo missing)"
echo "git_email=$(git config user.email || echo missing)"
echo "head=$(git rev-parse --short HEAD 2>/dev/null || echo none)"
} > .run/identity.txt
cat .run/identity.txt
Ask yourself one rude question in review.
If this writes to main, who gets the page?
Myth 2: Retries replace tests because retries are free
The claim
"The model is free, so I can loop forever."
"The server is free, so failure is cheap."
"A later green retry counts as a test."
Why that claim fails
A retry without a fixture is folklore.
You cannot tell luck from a real fix.
The next answer will drift again anyway.
Free retries hide flaky tools well.
They also hide missing assertions well.
Price zero is not the same as variance zero.
Corrected mental model
A retry is only a sampling strategy.
A test is a contract sitting on disk.
Do not merge a sample. Merge a contract.
# proposed: one command, one fixture, one exit file
mkdir -p .run tests
python -m pytest tests/test_agent_contract.py -q
echo $? > .run/pytest.exit
cat .run/pytest.exit
What did the second run actually prove?
That you rolled the same dice again?
Myth 3: A free server sits outside your threat model
The claim
"It is just a lab box. Relax."
"No production data, so no secrets policy."
"Env files on a free host are harmless."
Why that claim fails
Labs still clone private application repos.
Labs still carry cloud keys in .env.
Labs still run curl | sh from a model.
The box does not know it is "just a lab."
Your token issuer does not know either.
Compromise does not check your invoice first.
Corrected mental model
If the process can reach the network, scope it.
If the repo is private, assume the box is hostile.
Keep secrets out of prompts and out of git.
# proposed: refuse to start if secrets look loose
set -euo pipefail
if git ls-files --error-unmatch .env >/dev/null 2>&1; then
echo "tracked .env is a merge blocker"
exit 2
fi
if grep -R --line-number -E 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,}|xox[baprs]-' . \
--exclude-dir .git --exclude-dir .run --exclude-dir node_modules; then
echo "token-shaped strings in the tree"
exit 2
fi
echo 0 > .run/secrets.exit
Would you paste that .env into a group chat?
Then do not ship it onto a free box.
Myth 4: Skip pins, because you can always re-run
The claim
"Free means I can reproduce it later."
"Whatever Python the image has is fine."
"Lockfiles are for production, not labs."
Why that claim fails
Re-run is not the same as reproduce.
The image moved. The index moved too.
The model will not recant the old path.
Without a pin you only have a story.
Stories do not bisect over a weekend.
Stories do not survive a teammate's laptop.
Corrected mental model
Pin the toolchain you actually invoked.
Hash the lockfile. Store the command line.
Monday-you should replay Friday without guesswork.
# proposed: toolchain receipt
{
echo "python=$(python -V 2>&1)"
echo "pip=$(pip -V 2>&1)"
echo "which_python=$(command -v python)"
echo "uname=$(uname -srm)"
if [ -f requirements.lock ]; then
echo "lock_sha=$(sha256sum requirements.lock)"
elif [ -f requirements.txt ]; then
echo "req_sha=$(sha256sum requirements.txt)"
echo "warning=requirements.txt is not a lock"
else
echo "warning=no dependency pin found"
fi
echo "cmd=${AGENT_CMD:-unset}"
} > .run/toolchain.txt
cat .run/toolchain.txt
Can you replay Friday's run on Monday?
If not, you do not have a result.
Myth 5: The free box is close enough to CI
The claim
"The agent reported success on the box."
"The remote shell returned zero. Ship it."
"We can skip branch protection this once."
Why that claim fails
A scratch runner is not your pipeline.
It has no required checks you control.
It has no artifact store you can audit.
A wrapper zero is not a test zero.
A summary paragraph is not a diff.
"OK" in prose is not a merge artifact.
Corrected mental model
Use the free box to learn, not to gate.
Merge on receipts plus a human review.
If a file is missing, the run did not happen.
The table below is boring on purpose.
Boredom is the point of a gate.
Artifact: the merge receipt
This is a proposed gate, not a benchmark.
Copy it. Break it. Do not worship it.
I am not claiming a hardware profile here.
Decision table
| Signal | File you must have | Merge? |
|---|---|---|
| Who started the run | .run/identity.txt |
No file, no merge |
| What toolchain ran | .run/toolchain.txt |
No pin, no merge |
| Secret scan clean |
.run/secrets.exit is 0
|
Nonzero, no merge |
| Contract tests |
.run/pytest.exit is 0
|
Nonzero, no merge |
| Tree actually changed | .run/diff.patch |
Empty plus a "done" claim is a fail |
| Human still owns the PR | signed review on your forge | Agent text is not a review |
Ask the table out loud in standup.
Which column are you skipping because it is free?
Proposed receipt.sh
#!/usr/bin/env bash
# proposed workflow — unexecuted until you run it locally
set -euo pipefail
mkdir -p .run
utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)
{
echo "utc=$utc"
echo "user=$(id -un)"
echo "host=$(hostname)"
echo "head=$(git rev-parse HEAD)"
echo "status_before=$(git status --porcelain | wc -l)"
} > .run/identity.txt
{
echo "python=$(python -V 2>&1)"
echo "pip=$(pip -V 2>&1)"
if [ -f requirements.lock ]; then
echo "lock_sha=$(sha256sum requirements.lock)"
else
echo "lock_sha=missing"
fi
} > .run/toolchain.txt
set +e
grep -R -E 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,}|xox[baprs]-' . \
--exclude-dir .git --exclude-dir .run --exclude-dir node_modules >/dev/null
grep_rc=$?
set -e
# grep returns 0 on a match; that is a blocker
if [ "$grep_rc" -eq 0 ]; then
echo 1 > .run/secrets.exit
echo "secret-shaped match; blocking" >&2
exit 2
fi
echo 0 > .run/secrets.exit
set +e
python -m pytest tests/test_agent_contract.py -q
echo $? > .run/pytest.exit
set -e
if [ "$(cat .run/pytest.exit)" -ne 0 ]; then
echo "contract tests failed" >&2
exit 1
fi
git diff > .run/diff.patch
if [ ! -s .run/diff.patch ]; then
echo "empty_diff=1" >> .run/identity.txt
echo "agent claimed work, tree is clean" >&2
fi
echo "receipt_ok=$utc"
A tiny contract test worth keeping
# tests/test_agent_contract.py
# proposed example — not a measured suite
from pathlib import Path
def test_receipt_files_exist():
assert Path(".run/identity.txt").is_file()
assert Path(".run/toolchain.txt").is_file()
def test_lock_or_explicit_waiver():
lock = Path("requirements.lock")
waiver = Path(".run/no_lock_waiver.txt")
assert lock.is_file() or waiver.is_file()
def test_env_is_not_tracked():
import subprocess
rc = subprocess.run(
["git", "ls-files", "--error-unmatch", ".env"],
capture_output=True,
).returncode
assert rc != 0, ".env must not be tracked"
Run it like a grown-up job, not a chat.
Then look at git with your own eyes.
chmod +x receipt.sh
./receipt.sh
git add .run tests/test_agent_contract.py receipt.sh
git status --porcelain
cat .run/identity.txt
cat .run/toolchain.txt
wc -l .run/diff.patch
How to read a bad receipt
A missing file is already a failed run.
Do not let the model narrate the gap.
Open the directory before you open the PR.
ls -l .run
test -s .run/identity.txt && echo identity_ok
test -s .run/toolchain.txt && echo toolchain_ok
grep -n '^lock_sha=missing$' .run/toolchain.txt && echo pin_missing
git diff --check
Questions I want in the review thread:
- Who is named in
.run/identity.txt? - Is
lock_shaa real hash, ormissing? - Did the secret scan exit
0on purpose? - Is
.run/diff.patchempty while the summary says done? - Did a human still click the forge review?
If you cannot answer those from files, stop.
The free box did not finish your homework.
It only finished consuming a prompt.
What this does not prove
This receipt is not a compliance program.
It is not a wheel-by-wheel provenance graph.
It is not a model quality evaluation either.
It will not stop a determined leak.
It will not pin a GPU or a region.
It will not make a free box yours.
I am not giving quotas, SKUs, or uptime.
Those claims go stale by the next morning.
Keep this FAQ in the process bucket only.
Who should not use this approach
Skip this if you handle regulated data.
Skip this if the box can reach production.
Skip this if you cannot name an owner.
Also skip it if you need a vendor SLA.
A free server option is still an option.
Free is a price. It is not a contract.
Do not put customer PII on a shared lab.
Do not let the model echo the .env.
Do not merge because the prose sounded sure.
The five corrected models, again
- Free is not anonymous. Name the invoker.
- Free retries are not tests. Keep fixtures.
- Free labs still leak. Scan before start.
- Free re-runs are not pins. Hash the lock.
- Free "OK" is not CI. Keep receipts.
Which one did you violate last week?
Be honest. The diff already knows.
Closing
Keep the receipt in the pull request.
Paste the files, not the pep talk.
If you try this workflow on a free model and a free server, share .run/ instead of the chat.
Top comments (0)