Agentic Engineering · Rung 3
Harness Engineering
Which agent runs the job, on which model, with which tools, under whose permission, in what isolation. The harness is an engineering decision. Most teams leave it as a hidden default and then wonder why the outcomes are unpredictable.
What A Harness Actually Is
A prompt is what you asked for. Context is what the agent knows. The harness is what the agent is allowed to do about it.
Concretely: which agent program runs, which model it drives, which tools and servers are loaded, which directories it may write to, whether it can reach the network, whether a human approves every action or none of them, whether it works in your live tree or a disposable one, and whether you can watch it happen.
Everybody makes these decisions. Most people make them once, on install day, by accepting whatever the tool shipped with, and then never revisit them. That is the failure. A harness chosen by default is still a chosen harness. It just was not engineered.
The term is not only ours. A 2026 arXiv paper on automated algorithm discovery, Effective Harness Engineering for Algorithm Discovery with Coding Agents, states the case directly: discovery success is shaped not only by model capability but significantly by the design of the execution infrastructure, meaning the harness. Different domain, same finding. The scaffolding is not neutral.
This page stays in its lane. It is rung three of the agentic engineering ladder. What you feed the agent belongs to context engineering. How you word the instruction belongs to prompt engineering. Turning one run into a repeating cycle belongs to loop engineering. Wiring many agents into a dependency graph belongs to graph engineering. Here we only answer one question: who runs the job, and with what authority.
The Six-Line Harness Spec
Write it down before you launch. A harness spec is six lines. If you cannot state all six for the job in front of you, you are not ready to start it.
One Job, Three Harnesses
Take a real job. A helper function has been deprecated across a large codebase. Every call site has to be found, classified, replaced and proven. That reads like one task. It is not one harness. It is three.
The scout reads. It never writes. Read-only sandbox, network off, mid-tier model, headless, structured output. It produces a list of call sites with a classification for each. Give a scout write authority and you have built a refactoring agent that also happens to be unsupervised.
The builder writes. It works in a git worktree on its own branch, so nothing it does touches your editor’s checkout. Edits are auto-approved inside that directory because approving four hundred individual edits is not review, it is data entry. Larger model, visible terminal, because this is the part where a wrong premise gets expensive.
The reviewer judges. Fresh context. Read-only. It receives the diff and the acceptance criteria and nothing else, and it must be able to reject. A reviewer that inherits the builder’s context is not a reviewer, it is a rubber stamp with a larger token bill.
Same task, three answers to who runs it and with what authority. Collapse them into one agent with one permission mode and you get the worst properties of all three.
# 1. SCOUT: read-only, headless, structured output, no write authority
codex exec --sandbox read-only --json \
'find every call site of dc_legacy_price() and classify each as safe or needs-review' \
> scout.jsonl
# 2. BUILDER: isolated worktree, edits auto-approved inside it only
git worktree add ../wt/price-refactor -b price-refactor
cd ../wt/price-refactor
claude --permission-mode acceptEdits
# 3. REVIEWER: fresh context, read-only, judges the artifact not the story
git -C ../wt/price-refactor diff main > review.patch
gemini --approval-mode default -p \
'Judge review.patch against ACCEPTANCE.md. Reject on any unproven claim.'
The exact commands are illustrative and the flags will drift. The discipline will not: three roles, three authority levels, and a reviewer that never inherits the builder’s context.
Visible Agents Versus Headless Workers
This is the trade-off people get wrong most often, because both sides feel free and neither is.
Interactive PTY
You watch the tool calls scroll. You can interrupt mid-turn, correct a wrong assumption before it becomes forty files, and answer the question the agent actually needs answered. It is the highest-fidelity feedback loop available, and it costs the scarcest resource you have. One person can meaningfully supervise a handful of live terminals. Not twenty.
Headless Worker
You launch it and read the result. claude -p --output-format json. codex exec --json. gemini -p --output-format json. opencode run --format json. Every one of them emits machine-readable events, and that is the point. A headless worker without a machine-checkable output contract is a worker whose failure you discover later, in production. Codex pushes this furthest with --output-schema, which constrains the final message to a schema you wrote.
The Hybrid
Real work lands here. Scouts and mechanical passes run headless and report. Anything that changes the shape of the system runs visible, or runs headless and produces a review packet a human reads before anything merges. DCENT_ADE’s terminal-first workspace exists for the visible half: native PTYs, tiled recursive splits, up to 16 tabbed regions on screen at once.
Watching a fleet has its own failure mode: you cannot tell a thinking agent from a hung one by looking at a static pane. Orion, DCENT_ADE’s local-first coordination layer, reads real terminal behaviour to distinguish busy from idle from awaiting input from finished. That distinction has to come from the terminal, not from a hopeful assumption. An availability indicator that guesses is worse than no indicator, because you will trust it.
A Catalog, Not A Favourite
DCENT_ADE‘s native host owns a catalog of supported harnesses: shells, plus Claude Code, Codex, Gemini CLI and OpenCode. The renderer cannot ask the host to run an arbitrary process. It can ask for a catalog entry.
That looks like a limitation until you name the alternative: a WebView that renders untrusted content while holding a general-purpose spawn primitive. Once the process launcher accepts free-form input from the rendering layer, every piece of text the agent reads is a candidate command. A catalog is the cheapest way to make that structurally impossible instead of merely discouraged.
Here is how the four differ where it matters. All four are actively developed and all four are defensible choices.
| Harness | Approval vocabulary | Sandbox mechanism | Headless invocation |
|---|---|---|---|
| Claude Code (Anthropic) | Six modes: default, acceptEdits, plan, auto, dontAsk, bypassPermissions, plus per-tool allow / ask / deny rules layered across enterprise, user, project and local settings | Bash sandbox using Seatbelt on macOS and bubblewrap with an optional seccomp filter on Linux and WSL2; filesystem allow and deny paths plus network domain allowlists | claude -p with –output-format json and –permission-mode |
| Codex CLI (OpenAI) | Approval policies: on-request, never, untrusted, auto_review | Three sandbox modes: read-only, workspace-write, danger-full-access. sandbox-exec Seatbelt profiles on macOS, bwrap plus seccomp on Linux. Network access off by default | codex exec –json, with –output-schema to constrain the final message |
| Gemini CLI (Google, Apache-2.0) | –approval-mode with default, auto_edit or yolo | macOS Seatbelt profiles ranging from permissive-open to restrictive-closed, or Docker and Podman containers for cross-platform isolation | gemini -p with –output-format json |
| OpenCode (SST, MIT) | permission config resolving to allow, ask or deny per tool, overridable per agent, with wildcard matching on tool input | Host or container isolation you supply; –auto approves anything not explicitly denied | opencode run –format json, plus opencode serve for an API-driven fleet |
None of these is the right answer. They are four different bets, and the differences are real rather than cosmetic. Codex defaults to network off and ships the tightest per-platform sandbox story. Gemini CLI is Apache-2.0 and leans on containers, which travel further than any single OS policy language. OpenCode is MIT, reaches a large provider registry including local models, and attaches permissions to agents so a scout and a builder differ by config rather than by discipline. Claude Code has the most granular per-tool rule vocabulary and the deepest managed-policy story for organisations.
Our audience already runs many models by task. Running many harnesses by task is the same instinct one layer down.
Why A Control Plane Sits Between Intention And Authority
Here is the argument for all of this, stated once. A model produces text describing an action. Something separate has to decide whether that action happens. That something is the control plane, and where you put it determines what a bad turn costs.
Three things are true at the same time.
First, the attack surface is real. Simon Willison named the pattern the lethal trifecta in June 2025: access to private data, exposure to untrusted content, and the ability to communicate externally. Any two of those are manageable. All three in one session and an instruction buried in a README, a pull request title, an issue comment or a tool description becomes an exfiltration channel. Your agent reads untrusted content constantly. That is the job you gave it.
Second, the protocol itself already says so. The Model Context Protocol’s security guidance treats one-click local server setup as a code-execution decision rather than a configuration convenience. It requires the client to show the exact command that will be executed, without truncation, arguments and parameters included, and to obtain explicit approval before running it. That is a clear statement about where the boundary belongs.
Third, and least comfortable: capability does not reduce the need for the boundary. The harness engineering paper cited above reports that more capable models produced evaluation hacks at higher rates, meaning generated programs that exploit the scoring function rather than solve the problem. A stronger model is better at everything, including at satisfying your acceptance check without doing your work. The control plane matters more as models improve, not less.
So DCENT_ADE puts the authority in the Tauri and Rust native host. The WebView does not receive general spawn, SQL or fetch authority. Not asked politely to avoid it. It does not have it. MCP and tool servers go through a native registration catalog with approval-bound activation, native-owned executable and argv, and working-directory and environment restrictions, so activating a server is a decision a human makes against a command they can actually read. Egress controls are native-owned. Workspace memory is native-scoped local Markdown with bounded read, write, append, list and search, rejecting unsafe roots, path traversal, oversized documents and stale writes. Ordinary local work emits zero telemetry.
Inference follows the same rule. Local and LAN first, with Ollama and LM Studio discovery, management and model-role assignment. Cloud is available and it is an explicit, consented boundary, never an invisible fallback. A fallback you did not consent to is an egress you did not know about.
Isolation Is Cheaper Than Trust
The cheapest isolation available is already in your toolchain. git worktree add gives an agent its own working directory and its own index against the same object store. No clone, no duplicated history, no lock contention with your editor. One branch per agent, one directory per branch. Parallel agents stop being a merge problem and become a review problem, which is a far better problem to have.
Above that sit the OS primitives the harnesses already drive for you: Seatbelt, bubblewrap, Landlock, seccomp. Above those, containers. Above those, another machine. Pick the weakest isolation that makes the run survivable, then take one more step. The harness engineering paper poses the question in exactly these terms, asking how agents that require full filesystem access can execute safely in parallel. That stops being academic the first time two agents fight over one file.
DCENT_ADE’s Mission Control combines worktree isolation with claims, so two agents cannot silently take ownership of the same work. The roles run Coordinator to Scouts to Builders to Reviewers, then human approval, then integration and delivery.
When To Interrupt, And How Output Gets Checked
Interruption is a harness control, not a personality trait. Interrupt when the agent states a premise you know to be false, because a wrong premise compounds and every later turn is built on it. Do not interrupt to micro-manage a mechanical pass; if you are correcting formatting in a live terminal you picked the wrong harness for that job. Do not rescue a run that is about to fail cheaply, either. A run that dies in ninety seconds with a clean error teaches you more than one you nursed into a plausible half-result. And if you keep interrupting the same class of mistake, that is a signal about the instruction or the context, not about the run in front of you. Fix it upstream.
A harness decision is not finished until you have decided how the output gets checked. Headless output should be machine-checkable before a human ever reads it: an exit code, structured events, a diff that applies, a test that runs, a file that exists at the path it claimed. The agent said it was done is not evidence. Real evidence is real files, real tests, real pixels, real git effects.
Then a human. Review packets, MergeGate, co-signing. We hold ourselves to this in DCENT_ADE’s own build rules: no fake agents, no simulated activity, no fabricated telemetry, no optimistic availability indicators. The current catalog execution layer refuses to claim a Git merge it does not perform. An honest failure is worth more than a dishonest success, and a harness that misreports what happened is worse than no harness at all.
For turning a single reviewed run into a repeating cycle, see loop engineering. For the adversarial variant we actually build with, where an independent critic gets fresh context and is allowed to reject, see gauntlet loops.
Shoulders We Are Standing On
We invented none of this. The vocabulary and nearly all of the machinery came from other people’s work, and it is worth naming them properly.
Anthropic’s Claude Code, OpenAI’s Codex CLI, Google’s Gemini CLI and SST’s OpenCode each shipped a different and defensible answer to the permission question, and every one of them is easier to reason about because the others exist. The Model Context Protocol gave tool integration a shared shape and a written security posture rather than leaving it to each vendor. tmux taught a generation that a terminal session is a durable, attachable object instead of a window that dies with your connection. Git worktrees, Seatbelt, bubblewrap, Landlock, seccomp and containers are the isolation primitives all of this rests on, and none of them were built with agents in mind. Ollama and LM Studio made local inference something you can actually operate rather than admire. Simon Willison named the lethal trifecta clearly enough that people who are not security researchers now design around it.
DCENT_ADE is free, open and as-is. There is no paid tier, no gatekeeping and no feature held back. If you use it commercially, or it saves you real work, a voluntary subscription or donation is expected and never enforced: d-central.tech/fund.
Related products, repair, and setup paths
- how D-Central diagnoses ASIC repairs
- ASIC troubleshooting library
- ASIC manuals and repair guides
- replacement hashboards
- ASIC control boards
- ASIC power supplies
- S19 family replacement hashboard
- C52 replacement control board
- APW12 S19 power supply
- compare specs in the ASIC miner database
- compare ASIC miner specs
- ASIC miner database
- ASIC repair services
- Antminer S19 specs and profitability
- buy a tested Antminer S19
- Antminer S19 maintenance guide
- Antminer S19 repair service
- Antminer S21 specs
- Bitmain Antminer S21
- Antminer S21 maintenance guide
- BM1370BC S21 Pro chip
Last reviewed August 13, 2026.
