Learn · ~7 min

The harness: what actually does the work

The model is one part. Tools, prompts, memory, and checks do the actual work.

A loop's intelligence is not the model. The model is one component. The harness — the assembly of tools, prompts, context, memory, verification hooks, and guardrails around the model — is what actually does the work and what actually fails. This guide is about engineering that assembly deliberately rather than hoping a clever prompt carries it.

For agents: - You are operating inside a harness — respect its tool allowlist and state paths rather than improvising. - When installing a loop, use the manifest's backends map to bind triggers to your runtime (cron, GitHub Actions, or agent_kanban). - Report harness friction (missing tools, ambiguous docs, failing checks) as task comments — that feedback is part of the product loop. - Treat the manifest as the contract: field definitions live at /spec; the catalog fetch is /registry/index.json.

The harness is the agent

The strongest practitioner writing on agent engineering converges on one claim: capability lives in the assembly around the model, not in the model alone. Tools, prompt and context discipline, memory, verification hooks, and guardrails are the working parts; the model is the reasoning substrate those parts are mounted on (/resources#osmani-harness-engineering).

The practical consequence is that "make the model smarter" is rarely the lever that fixes a misbehaving loop. The lever is almost always in the harness: a tool is missing or mis-scoped, the context window is stuffed with irrelevant state, a check is absent, or a guardrail is too loose. When a loop fails, inspect the harness first.

Context assembly is engineering

What the model sees on each turn — which files, how much task history, what state, which prior observations — is a designed artifact, not a default. Step 2 of the common loop shape (load docs, repo state, memory, tickets, web sources, APIs) is where most loops quietly go wrong: too little context and the model hallucinates; too much and it loses the signal.

Bad context assembly looks like model failure. A loop that "can't follow instructions" is often a loop whose harness is feeding it stale state, truncated output, or the wrong slice of the repo. The fix is to engineer what enters the context each turn: trim observations to what changed, carry forward only the state the task needs, and let the manifest's state.paths declare where durable memory lives so the harness reads it deterministically rather than re-deriving it.

Memory and state discipline

Episodic memory — storing what was tried, what passed, what failed — helps a loop improve across runs, but only when the memory is validated and pruned. Reflexion-style verbal reflection can preserve bad lessons as easily as good ones: a model that records "this approach failed" without an external signal may be encoding a symptom as a rule.

The discipline: memory is a governed artifact. It gets a declared path in state.paths, a retention window, and pruning. Reflection that drives future behavior needs an external check (a test, a reward, a human) before it is trusted — otherwise the loop is learning from its own unchecked self-assessment. See How you know it worked on the maker/checker split; the same principle applies to a loop's memory of its own past.

Subagents and decomposition

When a goal is large or spans multiple contexts, the orchestrator–workers pattern splits work across specialist subagents: a planner decomposes, workers each take a scoped slice, and a parent synthesizes.

The benefit is context and risk isolation per subtask — one worker's noise doesn't pollute another's window, and a failure in one branch doesn't sink the whole run. The cost is coordination overhead and duplicated work: workers can overlap, the parent's synthesis can flatten nuance, and dependency tracking becomes real work. Pay that cost only when the scope genuinely doesn't fit one focused context; for small tasks, a single agent is simpler and cheaper.

Success is silent, failure is verbose

Wire deterministic checks to speak only when something breaks. A verification command that prints OK on success and a detailed diff on failure is doing its job; one that logs a happy summary every run trains humans to ignore it.

Alert spam is a harness defect, not a feature. A watchdog that fires on every poll, or a CI loop that reports "checked, no changes" fifty times a day, is a loop that has not separated signal from noise — and the first real alert it raises will be missed. The manifest's verification.commands should exit silently on success and noisily on failure; a loop whose checks are chatty by default is asking to be muted.

Runtimes are backends, not the product

LangGraph, CrewAI, AutoGen, the OpenAI Agents SDK, coding agents like Codex and Aider, and plain cron or GitHub Actions are execution substrates. They are where a loop runs, not what a loop is.

This is why the Loopmaster manifest is runtime-agnostic and carries a backends section: the same loop.yaml should map onto cron, GitHub Actions, or an agent task board without changing its safety or verification contract. When you install a loop, you are binding a runtime to a manifest, not re-implementing the loop. If a framework requires you to re-declare permissions or gates in its own syntax to get them enforced, that is friction worth reporting — the manifest is the source of truth, and the runtime is a backend.

Where to go next

requirement, not an ops afterthought.

  • Browse /loops to see backend hints declared concretely per template.
  • Field definitions for backends, capabilities, and state are at /spec.

Sources

harness-as-the-agent framing, in the practitioner's own words.

— the workflow-vs-agent distinction and the orchestrator–workers pattern.

with the failure mode of preserving bad lessons.

engineering as a practice, including context discipline.