Greenlight Console: Every Write Goes Through a Human
Every write operation pauses on an in-chat approval card and runs only via a single-use, argument-bound token minted by a human click

- Open-source project
- AI Agents
- Remote
- August 16, 2026
Screenshots

The image could not be loaded.

The image could not be loaded.

The image could not be loaded.
The problem
An agent that can call tools is an agent that can change data. The moment an agent gets access to write operations — refunds, order changes, customer updates — the real question is no longer “is the model smart enough” but “who approves its writes, and where is the record?”. Most chat consoles for agents answer that by not answering: tool calls hide behind the final text.
What we built
A streaming chat console for an MCP agent, the client-side counterpart to the
mcp-guarded-tools server. The agent
works through four guarded meta-tools — search_tools, describe_tool, invoke_tool,
confirm_action — and every tool call renders as an inspectable card: the exact
arguments, the raw result, the latency, and which guardrails ran.
When the agent attempts a write, the guardrail chain denies it with
CONFIRMATION_REQUIRED and an approval card physically replaces the composer — the
operator cannot type past it; Approve and Deny are the only exits. One click on Approve
mints a single-use, argument-bound token via confirm_action, and the paused loop
resumes. The /audit page shows the server’s append-only JSONL log, with PII-redaction
chips on arguments that contained personal data.
Engineering decisions
Approval timeouts fail closed. An unanswered approval is treated as a denial; silence never executes a write.
Provenance is read off the surface color. Human messages white, agent text mint, tool plumbing backstage grey, blocked state amber — authorship is legible at a glance without reading a label, and every chromatic status is paired with a glyph or text.
The agent loop is provider-agnostic. The default provider is a deterministic scripted mock, so the whole console — including the refund scenario that triggers the gate — runs offline with zero API keys. A live provider (DeepSeek) is optional.
The measured results
Two offline benches run against a real spawned server. The token bench shows a mixed result and keeps it mixed: on the read scenario the four-meta-tool facade wins decisively (2,382 vs 6,360 cumulative prompt tokens); on the refund scenario it loses (7,179 vs 6,380) because discovery, the denial, and the confirm-and-retry add four extra rounds that get re-billed too. The TTFT bench shows single-digit-millisecond plumbing latency (p50 2.6–4.9 ms) — in live mode those milliseconds vanish under model latency; the point is the governance layer is not where the time goes. Both are demonstration numbers from the mock provider, not production measurements.
Running it
npm ci && npm run demo, open http://localhost:3000 — sixty seconds, no keys, no
database. Click the refund scenario chip, watch the agent discover tools and then stop at
the gate, then approve or deny it. Reproduce the benches with npm run bench:tokens and
npm run bench:ttft.
Does your team face a similar problem?
Tell us about the workflow and its constraints. We start with a scope we can describe and verify.


