02

The Coding Agent Loop and Its Sandbox

Let the agent plan, edit, and test Workboard while the runtime controls every capability, limit, and irreversible effect.

From code generation to a controlled agent

A code generator produces a proposal; a coding agent repeatedly observes a repository, chooses an action, invokes a tool, and uses the result to choose the next action. The useful feedback loop also creates risk, because one mistaken observation or injected instruction can influence many later actions.

Control belongs in the orchestration runtime, the ordinary software that calls the model and executes its requested tools. The model may propose a file read, patch, test, or package lookup, but the runtime validates the request against a policy before anything happens. This is policy enforcement outside the model: natural-language instructions guide behaviour, while code-enforced capabilities provide the security boundary.

The objective is not unlimited autonomy. Workboard’s first implementation goal is narrow: an active editor can create a todo and mark it complete, with the tenant and state invariants from the executable specification preserved. The agent receives only the repository, a disposable test environment, approved documentation sources, and the tools necessary to produce evidence for that slice.

Stopping is a feature. A controlled agent can return “acceptance case not satisfied after four attempts” with its trace intact. An uncontrolled agent can keep changing unrelated code until one signal turns green, spend without limit, or weaken the very check it is meant to satisfy.

Define the tool contract

A tool contract gives each callable capability a name, typed input, validated output, side-effect class, timeout, and authorization rule. It matters because a vague “shell access” tool hides many distinct powers, while a narrow contract lets the runtime allow a read and deny a deployment with the same confidence as any other programmatic policy.

A compact Workboard manifest could look like this. SHA-256 is a cryptographic digest used here to identify exact file content:

tools:
  - name: read_file
    input: { path: workspace_relative_path }
    output: { content: string, sha256: string }
    sideEffect: none
    timeoutMs: 2000
  - name: apply_patch
    input: { patch: unified_diff, expectedBaseSha: sha256 }
    output: { changedFiles: string_list, newSha: sha256 }
    sideEffect: workspace_write
    timeoutMs: 5000
  - name: run_check
    input: { checkId: approved_check, idempotencyKey: string }
    output: { exitCode: integer, artifactUri: string, durationMs: integer }
    sideEffect: sandbox_process
    timeoutMs: 120000
  - name: request_approval
    input: { action: string, reason: string, evidenceUris: string_list }
    output: { decision: approved_or_rejected, approver: string }
    sideEffect: none
    timeoutMs: 86400000

The agent selects checkId: unit.todo-transition; it does not supply arbitrary shell text. The runtime maps that identifier to a pinned command and environment. File paths are normalized, resolved under the workspace root, and checked again after resolution so forms such as parent-directory segments or symbolic links cannot escape the boundary.

Outputs need schemas too. A tool failure must be a structured result with an error class, retryability, and artifact address, not an unbounded terminal transcript that the model may misread. Treat tool output as untrusted data: a source file, test fixture, dependency message, or web page can contain prompt injection, text crafted to make the model ignore its policy. The runtime never turns such text into new authority.

Isolate execution in a least-privilege sandbox

A sandbox is an isolated execution environment designed to limit what untrusted or generated code can read, modify, contact, and consume. Least privilege means granting only the capabilities needed for the current task, for only as long as needed.

For Workboard, create an ephemeral sandbox from a pinned base image. Mount the repository as a copy-on-write workspace, which allows local changes without changing the host checkout. Supply synthetic tenants and todos, not production data. Give the process a non-root user, a read-only operating-system filesystem, a small writable temporary directory, and explicit central processing unit (CPU), memory, process, disk, and wall-clock limits.

Network access is denied by default. If the build genuinely needs a registry or documentation site, use a controlled proxy that allowlists protocol, port, and hostname, resolves and checks the destination again when connecting, rejects redirects to unapproved or private addresses, limits response size, and logs the request. A hostname check alone is not a boundary because name resolution and redirects can point somewhere different later. Cloud metadata endpoints, loopback, link-local and internal address ranges, production databases, deployment application programming interfaces (APIs), secret stores, email systems, and source-control write APIs stay unreachable. Credentials are short-lived and scoped to the approved read or artifact-write operation.

Isolation reduces blast radius; it is not proof that hostile code is harmless. Sandbox escapes, malicious dependencies, resource-exhaustion attacks, and data encoded into permitted traffic remain residual risks. Defense in depth adds a patched host, process isolation, syscall and network policies, content scanning, audit logs, and a disposable environment that is destroyed after evidence is exported.

Run the plan–patch–test–observe loop

The core workflow alternates reasoning with small, externally checked actions. A patch is an explicit set of file changes, and an observation is the structured result of a tool call rather than the model’s prediction of what probably happened.

Start by pinning a goal, acceptance-case identifiers, allowed paths, and required gates. The agent inspects the smallest relevant files, writes a plan with success checks, and applies one coherent patch. It then runs the cheapest relevant deterministic check. The runtime records the patch hash and exact command before returning the exit code and artifact URI to the model.

If a check fails, the agent must diagnose from the evidence, not merely rewrite until the message disappears. It may inspect the failure, state a root-cause hypothesis, patch the source, and rerun the same check. It must not delete an assertion, widen a tenant predicate, add an ignore directive, or replace a deterministic oracle with its own judgement unless the authorized human changes the specification.

A simplified controller is ordinary code:

while (!state.acceptanceMet && state.stepsUsed < limits.maxSteps) {
  const proposal = await model.propose(state.visibleContext);
  const validated = policy.validate(proposal, state.capabilities);
  const observation = await tools.execute(validated);
  state = ledger.append(state, observation);
}

if (!state.acceptanceMet) {
  return escalation.withTrace(state);
}

The model does not set acceptanceMet. The runtime derives it from named gate results attached to the current patch and clean environment. A stale passing test from an earlier commit cannot close the loop.

Bound retries, time, cost, and side effects

Budgets make an agent loop predictably finite. A budget is a runtime-enforced limit on steps, retries, elapsed time, model tokens, tool cost, changed scope, or side effects; exceeding any hard limit stops the run and preserves evidence for escalation.

An initial Workboard configuration might be:

runBudget:
  maxModelSteps: 24
  maxPatchAttemptsPerGate: 4
  maxElapsedMinutes: 30
  maxChangedFiles: 12
  maxAddedDependencies: 1
  maxToolCostUsd: 4.00
  maxParallelProcesses: 2
  stopOnRepeatedFailureFingerprint: 2

A failure fingerprint is a stable classification derived from the gate, error type, and relevant location. Seeing the same fingerprint twice after purported fixes suggests the hypothesis is wrong; the run should stop or broaden diagnosis, not spend eight more attempts making cosmetic edits.

Retries apply only to operations classified as transient and safe. A read that times out can be retried. A package download can be retried against the same pinned digest. A write must carry an idempotency key, a stable operation identifier that lets the receiver return the original result instead of applying the effect twice. Workboard could derive todo-create:tenant-alpha:request-8721 from the acceptance run and preserve it across a network retry.

Side-effect budgets are explicit: the agent may change only approved workspace paths, create only synthetic data, and invoke only allowlisted checks. Adding a dependency, changing authentication configuration, deleting a migration, or touching deployment files consumes a separate capability and may be forbidden for this goal even if the total file count remains below the numeric cap.

Require approval for irreversible actions

Human approval is a control for actions whose consequences are difficult to undo, externally visible, privileged, costly, or legally significant. The approver receives the proposed action and evidence; approval is specific, time-bound, and single-use rather than a general instruction to “do whatever is needed.”

Reversible sandbox operations such as reading source, applying a local patch, creating synthetic fixtures, and running tests can proceed within policy. The following require a separate approval capability: publishing a package, merging protected code, deploying, changing production configuration, rotating a real secret, modifying a database schema with destructive effects, deleting data, sending external messages, or spending above the approved budget.

The model must never receive the production credential after approval. A trusted broker performs the exact approved operation and returns a receipt. This prevents an approval for one deployment from becoming reusable authority for an unrelated command. If action classification is missing or ambiguous, the fail-closed result is to stop.

Approval does not transfer responsibility to the approver blindly. The request should include the diff or artifact digest, relevant gate results, target environment, rollback method, expected impact, and reason the action cannot remain in the sandbox. An incomplete request is not approvable evidence.

Ship the first tracer-bullet slice

A tracer bullet is a thin end-to-end implementation that crosses the real architectural layers and produces observable evidence. Unlike a disposable prototype, it follows the intended production shape while implementing only one narrow behaviour.

For Workboard, the slice is “create and complete a todo” for one active editor in synthetic Tenant Alpha. The agent adds the domain transition, tenant-scoped repository operation, API handlers, minimal dashboard controls, and tests. It does not add organization sign-on, sharing links, notifications, analytics, or a design-system rewrite.

The execution trace should resemble this:

StepAllowed actionObservation and decision
1Read product brief and acceptance casesScope fixed to WB-TODO-001 and WB-TODO-002
2Inspect existing domain, API, persistence, and UI seamsPlan names exact files and invariants
3Patch domain transition and unit testUnit gate fails on retry behaviour
4Fix completion idempotencyUnit gate passes for current patch hash
5Add tenant-scoped API and integration testIntegration gate proves persisted tenant key
6Add create/complete controls and browser testBrowser gate proves visible state change
7Run the required clean-environment gatesEvidence records attached to the commit
8StopRelease remains a separate approval decision

This trace is valuable even if the run fails. It shows which capabilities were exercised, which evidence exists, where a hypothesis changed, and whether the agent respected its scope. The result is a reviewable software change, not just a final answer claiming success.

Further reading

These official sources describe secure software practices and agent-specific threat classes that motivate external policy enforcement, isolation, and evidence. The versions and status below were checked on 2026-07-26.

Key takeaways

This section compresses the controlled-agent design into rules that can be enforced by an ordinary runtime. The model proposes useful work; typed tools, capabilities, budgets, gates, and approvals decide what can actually happen.

  • Give the coding agent a narrow acceptance-backed goal, not general authority over a repository or environment.
  • Put policy enforcement in the runtime; a prompt is guidance, not a security boundary.
  • Define typed inputs, outputs, side-effect classes, timeouts, and authorization for every tool.
  • Treat all tool output as untrusted data and prevent prompt-injected text from granting capabilities.
  • Run generated code in an ephemeral least-privilege sandbox with synthetic data, bounded resources, and deny-by-default networking.
  • Alternate small patches with independent deterministic checks, and bind every result to the current patch hash.
  • Enforce hard budgets for steps, retries, time, cost, scope, dependencies, and processes.
  • Preserve idempotency keys across retries so one logical Workboard action produces one logical effect.
  • Require narrow, single-use approval for irreversible or privileged actions and keep production credentials in a broker.
  • Use the tracer-bullet trace as evidence of both software behaviour and agent-policy compliance.

Checklist

Use this checklist before allowing a coding agent to implement even a small Workboard slice. A checked control should exist in runtime configuration, tool schemas, a capability policy, or an inspectable trace.

  • [ ] The goal names acceptance-case identifiers, allowed paths, and required evidence.
  • [ ] Every tool has typed input and output, a side-effect class, timeout, and authorization rule.
  • [ ] Arbitrary command text is replaced by approved check identifiers wherever practical.
  • [ ] Workspace paths are normalized and resolved beneath the permitted root.
  • [ ] Tool output is handled as untrusted data rather than privileged instruction.
  • [ ] The sandbox is ephemeral, non-root, resource-limited, and supplied only synthetic data.
  • [ ] Network access is denied by default and production systems are unreachable.
  • [ ] Model steps, retries, elapsed time, cost, changed files, dependencies, and processes have hard limits.
  • [ ] Retried write operations preserve a stable idempotency key.
  • [ ] Repeated failure fingerprints stop or escalate instead of causing an endless loop.
  • [ ] Irreversible actions require scoped, time-bound, single-use human approval through a trusted broker.
  • [ ] The tracer-bullet trace binds patches, gate outputs, artifacts, and stop reasons to the exact run.