After this article: you should be able to trace a proposed tool call into a controlled action and explain the roles of tools, permission, sandbox, state, recovery, and observation.

Terminology note: vendors use “harness” at slightly different widths. This series uses it for the execution environment and controls outside the model but inside one run. The repeated control flow is introduced separately as the Agent Loop.

1. See how a proposal becomes a real action

1.1 First understand what a harness does

A harness is the software environment that lets a model use tools under explicit rules. It prepares the request, exposes available tools, checks arguments and permissions, runs actions in a limited environment, records what happened, and returns observations to the model.

Think of a workshop. The model is the worker deciding what to try. The harness supplies labeled tools, a protected workbench, safety rules, a logbook, and a way to resume after interruption. A more capable worker does not remove the need for the workshop.

1.2 Follow “run the payment tests” from words to evidence

When the model proposes a test command, the surrounding system has to complete a concrete sequence:

  1. Find the real test tool and its current interface.
  2. Check that the arguments are complete and valid.
  3. Decide whether this Agent may use it for this repository.
  4. Limit which files, processes, network locations, and credentials it can reach.
  5. Run the command with timeout and cancellation controls.
  6. Store large logs and return a useful result.
  7. Record enough state to explain or recover the action later.

If step 2 is missing, malformed input reaches the executor. If step 3 is missing, a prompt warning becomes the only permission boundary. If step 6 is missing, a huge log floods the next model request. Harness engineering is the design of this whole path, not merely a wrapper around an API call.

Put this Tool Call back into a complete run and a repeating chain appears: the harness prepares a request → the model proposes an action → the harness checks and executes it → the result becomes an observation → the observation enters the next request → the model decides again. The harness carries each action; the Agent Loop decides whether the chain needs another round.

2. Separate the parts of the action environment

2.1 Gather the seven steps into one runtime environment

Models are good at proposing plans under uncertainty. The runtime must contain uncertainty inside deterministic boundaries. Which tools are visible to the current role, whether arguments satisfy a schema, which paths are writable, which network destinations exist, and how results are serialized belong to policy and code—not to an improvised model decision.

A minimal harness only needs to prepare a request, expose tools, validate input and permission, execute within limits, and return results. A mature system adds a versioned tool registry, event records, progress observation, artifacts, and checkpoints for reproducibility and recovery. The table below puts both layers together for engineering review.

Layered harness providing request assembly, tools, permissions, sandbox, state, events, and recovery around the model
The model is a decision component, not the whole agent. The harness lets decisions touch the world safely.
Control surfaceFacts it ownsWhy the model cannot own them
Request assemblerModel, instructions, tools, context view, budgetsRequests must be reproducible and observable
Tool registryName, schema, capability, version, result typeThe model cannot invent real interfaces
Policy / permissionAllow, deny, ask, and scopeSafety boundaries need determinism
Sandbox / executorFiles, processes, network, and resource limitsPrompt text cannot isolate effects
State / transcriptRun state, events, result references, checkpointsRecovery and audit need durable facts
Observer / verifierProgress, metrics, and execution evidenceSelf-report cannot be the only truth

The harness records and exposes evidence. The agent loop decides whether this run should continue; evals decide whether evidence proves outcome quality across tasks and versions. A verifier may run inside the harness without owning product truth.

2.2 Pass one tool call through seven gates

A tool call is structured model output: a proposal. A robust harness does not map it directly to a function. It separates interpretation, authority, execution, and observation.

Seven tool execution gates: parse, resolve, validate, authorize, isolate, execute, and normalize
Each gate emits an explicit event, making failure a routable state rather than an ambiguous exception string.
  1. Parse: confirm the call is complete and belongs to the current request.
  2. Resolve: find the exact tool version in the current visible registry.
  3. Validate: check types, ranges, exclusions, and required fields.
  4. Authorize: combine actor, resource, action, and environment into allow / deny / ask.
  5. Isolate: create filesystem, process, network, and credential boundaries.
  6. Execute: manage timeout, cancellation, concurrency, retries, and idempotency keys.
  7. Normalize: turn stdout, structured results, errors, and artifacts into a stable observation.
async function dispatch(call, run) {
  const tool = registry.resolve(call.name, run.toolsetVersion)
  if (!tool) return observe("unknown_tool", call.id)

  const args = tool.schema.parse(call.arguments)
  const decision = policy.decide(run.actor, tool.capability, args)
  if (decision === "deny") return observe("denied", call.id)
  if (decision === "ask") return pauseForApproval(run, call)

  const box = await sandbox.open(tool.limits)
  events.append("tool.started", { runId: run.id, callId: call.id })
  try {
    const raw = await executor.run(tool, args, { sandbox: box })
    return normalize(raw, artifactStore)
  } finally {
    await box.close()
  }
}
Minimal dispatch: this handles one tool proposal; it does not own a while loop. Calling the model again belongs to the agent loop in Part 5.
{
  "call_id": "call_42",
  "tool": "run_tests@3",
  "arguments": { "target": "./payment", "mode": "read-write" },
  "policy": { "decision": "allow", "rule": "repo-test" },
  "sandbox": { "fs": "workspace", "network": "off", "timeout_s": 120 },
  "result": { "status": "failed", "exit_code": 1, "artifact_ref": "log://9f2" }
}
Shape-level example: bind decision, execution environment, and result evidence to one call id so an effect remains traceable.

The same call_id leaves three facts for different owners. The artifact store keeps the full log. An event or call ledger keeps states such as proposed, allowed, started, and completed. The model view receives only the observation needed for the next decision. During recovery, the runtime reads the ledger, reconciles it with the environment, and opens the artifact by reference when needed; chat text is not authoritative evidence that an effect did or did not happen.

2.3 Tool design shapes what the Agent can do

Part 2 covered the tool description the model sees and how it should choose. This part owns the registry, version, schema validator, authorization, dispatcher, and artifacts that decide whether execution can actually happen. More tools are not automatically better: overlapping write tools, a universal shell, and vague free-text arguments expand the action space and force the model to guess.

2.3.1 A good tool serves the model and the runtime

DimensionModel interfaceRuntime interface
SemanticsWhen to call and when not toCapability id and version
InputFew, clear fieldsStrict schema and normalization
OutputEnough to choose the next stepTyped result, artifact, and error class
EffectWhat will changePermission, idempotency, compensation, audit
CostWhen the call is worth makingTimeout, rate, token, and resource budgets

Do not dump large output back into context. Store full logs as artifacts and return a summary, critical errors, and a reference that can be paged later. This improves both context budget and recovery.

2.4 Permission to act is not permission to reach everything

Permission answers whether this actor may perform this action. The sandbox answers what the allowed action can actually reach. Permission to run tests does not imply access to the home directory. Permission to read a repository does not imply permission to transmit it to arbitrary network destinations. Both layers are required.

Harness safety layers for capability visibility, policy, human approval, sandbox limits, and audit evidence
Safety is not one deny button. It is a sequence that progressively narrows authority.
  • Capability scope: do not expose irrelevant tools to the model.
  • Policy decision: match actor, action, resource, and environment.
  • Human approval: pause only at high-risk or ambiguous boundaries and show an understandable diff.
  • Sandbox: limit blast radius with filesystem, network, process, and credential isolation.
  • Audit: record who proposed the effect, which rule allowed it, and what actually occurred.

3. Advanced: make real actions recoverable and traceable

3.1 After interruption, chat history alone cannot recover the work

Anthropic’s Managed agents treats a session as a stateful environment around the model, harness, and sandbox. Engineering still needs to distinguish UI conversation, model-visible messages, append-only events, external artifacts, checkpoints, and environment snapshots. They have different lifetimes and recovery roles.

Restarting by sending old chat back to a model is unsafe. The runtime must know which tool calls actually executed, which were in flight, how the workspace changed, whether approvals remain valid, and which external objects already exist. Deterministic records recover effects; the model should not infer them from prose.

tool.proposed → tool.validated → policy.allowed → tool.started
→ runtime.crashed → run.recovered → effect.reconciled
→ observation.ready
Recovery trace: if call_42 has started but not completed, the runtime first queries the environment. A read-only call may be replayed under limits; an idempotent write is reconciled first; a non-idempotent write with unknown state must block or escalate rather than execute again.

3.2 Both the user and the system need to see what happened

A final response and total token count are not enough to debug a harness. A run trace needs request assembly, model events, tool proposal, policy decision, sandbox execution, observation, checkpoint, and exit reason. Sensitive bodies can be redacted; control events cannot disappear.

  • Stable run, turn, and call ids join every event.
  • Record tool latency, queue time, retry, cancellation, and artifact size.
  • Separate model error, tool error, policy denial, environment failure, and user cancellation.
  • Retain the exit reason and unfinished work so the outer loop can decide safely.

4. Review the harness with six questions

Review questionIf unansweredRisk
Which capabilities can the model see now?No versioned registryCapability drift and wrong selection
Where are tool calls validated deterministically?The model self-checksInvalid arguments reach effects
Who owns authorization and isolation?Only prompt warnings existUnbounded blast radius
How are large results and secrets handled?Everything returns to contextDisclosure and window pollution
Which facts recover an interrupted process?Only chat is replayedDuplicate effects and false state
Does every exit have a machine-readable reason?Only final prose existsThe outer loop cannot take over safely

The harness turns “the model can think of it” into “the system can do it safely.” Next we enter the control flow that keeps advancing inside it: how an agent loop makes one run converge correctly.

Official sources

Further reading