Agent products are easy to demonstrate through capabilities. They can search documents, edit code, operate a browser, call APIs, and stream progress into a polished interface.
An architecture review has to answer a different set of questions:
Once a request enters the system, who establishes identity and tenant scope? Who decides which tools are available? Which record represents the run? When the model says the work is complete, who accepts it, and on what evidence? Who retains the task when the client disconnects?
A feature list cannot answer those questions.
A system may include RAG, memory, MCP, workflows, multiple agents, and an elaborate trace viewer, yet split apart during its first serious failure. The front end reports completion while a worker is still active. The task runner retries a job and the agent repeats the same side effect. The model says that tests passed after running one package. The browser tab closes and takes the only copy of progress with it.
The purpose of the architecture diagram is not to display the most boxes. It is to expose authority, state ownership, data flow, evidence, and failure responsibility.
Part 01 defined the working boundary of a harness. Part 02 places those responsibilities on one system map. Here, complete means complete coverage of responsibilities. It does not prescribe one deployment topology or require every box to become a microservice.

Figure 2-1 | A complete responsibility map shows how requests enter, who owns run state, who may authorise action, and how evidence becomes accepted completion.
Start with authority, not features
Counting features first usually makes an architecture harder to assess.
Two products may both advertise retries while referring to different mechanisms:
- an SDK resends a model request after an HTTP timeout
- the agent loop replans after a tool failure
- a task runner restarts an entire work unit after a worker crash
- an orchestrator assigns the work to another workspace
Four retry layers are not automatically safer than one. Without explicit retry ownership, they may deploy twice, send the same message twice, or write the same record twice.
State has the same problem. A front end, agent memory, workflow engine, issue tracker, and database may all store a status field without a rule for resolving disagreement. They appear consistent on the happy path and diverge after a disconnect, cancellation, or recovery.
A useful harness architecture should answer four questions:
- Which component owns each decision?
- Which record has canonical authority for each class of fact?
- How does an operation cross system boundaries and leave correlated evidence?
- Where does responsibility return after failure, cancellation, disconnection, or retry?
A diagram full of technical nouns is not enough.
A responsibility-centred reference architecture
The following is a general responsibility model:
User / Client Request
↓
Request Boundary
identity · tenant · schema · admission
↓
Task Contract + Effective Policy
objective · acceptance · budget · tools · approval
↓
Canonical Run Authority ↔ Workflow / Agent Controller
├─ Context Builder
├─ Model Adapter
├─ Query Planner / RAG
├─ Capability Registry / Execution Runtime
├─ Hooks / Middleware
└─ Approval and Recovery Gates
↓
Verification + Completion Gate
evidence · criteria · authority
↙ ↘
Not accepted: repair / retry / fallback / stop Accepted
↖ ↓
└──────── Controller Commit state and evidence
↓
Response / Stream / Artefact
Cross-cutting:
- Durable State / Checkpoint / Artefact Store
- Trace / Metrics / Audit / Replay / Eval Data
This is not a simple linear pipeline.
Canonical run authority is read and updated throughout execution. Persistence and observability are not final-stage dumps; they cross the request boundary, controller, capability execution, approval, verification, and delivery paths.
One process may hold several responsibilities. One responsibility may also involve several services. The important property is clear authority, not an attractive service count.
1. Request boundary: establish a trusted entrance
The request boundary turns external input into a request that the internal system can handle safely.
It commonly covers:
- authentication: who submitted the request
- tenant or project scope: which data and resources belong to that identity
- initial authorisation: whether the caller may start this class of work
- input schema: whether fields, formats, sizes, and required parameters are valid
- rate limiting and admission control: whether the system should accept the work now
- request and correlation identifiers: how later events will be joined
Checking that somebody is signed in is not enough. If a multi-tenant system passes only natural-language text into the backend, the RAG, memory, tool, trace, and artefact layers may lose the tenant boundary downstream.
The request boundary should not infer the user’s entire intent. Its job is to fix a trusted identity, scope, and input shape so that every later component does not reinterpret them independently.
2. Task contract and effective policy: separate completion from permission
The task contract answers:
What must this run produce, and what evidence will show that it is complete?
It may contain:
- objective
- in-scope and out-of-scope work
- required outputs
- acceptance criteria
- required evidence
- completion, pause, and stop conditions
A task contract does not have to be generated by the model at run time. It may come from an API request, issue, workflow, human-authored specification, or versioned template. The run must record which version it used.
Policy answers another question:
Given this identity, tenant, task, and risk, how may the system execute?
It may cover:
- available models and fallbacks
- token, time, cost, capacity, and step limits
- tools, data sources, filesystem, and network scope
- timeout, retry, escalation, and cancellation rules
- operations that require human approval
- verification gates that must pass
Effective policy often combines organisation, tenant, project, task, tool, and operation rules. Central authority does not require one enormous configuration file. It requires one auditable resolution path that applies precedence and produces the policy in force for this operation.
If timeout lives in the SDK, budget in the controller, tool denial in a hook, and another allow-list in the prompt, every component may claim to have followed its own rule while the system cannot explain which rule had priority.
The contract and relevant policy can be summarised into model context. Hard limits still belong in the runtime, policy decision path, and execution environment.
3. Canonical run authority: one authority does not mean one database row
Run state records the system facts for one execution, not merely its conversation transcript.
It may include:
- run, thread, turn, and task identity
- current phase, status, and state version
- consumed budget
- tool requests, operation identifiers, results, and unknown outcomes
- pending approvals
- checkpoint, artefact, and evidence references
- policy, prompt, model, and tool-schema versions
- cancellation, error, recovery, and completion state
A transcript may be part of run state or a derived view. It is not the whole execution record.
Suppose a tool successfully writes to an external database but the result event is lost before it reaches the agent. The transcript may look as if the action never happened. The external database still owns the truth of its data. Run state must retain the operation identifier, known outcome, and reconciliation state rather than pretending to replace every external authority.
Canonical therefore does not mean putting every fact into one record. It means:
- each important class of fact has an explicit authority
- the run lifecycle and its state transitions have one controlling authority
- projections can be rebuilt or reconciled
- client views, dashboards, and issue statuses cannot independently rewrite run truth
Part 06 will cover threads, checkpoints, pause, resume, forks, and persistence in detail. For now, one boundary is enough: client memory cannot be the sole source of truth for a long-running task.
4. The controller coordinates execution without owning everything
The workflow or agent controller chooses the next legal state transition from the task contract, effective policy, canonical run state, and latest observation.
In a fixed workflow, code defines most of the path. In a more autonomous agent, the model may propose the next step and tool. Anthropic distinguishes workflows, in which models and tools follow predefined code paths, from agents, in which the model dynamically directs process and tool use. Both can exist inside the same harness. The difference is where decision authority sits.1
OpenAI’s Codex material exposes the same layering. The agent loop coordinates the user, model, and tools. The complete agent experience also needs thread lifecycle, persistence, configuration, authentication, tool execution, and a client protocol.23
The capabilities around the controller can be separated as follows:
| Capability | Primary responsibility | Responsibility it should not quietly absorb |
|---|---|---|
| Context builder | Assemble instructions, task state, history, evidence, and visible tools | Durable-memory authority |
| Model adapter | Isolate provider requests, streaming, tool-call formats, and errors | Product policy |
| Query planner / RAG | Decide when and where to retrieve evidence | Whole-system orchestration |
| Capability registry | Describe schemas, risk, cost, timeout, and permission requirements | Authorisation of this operation |
| Execution runtime | Validate arguments and run tools, commands, APIs, or sandbox actions | Model self-authorisation |
| Hooks / middleware | Observe or transform at explicit event points | A second hidden controller |
| Approval / recovery gates | Pause, obtain a human decision, repair, fall back, reconcile, or stop | Treat approval as an ordinary tool call |
Registry and runtime are separate because knowing that a tool exists is not the same as authorising and successfully executing this operation.
Approval is not simply another capability card beside the context builder. It is a policy- and state-bound gate tied to an operation, its arguments, risk, expiry, and current state version.
What can a small block of pseudocode establish?
Part 02 can use short pseudocode to expose the responsibility order:
def handle_agent_request(request):
principal = request_boundary.admit(request)
contract = contracts.resolve(request, principal)
policy = policies.resolve_effective(contract, principal)
run = run_store.start(contract, policy)
while not run.is_terminal:
step = controller.next_step(run)
if step.kind == "model":
event = model_adapter.invoke(context_builder.build(run))
elif step.kind == "capability":
grant = policy.authorise(step.operation, run)
event = capability_runtime.execute(step.operation, grant)
elif step.kind == "approval":
event = approval_gateway.request(step.operation, run)
else:
event = step.as_event()
evidence = verification.check(event, run, contract, policy)
run = run_store.commit_transition(run, event, evidence)
return delivery.from_committed_run(run)
It shows that:
- identity and scope are established before agent execution
- contract and effective policy are separate responsibilities
- the controller advances only committed run state
- a model proposal does not directly become tool execution
- approval is a state transition rather than a conversational “yes”
- verification evidence is committed with the transition
- delivery comes from a committed terminal state
It does not prove that:
- distributed locking, concurrency, and worker crashes are handled correctly
- side effects have idempotency, unknown-outcome reconciliation, and compensation
- streaming, approval expiry, cancellation, and reconnection semantics are correct
- authentication, tenant isolation, sandboxing, or secret boundaries are secure
- the example is suitable for production use
Code that looks plausible does not prove production readiness. Its proof boundary still has to be stated.
5. Verification and completion authority: the generator cannot approve itself
A model can produce a candidate answer, patch, or action plan. It should not also hold final pass authority.
Verification may combine:
- deterministic tests
- schema validation
- linting, type, and architecture checks
- citation and grounding checks
- permission and side-effect evidence
- browser or API journeys
- calibrated model-based evaluators
- human review for selected risk classes
A verifier need not be one central service, and it should not be treated as an unconditional sovereign.
A more precise model is a verification and completion gate:
- Verifiers produce and aggregate evidence.
- The task contract defines the criteria that must be met.
- Effective policy selects the applicable gates, thresholds, and human decisions.
- Completion authority accepts only a result that matches the current contract, policy, and state version.
A repairable failure should return more than false. It should identify:
- the failed criterion
- supporting evidence
- the permitted repair boundary
- whether retry, fallback, or escalation is allowed
OpenAI’s Harness Engineering article describes executable architecture constraints, feedback loops, and recurring scans as mechanisms for keeping an agent-generated codebase coherent. Their value lies in moving quality decisions away from model self-report and into observable controls.4
Part 10 will cover verifiers, quality gates, and evaluation. The placement required here is simpler: a candidate output must travel through an acceptance path independent of the generator before it becomes accepted completion.
6. Persistence and observability are cross-cutting responsibilities
Persistence is not a final dump into a database.
A harness may need to retain:
- canonical run state and its version
- transition events and event ordering
- checkpoints
- tool request/result pairs
- operation identifiers and side-effect reconciliation state
- policy decisions and approval records
- artefact, diff, and evidence references
- model, prompt, tool, retriever, and configuration versions
Observability answers a different set of questions:
- Which step became slow or expensive?
- Which policy version allowed the operation?
- What did the model see before a retry?
- Which tool changed external state?
- Why did verification fail?
- Can the trajectory be reconstructed or replayed?
Their data may overlap, but their purposes differ. Persistence supports consistency and recovery. Observability supports inspection, diagnosis, and operations.
“Log everything” is not a design. Sensitive fields need redaction, event schemas need versions, and traces need run, turn, tool-call, and operation identifiers that can be correlated. Otherwise the system merely produces a more expensive pile of unsearchable text.
The important order is:
Execute
→ record outcome
→ verify
→ commit state and evidence
→ deliver response or event
The system does not have to synchronously write every cold-data record before responding. It must complete the durable commit needed for recovery, deduplication, and evidence before it presents the new state as accepted.
The eight stages of an agent request

Figure 2-2 | An agent request is a sequence of identity, policy, state, execution, and evidence transitions, not a model call followed by a response.
A typical request can be described in eight stages:
- The client creates a request. It submits input, a thread reference, and client capabilities.
- The boundary admits it. The harness establishes identity, tenant, authorisation, schema, and capacity.
- The harness resolves the contract and effective policy, then starts the run. It fixes the objective, limits, versions, and correlation identifiers for this execution.
- Context is assembled. Instructions, history, run state, retrieved evidence, and visible capabilities are selected.
- The model performs inference. It produces a candidate output, tool request, or next-step proposal.
- The capability is authorised and executed. The harness validates the operation, enters an approval gate when required, executes it, and records the observation.
- The transition is verified and committed. The applicable gates run, evidence is stored, and the controller chooses continue, repair, retry, fallback, or stop.
- The terminal state is durably committed and delivered. The required state, artefacts, trace, and evidence are retained before the client receives a response or event update.
Not every request repeatedly traverses all eight stages. A read-only question may require one inference and verification pass. A longer task may cycle through stages four to seven many times.
For a RAG answer, a model requesting rag_search establishes only that it needs information. The harness still has to apply tenant filters, execute retrieval, retain source references, return the result to the model, and check the candidate answer for citation and grounding. Calling a search tool does not prove that the answer is grounded.
Control plane and data plane
Control plane and data plane describe responsibility, not mandatory microservices.
The data plane performs work
- model calls
- tool, command, and API execution
- workspace reads and writes
- RAG and database queries
- artefact generation
- test execution
The control plane decides how work may proceed
- identity, tenant, and effective policy
- task contract, priority, and admission
- budget, capacity, and cancellation
- canonical run state
- approval, escalation, and completion authority
- versioning, deployment, rollback, and kill controls
Both planes may live in one process. The distinction prevents a tool worker from quietly changing global policy and prevents a client button from bypassing server authority.
A scalable principle is:
Centralise invariants and authority while preserving local autonomy inside the boundary.
Architecture dependencies, tenant scope, required tests, and high-risk approval can be enforced centrally. The agent can still choose an algorithm, local refactoring path, and order of permitted tools. Controlling what must not be violated tends to age better than prescribing every implementation step.
Headless harness service: one execution core, several client surfaces

Figure 2-3 | Several clients share a harness service, agent core, and durable thread state through a stable bidirectional protocol.
When one agent has to appear in a CLI, IDE, desktop app, web app, and partner product, the quickest prototype is to connect every client to an agent SDK separately. Behaviour soon diverges:
- one client supports approval and another does not
- diff, progress, and tool events use different semantics
- each client assembles prompts or retains session state differently
- an agent-loop fix has to be repeated across products
A headless harness service places the execution core and durable state in a UI-independent runtime. Clients handle input, rendering, and interaction rather than becoming the sole authority for a long-running task.
CLI / IDE / Desktop / Web / Partner Client
↕
Stable bidirectional protocol
↕
Headless Harness Service
auth · thread manager · events
approvals · config · negotiation
↕
Agent Core Runtime
loop · context · tools · sandbox
↕
Durable Thread State / Event History
OpenAI’s Codex App Server is a concrete example. OpenAI describes Codex Web, the CLI, the IDE extension, and the desktop app as being powered by the same Codex harness. The App Server exposes a bidirectional JSON-RPC interface through which clients submit requests and receive many event updates; the server can also initiate an approval request and pause the turn until the client responds.3
The example also exposes an important nuance: sharing a harness does not require every client to use the same deployment arrangement. A local application may launch a child process. A web runtime may execute in a container. A client may temporarily retain an in-process integration. Thread identity, event lifecycle, approval, cancellation, version negotiation, and reconnection semantics are the properties that must remain coherent.
Headless is a logical boundary, not a synonym for remote. The harness service and agent core may run in one process if the client protocol and state authority remain explicit.
Composable harness stacks: composition is useful, duplicated authority is not
A production harness rarely comes from one product. A common stack might contain:
Requirement / Issue System
→ Task Runner
→ Orchestrator
→ Coding Agent
→ Sandbox / Workspace
→ Tool and Protocol Layer
Runtime state, memory, policy, observability, evaluation, and artefact storage may cross the stack.
The problem is not composition. It is overlapping authority:
| Conflict | Typical result |
|---|---|
| Double retry | The same side effect executes twice |
| Split-brain task state | The board, worker, and agent disagree about status |
| Duplicate memory | Runtime, project notes, and local memory retain different versions of a fact |
| Nested sandbox | Outer and inner mount, network, or permission policies conflict |
| Conflicting approval | UI approval bypasses an enterprise denial, or two gates return opposite decisions |
Every boundary between layers needs an integration contract covering:
- identity and tenant propagation
- operation and correlation identifiers
- payload and protocol versions
- error, retry, cancellation, and unknown-outcome semantics
- evidence, audit, and state reconciliation
- final authority for each responsibility
Before adding another component, ask:
Which specific failure mode returns if this component is removed?
If the team cannot answer, the new layer may be maintenance cost rather than control.
The agent ecosystem is not one product category

Figure 2-4 | Nine kinds of agent product address different failure layers. They are neither a maturity ladder nor direct competitors in one ranking.
The following nine categories are a working map for this series, not an industry standard or a permanent label. Mature products may span several categories.
| Category | Primary problem |
|---|---|
| Coding agent | Reads and changes code, uses tools, and delivers a patch or artefact |
| Agent runtime | Manages execution, events, and process lifecycle across turns or sessions |
| Harness framework | Supplies primitives for state, tools, checkpoints, policy, and subagents |
| Task runner | Turns an issue, ticket, or specification into a trackable work unit |
| Orchestrator | Manages multiple agents, resources, concurrency, isolation, and ownership |
| Full-lifecycle platform | Connects requirements, execution, verification, approval, deployment, and governance |
| Knowledge / memory layer | Governs cross-session knowledge, preferences, history, retrieval, and expiry |
| Requirements / specification layer | Converts human intent into executable and verifiable requirements |
| Standards / protocol layer | Defines interchange contracts across tools, clients, agents, or repositories |
The map helps locate the problem before choosing a product:
- MCP provides an interoperability contract; it does not automatically become an authorisation system
- a coding agent is not a durable runtime
- an orchestrator does not automatically solve memory governance
- a task runner is not a complete software-delivery lifecycle
- a full-lifecycle platform may exceed the needs of a reliable queue consumer
Locate the failure layer before comparing products. A precise score is not useful when the objects solve different problems.
Which desired state is the harness regulating?
Component presence does not prove harness effectiveness. The system also needs a defined desired state.
The Martin Fowler article distinguishes maintainability, architecture fitness, and behaviour harnesses in the context of coding agents.5 This series extends that map with reliability / operations and product quality / taste to cover a broader product and operational view. Those two additions are this article’s extension, not categories attributed to the original source.
| Regulation domain | Desired state | Common sensor |
|---|---|---|
| Maintainability | Duplication, complexity, dependency hygiene, and documentation drift remain controlled | Linters, static analysis, test-quality checks |
| Architecture fitness | Module direction, ownership, layering, and API boundaries remain valid | Architecture tests, dependency analysis |
| Behaviour | Acceptance criteria, user journeys, permissions, and business correctness hold | API, browser, and contract tests |
| Reliability / operations | Latency, errors, capacity, recovery, and data integrity remain within operational bounds | Runtime telemetry, SLOs, incident replay |
| Product quality / taste | Consistency, accessibility, design judgement, and writing voice meet defined principles | Calibrated rubrics, model evaluators, human sampling |
A harness does not have to cover every domain at once. Each selected domain should still answer:
- What is the desired state?
- Which failure modes matter most?
- Which guides and sensors can be deterministic?
- Which judgements require semantic evaluation or human sampling?
- Who holds final authority?
Without a defined desired state, more sensors cannot reliably prove that the system is correct.
Reviewing an agent architecture with this map
For a new agent system, work through these questions:
- Where is the request admitted? Who establishes identity, tenant, schema, and capacity?
- Where are the contract and effective policy? Can the objective, budget, tools, approval, and stop conditions be traced?
- Who owns each class of state? How are client, worker, external-system, and issue-tracker facts reconciled?
- Who advances state transitions? Which decisions remain deterministic and which may the model propose?
- Who authorises and executes side effects? How are operation identifiers, retry ownership, and unknown outcomes handled?
- Which evidence permits completion? How do contract, policy, verifiers, and human gates combine?
- How does the task survive disconnection or failure? Where are durable commit, checkpoints, reconnection, and replay?
- Do composed components duplicate authority? Are retry, memory, approval, workspace, and task-state owners explicit?
Concrete answers expose the real architecture. “The framework probably handles it” is a reason to inspect the actual state, policy, protocol, and evidence contracts, not to add another logo to the diagram.
From theory to implementation: Part 02 checklist
- The request boundary handles identity, tenant, schema, admission, and correlation identifiers.
- Task contract and effective policy are modelled separately, with traceable versions and decisions.
- Authority boundaries between run lifecycle, external side effects, and client projections are explicit.
- Model proposal, capability authorisation, execution, and completion acceptance are distinct transitions.
- Durable state and evidence are committed sufficiently for recovery and deduplication before delivery.
- The headless client protocol supports events, approval, cancellation, reconnection, and version negotiation.
- The composed stack has no double retry, split-brain state, conflicting approval, or duplicate memory authority.
- The team can name the desired state being regulated and the failure modes that remain uncovered.
Part 03 will move into the controller at the centre of this map and examine the agent loop, tool request/result pairing, streaming, approval, stopping conditions, and goal drift. Without the authority, state, and evidence boundaries established here, a loop merely amplifies existing ambiguity more quickly.
Footnotes
-
Anthropic, Building effective agents, 19 December 2024. ↩
-
OpenAI, Unrolling the Codex agent loop, 23 January 2026. ↩
-
OpenAI, Unlocking the Codex harness: how we built the App Server, 4 February 2026. ↩ ↩2
-
OpenAI, Harness engineering: leveraging Codex in an agent-first world, 11 February 2026. ↩
-
Birgitta Böckeler, MartinFowler.com, Harness engineering for coding agent users, 2 April 2026. ↩