Skip to main content Molecule AI is now Enter OS →
Molecule AI
Blog

Engineering

Why every agent mode needs a gate-raising primitive: the create_approval incident

The org concierge needed management-mode approvals; we added governance before it became a standing admin credential.

By Molecules AI Engineering 4 min read

This is a post about a class of multi-agent failure that is easy to reason about in hindsight and surprisingly hard to anticipate in advance: what happens when an agent needs to raise a gate but has no primitive to do it?

The incident

The org concierge — the Molecule AI workspace that manages our own platform tenant — runs in management mode. Management mode gives it elevated tooling: it can list workspaces, inspect audit logs, mint tokens, surface pending approvals. What it couldn’t do was create one.

So when the CTO asked it to demonstrate raising a test approval, it improvised. It called set_workspace_secret — a gated operation that, by design, restarts the workspace when a secret changes. It called it on itself. The restart terminated the concierge mid-turn. Twice in the same day (Molecule AI core incident #2573). The first occurrence cost a 14-hour org-root outage.

The failure mode was not a bug in the concierge’s reasoning. The agent correctly identified that it needed to surface a user-facing gate; it had no tool to do that, so it found the nearest tool that produced a visible human-attention signal. That tool happened to be destructive.

The fix: create_approval in management mode

MCP server PR #62 added create_approval to management mode. The tool calls the platform’s requests endpoint with kind:"approval" and recipient_type:"user" via the management API path. The shape is identical to the workspace-mode tool — the only difference is the transport layer.

The PR was deliberate on one point: no decide_approval in management mode. Deciding is the human side of the gate. An agent should never hold both the ability to raise and the ability to resolve the same approval class — that collapses the gate to theater.

The follow-up (PR #63) caught a startup regression: PR #62 had registered create_request twice — once explicitly for management mode and once via registerRequestTools, which already registers it in both modes. The MCP SDK throws on duplicate tool names, so every management-mode boot died before serving initialize. The platform’s smoke gate caught it on first use; the fix drops the duplicate and lets requests.ts own the SSOT.

The unified requests system it runs on

create_approval is a thin shim over the unified requests subsystem, which was the larger RFC (molecule-mcp-server PRs #56 + #57).

Before the RFC, approvals were a parallel system — their own data model, their own MCP tools. After it, every approval is a request with kind=approval, and the agent-facing tools are:

| Tool | What it does | |---|---| | create_request | Raise a task or approval addressed to a user or peer agent | | list_inbox | See requests addressed to this agent (its incoming work queue) | | check_requests | Poll for responses to requests this agent raised (async pickup) | | respond_request | Resolve a request with done, rejected, or approved | | cancel_request | Cancel a pending request this agent owns |

The old create_approval / decide_approval / list_pending_approvals tools still work — they’re now shims that route to these endpoints with kind=approval set automatically. Existing agents don’t need to change.

The architectural lesson

The incident is a specific instance of a general pattern: agents invent solutions to unmet needs, and the solutions they invent are constrained by what tools are available. If the available tools are all gated-destructive operations, the agent’s improvisation will eventually touch one.

This shows up in practice whenever a role — here, management mode — gets a subset of tools without careful thought about which side-channel operations it can reach. The right fix is not a longer allowlist of banned actions. It is to ask: for every intent this agent might legitimately have, does it have a non-destructive primitive to express it?

For Molecule AI, the answer now is: yes. Every agent mode has create_request or create_approval. The human inbox gets the item. The agent waits. Nobody terminates.

If you’re building on Molecule AI today and your agent needs to surface a decision, use create_request (kind task or approval) or create_approval directly — both are available in workspace mode. If you’re running a management-mode concierge, update to MCP server v1.6.1 or later to get the fix. The molecule approvals management verb in the CLI surfaces the same inbox from the terminal.

Source: molecule-mcp-server PR #56, #57, #62, #63.