writing
From Browser Tool to Governed Workflow
Moving agent policy from client state to a durable server control plane changes what a tool demo can prove.
Moving policy from the browser to the server changed the claim Runbook Relay could support.
The first version demonstrated a useful interaction pattern. A browser agent could inspect an incident, compare predefined mitigations, stage one, and attempt execution. The page kept approval visible and blocked the negative path.
That proved the shape of the workflow. It did not prove a durable control boundary. The same client state rendered the interface and decided whether execution was allowed. Reloading the page erased the evidence. A stale or competing request had no durable resource version to check. An exact retry could not return a stored result.
A governed workflow needs stronger answers.
The page should not be the policy authority
WebMCP makes an operation explicit. It gives the page a named tool, a description, a bounded input schema, and a structured result. Those properties make discovery and testing easier.
They do not grant authorization.
A tool description that says “human approval required” is guidance for the model. A destructive annotation is useful metadata for the client. The service performing the action still has to reject an unapproved request.
Runbook Relay now routes native WebMCP calls, its labeled simulator, and human page controls through one same-origin server API. React renders the returned snapshot. It no longer owns the policy decision.
That separation creates a useful invariant:
Every interface can request a transition. Only the control plane can commit it.
Approval should name the exact action
A Boolean such as approved: true leaves too much unresolved.
Which action did the person approve? Which parameters? Which version of the incident? How long should that decision remain valid? Can another session reuse it? Did an earlier execution already consume it?
The server now binds approval to:
- a server-issued session identity;
- the incident and catalog mitigation;
- a SHA-256 action digest;
- the current resource version;
- a five-minute expiry; and
- a consumption timestamp.
Staging a mitigation increments the resource version. The server calculates the action digest from the incident ID, mitigation ID, and new version. It also derives an idempotency key from the session and digest.
The page sends the digest and version back when the operator approves. Execution has to present the same digest, version, and idempotency key. The server checks that the approval belongs to the same session, remains active, and has not been consumed.
If any value changed, execution fails closed.
Retries need a policy result
Retries are normal in distributed systems. They become dangerous when the operation is consequential and the caller cannot tell whether the first request completed.
The weak response is to tell the agent, “Do not call this twice.” The stronger response is to make a retry safe.
Runbook Relay assigns one execution record to each session-specific idempotency key. The first allowed request stores the result. Repeating the exact action returns that record without applying the synthetic effect again. Reusing the key with another action digest is a policy conflict.
The distinction matters:
| Request | Control decision |
|---|---|
| First matching request with active approval | Execute once and store the result |
| Exact retry | Return the stored result |
| Same key, different action | Block as an idempotency conflict |
| Old digest or resource version | Block as stale state |
| Expired or consumed approval | Block at the approval boundary |
The model does not decide which case applies. Durable records do.
Concurrency should not create fictional evidence
An audit trail can still mislead if a stale request appends a receipt after losing the state race.
Each Runbook Relay mutation uses compare-and-swap conditions over the resource version and current receipt-chain head. The receipt insert is also conditional on the new head. A request that does not win the state transition cannot leave behind a receipt claiming that it did.
Approval insertion uses the same pattern. Execution also requires the staged digest, version, idempotency key, unconsumed approval, expiry, session identity, and prior receipt head to match.
This is not a general transaction framework. It is a compact demonstration of a larger rule: the evidence record and the state transition need the same concurrency boundary.
Receipts should be verifiable, not only visible
Visible receipts help a reviewer compare what the model says with what the application recorded. Durability makes that evidence survive a reload. Hash linkage adds an integrity check.
Each receipt hash covers canonical JSON containing:
- session, event, tool, caller channel, and identity;
- input, result, outcome, and detail;
- action digest and resource version;
- previous receipt hash; and
- timestamp.
The snapshot API returns the latest 100 receipts plus one anchor when the chain is longer. It recomputes content hashes and verifies the links in that returned segment. The response reports the total receipt count, returned count, truncation state, head, and verification result.
That detects modification inside the segment. It is not a signed audit log or independent transparency system. Production evidence would need a trusted identity, retention controls, independent anchoring, redaction, and access monitoring.
“Human approval” still needs an honest boundary
The demo now issues a random 256-bit session cookie and stores only a SHA-256-derived key. The cookie is HttpOnly, SameSite=Strict, and Secure on HTTPS. State-changing requests require the exact same origin and JSON content type. Worker responses deny framing.
These controls isolate browser sessions and make cross-site misuse harder. They do not authenticate an employee or prove that a human initiated the page click.
The term “human approval” describes the intended interaction and the absence of an agent-callable approval tool. A browser agent with general page-control capability could still press the approval button. A production workflow should use organization identity, explicit authorization policy, and strong confirmation for consequential actions.
That limitation does not weaken the implementation evidence. It defines it.
The evaluation also needs a control boundary
A deterministic test can prove that code rejects an expired approval. It cannot prove that a model selects the right tool across realistic requests.
Runbook Relay now includes 50 versioned tasks across observation, comparison, staging, unauthorized execution, approved execution, reset, and out-of-scope requests. Eighteen tasks are adversarial. The live runner requires a pinned model and current pricing inputs, then captures:
- complete tool traces and results;
- task and policy grades;
- provider request IDs;
- end-to-end latency;
- input and output tokens;
- estimated cost; and
- a human-label template for response quality and failure taxonomy.
No API key has been supplied. The suite has not run. The repository can claim a tested evaluation contract, not a model success rate.
That is the same control principle applied to public evidence: a result should not exist until the system that produces and reviews it has actually run.
What the project proves now
Runbook Relay remains a synthetic reference application. It changes no production system.
It now supports a stronger and more useful claim: a browser-agent workflow can keep one visible human interface while a durable server control plane enforces scoped approval, stale-state checks, idempotency, replay protection, concurrency guards, and hash-linked receipts.
The remaining gaps are explicit. Enterprise identity, strong human confirmation, real infrastructure authorization, independent audit anchoring, operational recovery, and live-model evidence still require separate work.
That is the difference between a smooth tool demo and a governed workflow. The interface makes the action available. The control plane decides whether it happens. The evidence shows which decision won.