- Get Started
← Back to Blog

Delegated Verification: How SENTINEL Gets FORGE to Run Code, Without Ever Touching FORGE's Workspace

A design for cross-workspace command execution that lets a reviewer agent verify code by asking for evidence — never by entering the workspace it's reviewing.

Christian Yemele · August 7, 2026 · 8 min read

The problem: a reviewer that can’t run the tests

SENTINEL’s job is to gate FORGE’s work at two points: reviewing PLAN.md before implementation starts, and reviewing the PR before it merges. Both of those reviews are, today, read-only — SENTINEL reads an artifact (a plan, a diff) and reasons about it.

That’s fine for “does this plan make sense” or “is this diff internally consistent.” It falls apart for a very ordinary question: does the code actually work? Answering that requires running something — cargo test, npm test, a lint pass, a build. And that command has to run somewhere with the repository checked out, which today means it has to run inside FORGE’s Coder workspace, not SENTINEL’s.

The naive fix — give SENTINEL shell access to FORGE’s workspace — was rejected for three reasons that all come back to the same principle: the reviewer must remain isolated from the thing it reviews.

The design that shipped instead: SENTINEL never enters FORGE’s workspace. It delegates. It sends FORGE a typed request — “run this command, tell me what happened” — and gets back a structured result. FORGE stays the only thing that touches its own filesystem. SENTINEL stays a pure reviewer, just one that can now ask for evidence instead of only reading claims.

Why A2A, and why not just reuse Redis

OpenFlows already has a cross-workspace coordination mechanism: the Redis SharedStore, accessed exclusively through openflows-harness. PLAN.md lives there as pair:{id}:plan; handoffs, PR info, and review verdicts all live there too. So the obvious question is: why introduce a second protocol (A2A) instead of just writing a “please run this command” key to Redis and polling for the answer?

The two mechanisms are solving genuinely different problems, and conflating them would have made both worse:

Redis SharedStoreA2A
NatureDurable artifact storeLive task/message exchange
Good at”What is the current plan?” “What did the review say?” — anything that should survive a restart and be replayed/audited”Go do this now, stream me progress, tell me when it’s done”
SemanticsPoll-and-readRequest/response with SSE streaming, cancellation, resubscribe-after-disconnect
EcosystemBespoke, tenant-namespaced keysStandard task lifecycle, Agent Cards, JSON-RPC methods with existing tooling

A verify request is fundamentally a task, not a fact. It has a lifecycle — submitted, running, producing incremental output, completing or timing out — that Redis’s plain-key model can express, but only by reinventing exactly what A2A already standardizes (task IDs, progress streaming, cancellation, resubscription). Doing that with hand-rolled Redis polling would have produced a bespoke pseudo-A2A with worse ergonomics and no compatible tooling. So the design draws a firm line:

Redis remains the single source of truth for durable artifacts. A2A is used only for live task exchange, and every terminal A2A result is mirrored into Redis before the task is acknowledged complete.

That second sentence matters as much as the first: A2A doesn’t get to be a second, competing source of truth. The moment a verify task finishes, its result is written to pair:{id}:verification in Redis — so even though the conversation happened over A2A, the record lives in the same durable store as everything else, replayable and auditable the same way a PR or a plan is.

Why a relay, not peer-to-peer

Given A2A for the live exchange, the next question is topology: does SENTINEL dial FORGE directly, or does something sit in between?

Coder workspaces are reliably good at making outbound connections and bad at accepting inbound ones — there’s no stable address for “the FORGE workspace for pair T-048” that SENTINEL could dial, short of wiring up coder_app URLs and a discovery mechanism for every pair. So the design puts a relay inside nexus, the existing control-plane workspace, and has both SENTINEL and FORGE open outbound connections to it. Nexus routes messages by (pair_id, role).

This isn’t just a networking convenience. It’s the enforcement point:

The alternative — SENTINEL and FORGE dialing each other directly once nexus hands out short-lived tokens — was considered and explicitly deferred. It solves nothing that the relay doesn’t already solve for v1, and it adds a token-exchange and NAT-traversal problem that isn’t worth taking on before the simpler design has been proven.

What actually gets sent

The whole capability rests on one task type: verify. It’s deliberately narrow — not “run any shell command,” but “run this specific, allowlisted command and tell me what happened”:

// SENTINEL → nexus → FORGE
{
  "task_type": "verify",
  "pair_id": "T-048",
  "verify": {
    "kind": "command",
    "cwd": "repo",
    "argv": ["cargo", "test", "--package", "foo"],
    "timeout_secs": 600,
    "expect": { "exit_code": 0 }
  }
}
// FORGE → nexus → SENTINEL, and mirrored to pair:T-048:verification
{
  "task_id": "…",
  "exit_code": 0,
  "duration_ms": 12843,
  "stdout_ref": "audit:a2a:{task_id}:stdout",
  "artifacts": [],
  "executor": { "role": "forge", "workspace": "forge-T-048" }
}

Everything about this shape is designed to be boring on purpose:

This is what makes the isolation argument actually hold up: SENTINEL isn’t gaining “run arbitrary code in FORGE’s workspace,” it’s gaining “ask FORGE to run one of a handful of pre-approved test/build commands.” The blast radius of a compromised or misbehaving SENTINEL is bounded by the allowlist nexus enforces, not by SENTINEL’s imagination.

Failure is the interesting part

A synchronous “run this and get a result” RPC is easy to design for the happy path. The reason this took real design work is the failure modes, because every one of them has a wrong answer that looks tempting:

None of these are exotic. They’re the ordinary failure modes of any distributed request/response system, and the design’s answer to all of them is the same instinct: when in doubt, don’t approve. That instinct is also, not coincidentally, the fix for the actual incident that motivated this work in the first place.

The other half of the fix: refusing to approve blind

This capability exists because of a real failure: a SENTINEL instance was asked to approve a planning gate for ticket T-048 and discovered it had no way to read PLAN.md or reach the ticketing tool at all — wrong environment, missing binary, empty workspace. Faced with that, the correct move is to say so and stop. verify delegation is the mechanism for one specific gap in that story (verifying code), but the general principle it’s built alongside is broader:

SENTINEL must hard-fail — never approve — when a required artifact is missing or unreadable.

This applies whether the missing thing is PLAN.md, a PR diff, or a verify result that never got persisted to Redis. The gate isn’t “approve unless something looks wrong.” It’s “approve only once the required evidence is actually in hand.” Everything else, including this whole A2A relay, exists to make sure that evidence can actually reach SENTINEL when it’s needed — not to give SENTINEL an excuse to approve without it.

What this deliberately doesn’t do yet

Where this fits in the bigger picture

Nothing about this changes the shape of the existing gated-phase state machine in openflows-harness (planningbuildingtestingreview_ready, with SENTINEL’s gate approve consuming a single-use approval token via Redis GETDEL). Delegated verification is additive: one more thing SENTINEL can ask for before it decides whether to call gate approve. The gate itself still lives entirely in Redis, still requires the SENTINEL role, and still can’t be bypassed by FORGE approving its own plan.

What changes is what “evidence” can mean. Before this, a SENTINEL review was necessarily an act of reading — a plan, a diff — and reasoning from prose. Now it can also be an act of asking the code to speak for itself, through a narrow, audited, allowlisted channel that never requires SENTINEL to leave the boundary of its own workspace.

Comments

Questions, feedback, or thoughts? Comment below and join the discussion on GitHub.