What this is: twenty-four practices for the half of an agent that is not the model — the loop, the context pipeline, the tool surface, the state it keeps, its trust boundary, its traces, and the doors a human steers it through. Each one is written as the rule, the failure that paid for it, and the form that ports to any implementation.

Environment used here: tinycmdr, a single-file, local-first agent harness running as a supervised process on the machine it manages, driving any OpenAI-compatible endpoint — a local llama.cpp server or a cloud API — on macOS, Linux and Windows. Substitute your own stack; the practices are implementation-agnostic by construction, and the measurements are one harness’s answers rather than targets.

Placeholders: no addresses, hostnames or household detail appear in this post. Peers in the federation material are described by policy tier rather than by host, and every version number is the record’s.

Verified: the runtime figures in section 10 come from the project’s own record, dated to the 26-day window in which the case was built (September–October 2026). They are computed from the tree by a generator that fails a check when the committed number disagrees with the code, which makes them checkable, not independent. The artifact has continued to ship since; the mechanisms that landed after the window are described at the end of section 10 rather than folded back into the practices, because a practice is a rule and a release note is a date.

Not shipped: the prompt text, the tool catalogue, and per-host configuration. The code and the engineering record are public — tinycmdr and tinycmdr-dev — so the record behind every practice here is one clone away.

Abstract

Every property a user experiences of an agent beyond raw text — that it acts, recovers, refuses, remembers, stays inside a budget, can be interrupted, resists content it merely read — is built in the code around the model rather than in the weights. This article distils that layer into twenty-four practices and one checklist, argued from a single fully instrumented case: tinycmdr, a local-first, single-file harness (one Python file of some fifty thousand lines, built over a 26-day window) in which every practice is traced to the failure that paid for it and reduced to a form that ports. The specifics include prompt overhead treated as a measured rent with a subtraction rule, tool schemas disclosed progressively, context shaped for the engine’s cache, window-scaled caps that spill rather than truncate, numeric progress guards, mid-run steerability, secrets the model cannot read, danger decided from parsed effect, indirect prompt injection as a named threat with mechanisms, self-extension under the same gates as human-authored tools, and an observability surface a harness can be graded against. The evidence is one harness, one operator and a 26-day window; section 12 states the threats to validity.

Keywords: agent harnesses, LLM agents, harness engineering, context engineering, tool use, prompt injection, agent-to-agent, trust boundaries, local-first AI

1. Introduction

Model leaderboards credit weights. Anyone who actually operates an agent learns a different lesson. Put a new model under a fixed harness and most of the behaviour survives; swap the harness under a fixed model and almost none of it does. Tool dispatch, retries against a server that drops frames mid-stream, what the model sees and what is withheld from it, what happens when it loops, what it does with a fetched page containing instructions — every one of those is a property of the code around the model. None of them is in the weights.

I use harness for all of it: the loop, the tools and their contracts, the context given and withheld, the state kept across turns and crashes, the gates between an intention and machine state, the traces it leaves, and the doors through which a human steers it. Harness engineering is the discipline of building that system. It is not the same discipline as running a software project — branch flow, release gating, review — and mixing the two is how the interesting parts of both get lost.

2. Evidence base and method

The case is one harness rather than a survey, and its sources are the artifact’s own runtime record. tinycmdr (Trapp, 2026a, 2026b) is a local-first agent harness I built, measured and repaired in public over 26 days, as one Python file of some fifty thousand lines with its release history in the open. It was built for a specific operating position — one operator per host, no administrator rights, local inference to keep per-token cost at zero and to keep files on the machine that owns them. Much of what follows is shaped by that position. It drives any OpenAI-compatible endpoint, so the same harness runs a 9B model on a workstation’s GPU and a frontier model over the internet.

Every release’s changelog entry names a defect and the mechanism that answers it. That is the whole method: the practices below are those mechanisms, compressed, with the failure still attached. A practice whose failure you cannot name is decoration, and I have deleted several of my own.

Seven surfaces carry it. Each has its own failure mode, which is why each needs separate attention, and why “the harness” is a system rather than a wrapper around an API call.

SurfaceWhat it isHow it fails
The loopturn assembly, parsing, dispatch, retries, guards, steeringa wedged, looping, or unsteerable run
Contextfixed prompt, tool index, on-demand schemas, history, memory, tailunbounded rent; cache-destroying instability; no long-horizon strategy
Toolsthe capability surface, each tool with a declared contractcapability without validation or safety
State and memoryconfig, sessions, logs, spill, memory files, personaunrecoverable, un-auditable state
Trust boundarysecrets, confirmation tiers, injection defences, exposurean agent exceeding its mandate, or following content it merely read
Observabilityevent log, transcripts, per-turn instruments, evalsfailures nobody can see, grade or reproduce
Steering surfacesterminal, chat, web page, schedules; file handoff both wayscapability nobody can see or steer; a run that cannot be interrupted

A team shipping an agent product owns all seven whether or not it has staffed them. A research group evaluating agents does not own them and depends on them anyway, because without them nothing about an agent’s behaviour is reproducible.

Two conventions in the record are worth stealing before the practices themselves. Claims about the artifact are computed from the tree, not typed into a document: prompt overhead is rendered by a generator, and the committed number fails a check when it disagrees with the code. And every measurement carries a date, because a number without one is a rumour by the next release.

The framing is design science in the ordinary sense, after Hevner et al. (2004) and Peffers et al. (2007): the harness is the artifact and the practice set is the design knowledge. I would not lean on the label. The practices are inductive. One harness, one operator, one 26-day window, measured by the same machinery that serves the product. That makes them checkable and it does not make them independent, and section 12 states the rest of the threats.

One disclosure belongs here rather than in a footnote. The project and its record were produced with heavy AI assistance; every design decision and review described in this post is mine, and the record is public, so the claims are checkable by someone who is not me.

3. The loop: guards, steering, and a boundary that assumes the model is wrong

1. Progress is guarded numerically

“Not progressing” has to be a number, or the loop cannot enforce it. Identical calls are refused after two repeats and the run is stopped after six, on a canonical hash of the argument signature. A stall watchdog warns at eight minutes and abandons at twenty. Run budgets — 250 steps, 75 minutes, a 120-second budget for shell and code scans, per-segment turn caps — checkpoint and continue rather than dying, so a budget that trips costs a segment instead of the work. Check-ins land every five minutes, and a catch-up sweep covers thirty minutes after a restart. The process itself is supervised by the host’s service manager, so a crash costs a gap in the record rather than the record.

The user-facing cost all of that answers is specific: one looping model wedges the inference slot that every other job on the machine shares, and the operator finds out when something else fails to start. Guarding the thing you can measure beats hoping the thing you cannot see behaves.

2. The tool boundary is defensive, because model output is untrusted input

A tool call is a string a language model produced, and it arrives with the same trust you would give a request body from the internet. Calls are parsed leniently, so a sloppy call does not kill the run; validated against the schema the tool declares before the handler executes; and a wrong-shaped call is answered with the path and the expected type rather than a stack trace. A tool that declares it needs a credential gets it through one seam instead of having its whole file refused at load.

Three releases carry that history: v1.0.26 (“the harness survives a sloppy tool call”), v1.0.28 (“a tool call arrives exactly as the model wrote it”), and v1.1.16, which added schema checks and the credential seam. The portable rule is unglamorous. Validate before dispatch, answer a wrong call with the fix, and never let one malformed argument take down the loop.

3. Endpoint quirks are learned per server and remembered

The OpenAI-compatible surface is a family of dialects, not a standard. Error events arrive inside SSE streams that claim to be healthy. Keep-alive pings hold a generation open long after the server has given up on it. Argument fragments show up out of order, or arrive in parallel calls with the index field omitted. Each of those was a defect from a real server, and each left behind a normalizer or a persisted per-endpoint verdict — reasoning replay, prompt-cache key, 400 handling — stored in state so the next run does not relearn it.

The case speaks the chat-completions surface first and the /responses wire only when the base URL or an error says so (v1.0.83). Assume neither the strict behaviour nor the lenient one; discover the wire, write down what you found, and key it to the endpoint that told you.

4. Platform mechanisms, not platform hope

Every platform difference that mattered arrived as a defect first. On Windows an S4U service task lives in session 0 with no desktop, so GUI work crosses sessions through an attended scheduled task (v1.1.17). os.kill(pid, 0), the standard POSIX probe for a live process, terminates a process on Windows instead of probing it. shlex in POSIX mode eats every Windows path’s separators. A console that cannot carry a glyph kills the print rather than the message. getaddrinfo("") succeeds on Windows and resolves to the local machine. macOS asks its privacy grants — Local Network, accessibility for GUI control — at first use, so the harness names the permission in the failure instead of reporting a mystery (v1.0.34).

Writing those down where the next reader hits them is the practice, not documentation hygiene. A platform difference that lives in an unstated assumption is a bug with a delayed fuse.

5. The run is steerable mid-flight

A message that arrives during a run is folded into it at the next step boundary, not queued until the end. A plan under execution can be read, stopped or redirected while it runs, and a stop reaches sub-agents rather than only the foreground loop (v1.0.40). Steering is what makes the guards tolerable: the loop is allowed to run long precisely because the operator can redirect it without killing it and losing the context that made it worth running.

That path exists because “every door into a running conversation was one-way” was itself filed as a defect. Interruption at a step boundary is a first-class input, not a kill signal.

The check for this cluster is one command and one experiment. Ask the harness to print the numbers it enforces for repetition, stalls and budget, then start a task long enough to interrupt and send it a plain message mid-run. If the numbers are not printed, or the message waits for the run to end, the loop has a failure mode the operator cannot see.

4. Context economics: the prompt is rent

6. The prompt is rent, measured and gated

Fixed overhead is the part of the context you pay for on every turn whether or not it helps, and it is the only part you can put a number on. In the case it is generated from the tree and graded. A clean unpack measured 4,116 estimated tokens, split 2,358 for the prompt and 1,758 for the tool schemas, with a 5,400-token ceiling on the core prompt. A live install with host knowledge loaded measured 5,860.

The estimator is honest about being one. On 2026-09-27 the endpoint’s own tokenizer read 3,462 tokens where the estimator reported 4,145, so the estimate over-reads by roughly 1.2× and the budget errs on the safe side. The reduction arc across releases — 5,333 → 4,802 → 4,301 → 4,145 estimated — is four named deletions, not four rewrites. For scale, the framework this project replaced cost more than 16,000 tokens before its first tool call.

Publish the number and hold a ceiling. An addition that cannot argue for its rent is an addition that does not ship.

7. Subtract before adding

Every new mechanism deletes one, and names the deletion in the same breath. The prompt’s reasoning block cost +214 estimated tokens and paid for itself by merging two anti-fabrication lines and retiring a rule into the settle rule (v1.1.18), with the arithmetic on the record. Two numbers per change — what went in, what came out — is enough to keep a prompt from growing for a year and enough to catch the change that quietly cost 400 tokens.

8. Tool schemas are disclosed progressively

Every tool’s full schema is rent paid on every turn, and most turns use one or two tools. The case pays for a catalogue instead: a compact index of tool names laid out on their shelves’ lines, full schemas revealed on demand or by actually calling the tool, and only eleven of twenty-one core tools always on. A dedicated find_tools call reveals the rest once the index says they exist.

The economics: a custom tool costs about 5.7 characters per tool at eighty tools, and an index line caps at twelve names and collapses the rest to “+N more”. When a per-tool description line cost 167.8 characters, the format changed the same day. The index’s cost gets re-measured as the tool set grows, because that is the one number in the design that has to stay true at three hundred tools.

Pay for discoverability rather than disclosure. The model should be able to find a tool without carrying its schema, and an index whose cost you have not measured is a schema set with extra steps.

9. Context is shaped for the cache

Stable prefix, volatile tail, since the first release — but the bug that mattered was subtler than ordering. An in-flight turn’s reasoning text has to replay whole, or the endpoint’s KV cache diverges from the cut onward, once per tool round, invisibly. The visible symptom was latency and cost, not an error, which is why it took two releases to corner. One fixed the truncation; the other fixed the harness having auto-learned a wrong endpoint verdict from the damage.

Prefix what is cacheable, suffix what changes, and test cache-hit behaviour rather than testing the text.

10. Window limits scale, and out-of-spec refuses

Caps derive from the window the endpoint declares. Tool output is capped at min(configured, window/8) with a 512-token floor; the final landing call is clamped to window/4; presets ship for 8k, 16k and 32k contexts; a declared window below 8,192 is refused outright and one below 16,384 warns. A configuration the harness cannot serve is refused loudly at setup instead of being discovered as a truncated answer two hours into a run.

Small windows are the case this was built for. A 9B model on a workstation GPU has a working set far below its advertised maximum, and a harness that assumes otherwise fails late and expensively.

11. Long-horizon context reduces, offloads and isolates

Three verbs, each with its own failure in the record. Reduce: compaction cuts old exchanges from the request and its evictions stick. A cut that removed history from the payload but not from the session file made every later run re-compact the same span and re-archive it (v1.1.14), while the full text survives in the transcript. Offload: oversized tool results spill to disk, content-addressed, with an index that survives a restart. Isolate: sub-agents get their own context windows, a hard 900-second wall-clock cap each, and a process-wide concurrency gate sized by the slots the endpoint reports, because four concurrent children on a two-slot endpoint was the measured defect (v1.1.12).

A harness with any horizon longer than one window needs all three verbs — shrink, spill, split — or it is one full context away from failing. The check is to fill the window deliberately with a task that does not fit, and watch whether the harness compacts, spills and keeps working, or truncates and claims success.

5. The prompt has to carry the reasoning, not just the routing

12. The prompt carries the epistemics, not just the routing

Most harness prompts teach tool routing and stop there, which leaves both of a model’s real failure modes uncovered: it stalls, and it is confidently wrong. The case spends part of the same measured budget on how to reason and how to check. Check the premise before starting, and say so in one line if the request assumes something missing. Carry one approach to a conclusion, and switch only when the obstacle can be named. Verify by running the check, not by rethinking. Do not perform caution — no invented objections, no stacked hedges. Search the web before planning anything with an external surface, because the model’s knowledge is a dated snapshot and a library’s current release notes are not in it.

The anti-fabrication core is one sentence, learned the hard way: only a tool result proves a tool ran. A model that describes a command it never issued, and a model that reports a file it never read, are the same failure with different costumes. Both cost an operator an hour of believing a status report.

That block shipped as its own release (v1.1.18) and was paid for out of the same budget as everything else. A harness whose prompt teaches only routing owns neither of its model’s failure modes.

The check here is a file you can read. Open your system prompt, count the lines that tell the model what to do with a tool, and count the lines that tell it how to know whether it is right. If the second number is zero, the prompt is a call router wearing a policy’s clothes.

6. Knowledge, identity and state are files, and the operator owns them

13. Knowledge lives as host-readable files

Skills are per-host runbook files, injected on demand when the prompt’s index says they exist. Memory is one plain document per concept, with staleness fields the model fills at use. Nothing the harness knows is confined to an opaque store, because a store the operator cannot read turns every incident into a support case.

The memory tool teaches its index-line format and its TTL semantics at use rather than paying schema rent on every turn (v1.0.77), which is practice 8 applied to knowledge. The skills directory is host state and is deliberately not shipped in the repo: what this machine has learned about itself does not belong in a release.

14. Identity belongs to the operator and the model, not to the program

Persona (soul.md), skills, notes and configuration are editable files the harness reads at start. The operator can rewrite the agent’s persona by hand; the model can edit its own identity files with the same tools it uses for anything else, which makes them editable from inside a conversation rather than only from a shell. Both are read once per process, so an edit lands on restart, and the program ships defaults that it seeds once and never overwrites.

Identity as data rather than code is a small decision with a large consequence. The agent’s character is a thing its user controls and its model can revise, and no release can silently change who it is.

15. State is plain, atomic and recoverable

Config, sessions, logs and memory are readable files in documented formats. A save writes a sibling temp file, fsyncs it, chmods to the destination’s mode, renames over, and fsyncs the directory, so a failure leaves the old file byte-identical (v1.0.27). An unreadable state file is kept as a damaged copy and reported rather than replaced by an empty default, because the empty default is how a recoverable incident becomes a silent data loss. Locks are keyed to the install folder rather than to a caller’s uid, and live in a sticky 1777 directory (v1.0.79), so two processes started by different means still see each other.

The requirement is that a user can read, edit, back up and repair the state with ordinary tools, and that state outlives the version of the program that wrote it.

16. Bound every accumulating resource at birth

Logs rotate size-bounded with exactly one predecessor. Spilled results are content-addressed with an index that survives restarts. Memory entries carry staleness bounds, and the memory caps refuse rather than truncate, naming the way out — 400 concepts at 6,000 characters each. Sessions and caches have keep-bounds, payload dumps land 0600 inside a 0700 directory, and the operator upload folder has a stated keep-days bound.

For every growing list, log, cache or directory, name the bound and the place it is enforced. The failure this prevents is the quietest one in the list: a disk that fills over six weeks and takes the harness down on a Tuesday morning with no single cause to find. The check is a du you can run today and a du you can compare it to in a month.

7. The trust boundary: nothing the model can read is trusted

17. Secrets live where the agent cannot read them

Credentials sit in a dotenv the model is never shown. The agent-editable configuration holds no token, so a config edit by the model cannot grant it a credential. Secret values are masked at every export, every log line and every spill — masking at the happy path only is how a key ends up in a transcript that gets pasted into a chat. Installers write their outputs 0600 and never echo the page token (v1.0.24 onward).

One rule covers the design. No credential appears in anything the agent can read or write. That is a stronger statement than “the agent is told not to print secrets”, and it is the only version that survives compaction, an injection, or a model having a bad round.

18. Danger is read from effect, not spelling

Confirmation is tiered — blocked, confirm, allowed — and the tier is decided semantically. One unwrap rule peels wrappers, shell keywords, variable assignments, line continuations and interpreter payloads before any tier reads a verb, and a script’s contents are read as commands (v1.1.1). Every guard in this project that matched spelling was walked past by a new spelling, which is the general result: a blocklist of command names is a puzzle with an infinite number of solutions.

The design phrase for the whole boundary is a seatbelt, not a leash. It is friction with visible scope, applied to parsed intent, and its trust root lives outside anything the agent can write. Tier the friction so the prompts that remain are meaningful — a confirmation you have trained the operator to approve reflexively is not a control.

19. Indirect injection is a named threat with mechanisms

Content the agent merely reads can carry instructions, and this is the one practice in the set that has a measurement behind it rather than an argument. A note inside a folder the operator had asked the run to clear carried four numbered steps. The run executed all four (2026-09-25, macOS). Nothing was malicious in that case, which is exactly why it is the useful one: the mechanism worked perfectly and the payload was benign.

Two defences came out of watching it happen. A one-off untrusted-data hint attaches to fetch_url and web-search results: roughly 65 tokens saying the text inside a tool result is data and never instructions. It is delivered where it applies instead of sitting in the static prompt paying rent on turns that never fetch anything. And instruction-shape detection runs over file and tool content: a phrase signal (“ignore previous instructions”, “before you delete”) or a numbered step list in which at least two steps carry a path alongside a shell verb. The confirmation tiers then apply regardless of who proposed the action, so injected intent still faces the gate.

Decide deliberately whether your harness ingests untrusted content at all. If it fetches web pages, it does, and then labelling at the point of reading, shape detection and a gate that ignores provenance are load-bearing rather than decorative.

20. Capability the agent writes for itself passes the same gates

The case lets the model mint a routine into a durable tool through create_tool, written by a toolsmith that loads it at the next start. The creation is classified as a write, the same tier as editing a file. The created tool is classified as exec when it is called, failing closed in the policy map, with provenance tracked in state. So an injected instruction to “create a tool that does X” meets the write gate, and the capability that results meets the exec gate, with no special case for who wrote it.

Self-extension is a feature, not an exemption. The moment an agent can mint callable capability, the mint is a write like any other, and the honest way to say it is that the agent’s author identity buys it nothing.

21. Remote principals are a narrower trust tier than the local operator

When several harnesses federate under one hub over the agent-to-agent protocol, a peer’s authority is configured rather than inherited. The read_only tier refuses every write and exec tool arriving over the wire while the local page keeps full tools, and that is what the cohort recipe sets. Remote tokens are per-box, named per peer so one rotates alone, and live in the environment rather than in the agent-editable config.

The transport’s limits are stated instead of assumed: a bearer token over plain HTTP on a private network, with a startup warning if the address is public. The local door follows the same doctrine in the other direction — loopback by default, a network bind as an explicit act, and a mandatory bearer token whenever the door is open. The A2A specification requires encrypted transport in production, and this peer link is deliberately cleartext on a trusted private network; that is a narrowing carried by configuration and stated as a position, not an oversight.

The general rule is the one worth carrying: the moment a harness has more than one principal, authority becomes explicit per-principal configuration, and the default direction for a remote peer is downward rather than sideways.

22. Fail loudly, and degrade with a name

A failed lockdown prints failure rather than “locked”. A missing guard pattern makes the doctor exit non-zero, so configuration cannot silently downgrade the tiers (v1.0.24). Bounds refuse instead of truncating, unreadable state is quarantined and named, and every degraded path reports the value, the path and the next command to run.

The reason is not tidiness. Silent degradation is the worst failure mode available, because it makes every other fact about the machine untrustworthy — once you know a truncation can look like a complete answer, you cannot trust any answer without re-running it.

The check for this cluster is a negative test, and it is the one most harnesses skip. Break a control on purpose — rename a guard pattern, make a state file unreadable, point the peer token at nothing — and confirm the harness says so, in words, at the point of failure. A control you have never seen fail is a control you are guessing about.

8. If you cannot see the turn, you cannot grade it

23. Every turn leaves a trace

Runs append a shadow event log (sessions/.events.jsonl) beside the transcript, and the harness instruments each model turn: request shape, tools on the wire, server-reported token counts, who spoke last (v1.0.10). That surfaces in a live log panel and in per-run cards. The transcript keeps what compaction destroys, so a post-mortem can reconstruct what the model actually saw, which is usually the question you are trying to answer and never the thing a chat log preserves.

Record the turn as the wire saw it, and keep the record out of the request. A harness that cannot be traced cannot be debugged, and the failure that motivates this one is the operator who has to say “it worked yesterday” and mean it.

24. Evals run against a real model

Grading is end-to-end with real inference. Mocks grade the mocks. The case carries nineteen tasks against a live endpoint plus a suite built around the small-model thesis: caps that follow the window the endpoint actually serves, graceful degradation when it is small, honest failure when the request cannot be met. The set is deliberately small. Each task targets exactly one guarantee the harness makes — steer mid-run, a window too small to work in, a command the policy refuses — and real local inference costs machine-minutes per run. A set large enough to be impressive would be a set nobody runs.

Failures found this way become permanent checks. The eval set and the guarantee set then grow together. That is the only version of this that stays honest: a harness that is never graded with a real model is graded by its author’s optimism.

9. The checklist, and the anti-patterns it exists to catch

Twenty-four rows, ordered by the cost of leaving it out, with the minimal shape of each and the failure it prevents. The grading move is mechanical and takes an afternoon: for each row, the harness either has the capability or it has the failure.

#CapabilityMinimal shapeFailure it prevents
1A progress definitionnumeric loop, stall and budget guards, enforced in the loopone wedged run consuming the machine
2Mid-run steerabilityinterruption at step boundaries; steering folded in where the next turn readsa run that can only be watched or killed
3A defensive tool boundaryparse leniently, validate against declared schemas, answer wrong calls with the fixone malformed call killing a run
4Persisted endpoint knowledgeper-server quirks detected, stored, honouredre-learning the same server bug every run
5Platform-native mechanismsthe real mechanism per OS, written down where it bitesfeatures that work on one platform only
6A measured context budgeta fixed-overhead figure generated from the code and heldprompts and schemas growing unnoticed
7A subtraction rulea new mechanism names the one it deletessediment that never dies
8Progressive tool disclosurea measured index; schemas on demand; not everything always-onevery tool’s schema paid on every turn
9Cache-shaped contextprefix stable, tail volatile; replay fidelity testedfull prefill every turn
10Window-scaled limitscaps and refusals derived from the declared windowlate failures on small models
11A long-horizon strategyreduce (compaction that sticks), offload (spill), isolate (child contexts)one full window away from failing
12A behaviour contractverification, recency and anti-fabrication rules in the promptconfident wrongness; stale-data planning
13Host-readable knowledgeskills and memory as plain documents, loaded on demandknowledge locked in opaque stores
14Operator-owned identitypersona, skills and notes as files both human and model can editan agent whose identity can only change in a release
15Plain, atomic, recoverable statedocumented formats; write-temp-fsync-rename; damaged copies keptunrecoverable, un-auditable state
16Bounded growtha named bound on every log, cache, spill and directorydisks and windows filling quietly
17Secrets out of reachno credential in anything the agent can read or writecompaction or injection exfiltrating keys
18Effect-based safetydanger from parsed effect; tiered confirmation with visible scopeguard dodging by new spellings
19Injection defencesuntrusted-content labelling at the point of reading; instruction-shape detection; the gate ignores who suggested the actionfollowing instructions that merely arrived in a file or a page
20Gated self-extensionagent-authored capability enters the same policy pipeline; the mint is a gated writean agent that can grant itself new powers
21Principal-scoped authorityper-peer tiers, narrower by default for remote peers; per-principal tokensa federated peer treated as the local operator
22Loud degradationdegraded paths name the value, the path and the next commandsilent failure poisoning later facts
23Tracesan append-only event log, transcripts, per-turn instrumentsfailures nobody can see or reproduce
24Evals with a real modelend-to-end tasks against a live endpoint; failures become permanent checksgrading by the author’s optimism

Rows 1–5 are the loop’s floor, 6–12 the economics and behaviour of context, 13–16 what the user has to be able to own, 17–22 the trust boundary, and 23–24 the ability to see and grade the rest. The ordering is not arbitrary: the top five are the rows whose absence costs you a morning, and the last four are the rows whose absence costs you a year of not knowing.

The anti-patterns fall out of the same table, and they are what a harness looks like before someone grades it. Trusting what the agent read — tool output and fetched pages treated as context rather than as data, so instructions that arrived in a file get executed because nothing labelled them (19). Ungated self-extension, where the agent mints callable capability without the mint facing the write gate (20), and the wide-open peer, where a federated principal inherits the local operator’s authority by default (21). Spelling-based safety, the one I lost to myself: every matcher on a command’s look fell to a new spelling, and only parsed effect survived (18).

The quieter set is worse. Silent degradation, where truncations look complete, empty defaults replace damaged files, and lockdowns print success (22, 10). Opaque state, where a store nobody can read turns every incident into a support case (15). Growth by addition — rules stated three times, a framework’s 16K-token floor, logs that never rotate — each one fixed in the end by naming the subtraction (6, 7, 16). The policy-free prompt, which routes tools with no reasoning discipline and no recency rule, so the model plans from stale training data and performs caution instead of verifying (12). The hope-based platform, where “it works on my OS” hides undefined separators, terminating liveness probes and glyph-killed prints (5). The unbounded wait, a loop with no numeric definition of stuck, where the run owns the machine until a human notices (1). And the ungraded harness, which keeps no traces and runs no evals against a real model, so every debate about it is settled by anecdote (23, 24).

10. What the case measured

Every row is a number someone can be held to, dated at the version studied. They are one harness’s answers and I would not defend most of the specific values as optima. The point is that each surface has an answer, and that a harness whose answers are unstated numbers is a harness whose failures will be surprises.

MeasureValue
Fixed overhead, clean unpack4,116 est-tokens (2,358 prompt + 1,758 schemas); the endpoint’s own tokenizer read ~0.84× the estimate
Fixed overhead, live install5,860 est-tokens; core-prompt ceiling 5,400
Reduction arc5,333 → 4,802 → 4,301 → 4,145 estimated, across releases
Framework replaced>16,000 est-tokens before its first tool call
Tool index~5.7 characters per custom tool at 80 tools; 12 names per line, “+N more” beyond; 11 of 21 core tools always-on
Run bounds250 steps · 75 minutes · per-segment turn caps, checkpointed
Scan budget120 s of shell and code per run; refusal names the budget
Loop guardrefuse an identical call after 2, stop the run after 6
Stall watchdogwarn at 8 min, abandon at 20; check-ins 5 min; catch-up 30 min
Steeringoperator messages folded in at the next step boundary; stop reaches sub-agents
Tool output capmin(configured, window/8), floor 512 tokens; spill beyond
Context presets8k / 16k / 32k; refuse below 8,192, warn below 16,384
Sub-agent bounds900 s per child; concurrency gated by the endpoint’s reported slots
Injection hints3 one-off rules, 196 est-tokens, kept off the static prompt (2026-09-27)
Peer policyread_only refuses every write and exec tool from A2A peers; per-box tokens in the environment
Eval set19 tasks against a live endpoint; the small-model thesis graded in the same suite family
Tool surface21 core tools, 11 always-on; 33 schemas in the case’s install

The practice set held after the window closed. Work kept landing in the artifact, and the mechanisms in it map onto rows already in this table rather than adding a twenty-fifth: a checkpoint before the harness delivers its own output (practice 12), constants abandoned for measurement where the endpoint can supply the number (practice 10), a peer tier enforced in code where it had only been documented (practice 21). That is the ordinary fate of a good practice set — mechanisms accumulate beneath it while the rows stay put — and it is the strongest claim this case can make for the table’s generality, because none of those changes needed a new column.

One of them is a security patch and belongs outside the table. A linked box’s page token no longer travels in the browser URL: the page trades a single-use, two-minute code for its sign-in cookie, so a token previously handed over in a link of that kind should be treated as disclosed and rotated.

Harness engineering is now a named concern in the field, and the positions taken above sit inside a live conversation rather than beside one. Yao et al. (2026) define the harness as the system layer that manages context, tools, state, constraints, permissions, tracing and recovery, and measure configuration-level effects across 106 tasks and 5,194 trajectories; their conclusion, that capability should be reported at the model-harness configuration level, is this article’s opening claim stated from five thousand runs instead of one case. The failure class they name, execution-alignment failures in which plausible reasoning becomes decoupled from tool feedback, is what practice 12’s behaviour contract and practice 24’s evals exist to catch.

Mei et al.’s survey (2025) formalises the context discipline practised here, and Chroma Research’s context-rot measurements (2025) together with the lost-in-the-middle result (Liu et al., 2024) underwrite practices 6 to 10: a window is a maximum, not a working set. Anthropic’s engineering series on context engineering (2025a) and on agent evals (2025b) converges on the same economics and the same grading discipline from the vendor side. The permission-systems direction of current security guidance, deny by default and structured decisions in place of natural-language trust, is what practice 18 implements as effect matching, and the injection defence in practice 19 answers the threat that guidance names. Practice 21’s principal-scoped authority sits on the agent-to-agent protocol (A2A Protocol, 2026), whose v1.0 specification standardises the cross-principal messaging this harness federates over, with one stated deviation: the specification requires encrypted transport in production, and the peer link here is deliberately cleartext on a trusted private network, a narrowing carried by configuration rather than by the wire. The case also does not speak MCP. Its tools are host files disclosed progressively (practice 8), which follows from the single-file, no-infrastructure premise; the protocols are complementary, MCP standardising tool access where A2A standardises peer delegation, and the practices here bind whichever wire a harness chooses.

The foundational work stays foundational. ReAct established the reasoning-acting interleaving that every harness implements (Yao et al., 2023), Toolformer explored learned tool use (Schick et al., 2023), and the chain-of-thought result showed how much observed reasoning is prompt-mediated (Wei et al., 2022). Retrieval augmentation (Lewis et al., 2020) and instruction tuning (Ouyang et al., 2022) inform the context pipeline, and prefix caching in self-hosted stacks (Gerganov & contributors, 2026) is what makes practice 9’s constraint physical rather than stylistic. Holzmann (2006) argued that a handful of hard rules, bound everything and fail loudly, can carry a safety argument on its own, which is what practices 1, 10, 16 and 22 are once the code being bounded has a shell.

A survey conducted inside the case’s own record compared the shipped system prompts of four sibling harnesses: a coding agent whose prompt spends most of its bulk on tone examples and git procedure, an open agent that keeps behaviour in tool descriptions and skills, a research agent whose identity is a compact behaviour spec, and a frontier open model shipping a one-sentence identity and training the rest into the weights (sst, 2026; badlogic, 2026; NousResearch, 2026; MoonshotAI, 2025). The four converge on the same answers as practices 6 to 14 from a different direction, identity in a sentence or two, rules as short imperatives, routing in tool descriptions, knowledge in files, and none of them holds its prompt to a published budget. The one that ships almost no prompt is the clearest evidence of how much of that budget is still unclaimed.

12. Limitations and threats to validity

One harness, one operator, a 26-day window, self-measured. The numbers come from the same machinery that serves the product, which makes them checkable without making them independent, and the practices are survivors of one environment. The largest technical gap is ablation. None of these numbers — context rent, guard thresholds, cap arithmetic, hint placement, index shape — has been tested against an alternative, so what follows is a set of shapes rather than a set of optima. If you take one value from this post without testing it, take the shape instead.

The security model is insider-shaped on purpose. The harness runs as the operator, on the operator’s own machine, with the operator’s full authority; that is the product premise rather than an accident of implementation. What the model can read is minimised, so secrets live outside its reach. What it can do passes effect-matched confirmation tiers that ignore who proposed the action. What it merely reads is labelled and screened (19), and capability it mints for itself enters the same pipeline (20). Because the case does fetch web pages and run searches, those last two are load-bearing rather than decorative.

What is deliberately absent is worth stating plainly: no sandboxing or virtualisation, so no micro-VM and no container, no egress confinement, no multi-tenant isolation. No TLS on the peer link either, which is a position rather than an oversight. The honest scope is a single operator, per-host machines that may federate across a trusted network, and content that may be hostile guarded by labels and gates instead of by confinement. A harness that ingests untrusted content and executes it without gates would need the sandbox this one does not have.

The last caveat is one the field states and I will repeat because it changes how you should read the whole list: harness guardrails have a half-life. Most of them compensate for a weakness of current models — looping, spelling-sensitive compliance, stale knowledge — and they should be designed to dissolve as models improve. The discipline of tracing every mechanism to a failure makes the retirement criterion mechanical: when the failure class stops recurring, delete the mechanism and bank the tokens. What does not dissolve is the structure. Budgets, traces, gates, contracts, principal scoping and readable state outlive the weaknesses they were built around, and those are the rows I would keep if I could keep only a handful.

References

References follow APA 7th edition; software entries carry the version contemporary to this post. The primary record behind every practice is Trapp (2026a, 2026b), including the changelog entry each practice cites.