You shut the lid on Friday while a coding agent still iterates against a shared free server. The loop looks harmless because it is only a rehearsal spike, not customer-facing production traffic. Monday morning a teammate finds the box busy, the prompt undocumented, and the stop condition missing. Shared free AI stays useful until overnight ownership evaporates, after which the rehearsal quietly becomes a blocker.
Agentic tool loops make this failure mode sharper than a forgotten notebook process. The agent keeps assuming it may call tools, retry failures, and hold the only warm runtime on the host. Your team does not need another glossary of agent terms; you need named humans, a written stop rule, and a paste-ready handoff. This playbook gives you four roles, one wiki page, and a session card you can generate from the shell.
What this SOP is for
Treat every long-running agent session as a borrowed machine, not a private scratch buffer. You are sharing model access, disk, and a process table with people who also have Friday spikes. If the loop can continue after you disconnect, it needs an owner who will still answer Slack. If nobody will answer, the default action is park or kill, never hope.
This article stays useful on any shared box. The free-model and free-server option discussed later is only one place you might rehearse. Do not promote an overnight loop into production routing until the session card is complete and a reviewer has signed the transfer line.
Four roles you assign before the loop starts
Do not start the agent until these four names exist, even when two names belong to the same person. Write the names on the wiki page first, then start the process, not the other way around.
- Experimenter — writes the prompt, tool allowlist, and the hypothesis the loop is testing.
- Session owner — remains accountable while the process lives, including nights and weekends.
- Incoming owner — the human who accepts the next shift and may kill the process on sight.
- Reviewer — a second person who can veto continued spend, extra tool access, or any promotion talk.
If you cannot name an incoming owner for the next twelve hours, you do not have a session owner either. In that case you park the work with a card, or you kill the process before you leave. Shared rehearsal hosts fail when “someone will check it tomorrow” is the only runbook.
The one-page wiki you can paste today
Copy the block below into your team wiki and fill every field before python starts. Empty fields are a failed handoff, not a flexible culture. Keep the page to one screen so the incoming owner can read it on a phone.
# Agent session card (kill / park / transfer)
- Experiment id:
- Hypothesis (one sentence):
- Data class: public-sample / synthetic / **no customer data**
- Host: (shared rehearsal server only)
- Working directory:
- PID / container id:
- Started at (UTC):
- Must stop at (UTC):
- Experimenter:
- Session owner (on the hook now):
- Incoming owner (next shift):
- Reviewer (veto):
- Tool allowlist (exact):
- Forbidden actions:
- Stop condition (tokens, errors, wall clock, or test gate):
- How to kill (exact command):
- How to park (artifact path):
- Transfer notes for the next human:
- Decision: kill | park | transfer
- Sign-off timestamps:
Print that page beside the process list. If the card and the live process disagree, the process is wrong, and the incoming owner kills it. Do not negotiate with a loop that outlived its card.
Numbered handoff run
Run this sequence at every shift change, including a quiet Friday evening. Skipping a step is how orphan loops survive until Monday.
- Outgoing owner freezes input. Stop feeding new files or extra tools into the agent. Record the last prompt hash or file path on the card. You are handing a snapshot, not a moving target that keeps mutating in chat.
- Outgoing owner writes the kill command. Paste the exact shell line, not a vague “stop the python thing.” Include working directory and container name if you used one. The incoming owner must be able to execute it without guessing flags.
- Outgoing owner chooses kill, park, or transfer. Use the decision table below; do not invent a fourth option called “let it ride.” If the stop condition already fired, you only have kill or park. Transfer requires a living incoming owner who replies in-thread.
- Incoming owner repeats the process list. They run the inspection commands and compare PIDs with the card. Mismatch means kill first and reconstruct later from artifacts. They do not attach a debugger to a process they do not own.
- Reviewer signs or vetoes. The reviewer checks data class, tool allowlist, and whether anyone is talking about production. A veto parks the card and kills the process. Silence from the reviewer is not approval; it is a missing signature.
- Someone updates the wiki timestamp. The card is the source of truth, not the Slack thread that will scroll away. If the wiki is down, you kill the loop rather than extending it on memory.
Inspection commands you should actually run
Label these as a local rehearsal checklist, not as measured production telemetry. Run them on the shared host you control, and never against a machine you do not administer.
# Proposed inspection — run only on your rehearsal host
date -u
whoami
pwd
ps -eo pid,etime,user,cmd | awk 'NR==1 || /python|uvicorn|node|agent/'
ss -lptn 2>/dev/null | head
ls -lt ./artifacts/session-cards 2>/dev/null | head
If etime is already past the “must stop at” field, you do not investigate further for curiosity. You execute the kill command written on the card. Curiosity is how a “quick look” becomes another unowned overnight loop.
# Proposed kill — replace with the line stored on the wiki card
kill -TERM <PID>
sleep 2
ps -p <PID> || echo "process gone"
# if it still exists:
kill -KILL <PID>
Park means you persist artifacts and then kill anyway. A parked loop is a directory plus a card, not a sleeping process that might wake and keep calling tools.
Session card artifact (proposed Python)
The script below is a proposed helper, not a benchmarked service, and you should read it before running it. It refuses to start when required ownership fields are missing. That refusal is the entire point: the agent must not outrank the roster.
# proposed_session_card.py — example only, not production control plane
from __future__ import annotations
import json
from datetime import datetime, timezone
from pathlib import Path
REQUIRED = (
"experiment_id",
"hypothesis",
"data_class",
"host",
"session_owner",
"incoming_owner",
"reviewer",
"stop_condition",
"kill_command",
"decision",
)
ALLOWED_DECISIONS = {"kill", "park", "transfer"}
ALLOWED_DATA = {"public-sample", "synthetic"}
def build_card(payload: dict) -> dict:
missing = [key for key in REQUIRED if not str(payload.get(key, "")).strip()]
if missing:
raise ValueError(f"refusing to start loop; missing fields: {missing}")
if payload["decision"] not in ALLOWED_DECISIONS:
raise ValueError("decision must be kill, park, or transfer")
if payload["data_class"] not in ALLOWED_DATA:
raise ValueError("customer or unknown data classes are not allowed on shared hosts")
if payload["session_owner"] == payload["reviewer"] and payload["decision"] == "transfer":
raise ValueError("transfer needs a reviewer who is not the current session owner")
payload = dict(payload)
payload["written_at_utc"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
return payload
def write_card(payload: dict, directory: str = "./artifacts/session-cards") -> Path:
card = build_card(payload)
out_dir = Path(directory)
out_dir.mkdir(parents=True, exist_ok=True)
path = out_dir / f"{card['experiment_id']}.json"
path.write_text(json.dumps(card, indent=2), encoding="utf-8")
return path
if __name__ == "__main__":
demo = {
"experiment_id": "spike-2026-09-10-agent-loop",
"hypothesis": "A tighter tool allowlist reduces retry storms overnight.",
"data_class": "synthetic",
"host": "shared-rehearsal",
"session_owner": "alex",
"incoming_owner": "sam",
"reviewer": "riley",
"stop_condition": "wall-clock 4h or 8 consecutive tool errors",
"kill_command": "kill -TERM 12345",
"decision": "park",
}
print(write_card(demo))
Wire your starter script so it calls build_card() before it launches the agent. If you cannot import this check, you also cannot claim you had a handoff. A README sentence is not an ownership control.
Decision table: kill, park, or transfer
Use this table on the wiki page so people stop inventing local folklore. When two rows could apply, choose the upper row. Upper rows prefer a dead process over an unexplained live one.
| Condition | Decision | Who acts | What you must leave behind |
|---|---|---|---|
| Stop condition already hit, or PID is not on the card | kill | incoming owner | wiki note with timestamp |
| Incoming owner did not reply before you leave | park, then kill | outgoing owner | card plus artifact directory |
| Data class is unclear or tools expanded mid-loop | kill | reviewer or incoming | short incident note |
| Work is useful, next human is present, allowlist unchanged | transfer | both owners | updated card and PID |
| Anyone mentions production, customers, or real secrets | kill | reviewer | do not park on the shared host |
Transfer is the narrow path. It requires a living incoming owner, a reviewer signature, and a stop condition that still has budget. Everything else is park or kill. “The agent is almost done” is not a row in the table.
Where a free model tier participates
You need a cheap rehearsal lane so this SOP gets used before anyone touches paid production routing. Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode is an open project that currently states it offers free model access, a stated ten-million-token pool, and a free server option for that kind of rehearsal.
Use that lane only for synthetic or public-sample prompts that match the card’s data class. Put the session card in git or the wiki, not in the model prompt, so ownership survives even if the chat transcript is noisy. If the free server is shared, the four roles matter more, not less, because collision cost is social as well as technical.
Do not treat those free-tier statements as a capacity plan, a latency promise, or a permanent quota. This playbook does not measure throughput and does not name models. If the rehearsal host disappears, your artifacts and wiki page should still explain what you were testing.
Limitations and who should not use this
This SOP does not replace access control, secrets management, or a real orchestrator. It will not save you if the agent can reach customer data, production credentials, or billing accounts. Shared free hosts are the wrong place for regulated workloads, medical text, or anything you would not paste into a public ticket.
Skip this approach when you are a solo hobbyist with a laptop that nobody else shares. Skip it when your company already forbids external model providers or shared servers. Skip it when the loop must stay up for customers; that workload needs paging and budgets, not a one-page wiki card.
Also skip overnight loops when you cannot write an exact kill command. If you cannot kill it, you do not own it, and the agent is only borrowing your reputation. Park the idea, commit the prompt, and start again when a human is actually watching.
Keep the roster louder than the agent
Overnight agent failures are usually social: no incoming owner, no stop rule, and a process that outlived the chat. Fill the four names, generate the session card, and make kill the default when the card and the host disagree. If you want a shared rehearsal place to practice the handoff itself, try MonkeyCode’s stated free model access and free server option, then see whether Monday still starts with a named owner.
Top comments (0)