Inspiration

You gave a coding agent a terminal. The thing you're actually afraid of is the one git push --force, rm -rf, or payment you never saw coming. Codex already asks before dangerous commands — but that prompt protects the moment and then scrolls out of the terminal. It's the same person, at the same keyboard, and nothing is left behind. We wanted the opposite: a different human, on a different device, deciding — and a permanent, verifiable record of every yes, every no, and every silence.

What it does

GreenTeamGo is a human approval gate for the Codex coding agent. Before a risky action, Codex calls the greenteamgo MCP tool request_approval and stops. A human approves or denies from a web inbox ("the phone"), and every decision becomes a receipt in a per-workspace chain:

  • Approve → sealed receipt, the action proceeds.
  • Deny → sealed receipt, handed back to Codex. Type a reason and Codex adapts to it (e.g. opens a PR instead of force-pushing) — or type nothing: the human owes the agent no explanation, and a bare "no" is sealed all the same.
  • Timeoutfail-closed. No decision by the deadline counts as a deny, and that expiry is itself sealed as a receipt. Silence is on the record too.

Each receipt is Ed25519-signed and hash-linked to the one before it. The chain is tamper-evident: anyone can detect alteration, deletion, or reordering offline with the greenteamgo-verify CLI — no server, no login required to check the math.

How we built it

A 7-package TypeScript monorepo (141 tests green):

  • core — RFC-0002 canonical JSON serialization + Ed25519 signing + the hash-linked receipt chain + the greenteamgo-verify CLI.
  • policy — versioned allow/deny/gate/challenge rules; safe actions auto-decide, only the rest page a human. Plus a natural-language→policy compiler authored by Codex (below).
  • identity — API keys, hashed (never plaintext), scoped.
  • api — the create → poll → decide lifecycle, with fail-closed expiry sealed into the chain.
  • mcp — the stdio MCP server (request_approval / get_decision / list_pending) with a fail-closed blocking poll.
  • notify + apps/console — the inbox API and the web approval page in one process.

How we use Codex and GPT-5.6 (both, meaningfully)

  • OpenAI Codex is governed and a co-author. A real Codex CLI v0.144.6 session reads AGENTS.md and fires mcp: greenteamgo/request_approval before a force-push — that transcript is the demo. A second real Codex session authored the natural-language policy compiler (packages/policy/src/nl-policy.ts), committed to the public repo. (Session ID: 019f84e0-1aa6-7802-99f1-a75678efce0d.) Codex both builds the product and is governed by it.
  • GPT-5.6 (gpt-5.6-luna) is the risk analyst at the gate. It writes the one-line, plain-English risk brief on every approval card — "Force-pushes local main over three remote commits, permanently discarding others' changes" — the assessment the human relies on to decide, and the engine behind the NL→policy compiler.

The one number (reproducible, committed to the repo, verifiable by anyone)

Out of 20 agent actions, policy auto-cleared 14 routine reads with no human involved. A person was asked about only the 6 that could do harm — and denied 2 outright: a force-push over main, and a $4,200 payment.

# Action Risk Decided by Outcome (from the receipt)
1–14 file_read / file_list low policy allow (auto, no human)
15 git_push --force-with-lease (feature) high human approve — "only my own commits."
16 db_migrate (additive, CONCURRENTLY) high human approve — "no data loss."
17 deploy to staging medium human approve — "smoke tests green."
18 shell_exec clean reinstall medium human approve — "reproducible."
19 git_push force-push over main critical human DENY"open a PR instead."
20 payment charge a card $4,200 critical human DENY"needs finance sign-off."

The 20-receipt chain and the workspace public key are committed to the repo. Re-verify in one command:

node packages/core/dist/cli.js receipts.json keys.json
# → OK: 20 receipt(s) verified — chain intact, signatures valid

Flip a single byte of any receipt's content and the same command turns red: receipt_hash mismatch — content was tampered.

Challenges we ran into (and what we learned)

- The sandbox is the enforcement story. On Windows, codex exec runs read-only — Codex could call our MCP tool but couldn't touch the filesystem. Frustrating, until we realized that's the point on camera: the OS sandbox denies by default, and the approval gate is the sole escalation path out of it. AGENTS.md tells Codex when to ask; it isn't the security boundary. Naming that honestly is stronger than pretending the gate is unbypassable.
- We caught our own overclaim. A draft said the GPT-5.6 risk summary was "sealed inside the receipt." It isn't — the receipt seals the decision and the human's reason. For an honesty-themed product, shipping that would have been fatal, so we cut it. GPT-5.6 is the analyst the human acts on; we don't dress it up as more.
- The metric has to match the artifact. Our first framing was a rounder "16 auto / 4 human." The committed chain honestly produced 14 / 6, so the copy matches the chain — because a judge can run the verifier and check.

Limitations (we name the sharp edge ourselves)

The signing key lives on the server today, so the chain is tamper-evident (anyone can detect alteration, deletion, or reordering after the fact) — but a fully compromised server could sign false history. Device-bound countersigning (the deciding human's own device co-signs each receipt) is on the roadmap. We say "tamper-evident," never "trustless."

What's next

RedTeamGo — the inbound half. Green gates the actions your agents take; Red screens the requests everyone else's agents send you; both write to one signed logbook.

Built With

Share this project:

Updates