Approval patterns & one-time codes

Some calls should never run on an agent’s say-so alone. Refunding a large amount, deleting a bucket, sending a message on the company’s behalf — for those you want a person in the loop. Meandr’s third policy verdict, alongside allow and deny, is approve: a call that pauses mid-flight and waits for a human.

Pause, decide, then run — or don’t

When a policy returns approve, the proxy does not forward the call. It records a pending action, notifies the owner, and holds. From there exactly one of three things happens:

  • Approved — the call runs upstream, exactly as the agent asked, and the result comes back.
  • Denied — it never runs.
  • Timed out — the decision deadline passes with no answer, and again it never runs.

Deny and timeout are the same outcome from the upstream’s point of view: nothing reached it. And every one of those endings — approved, denied, expired — is written to the audit trail against the rule that asked for the decision. The record of “we held this, and here is what a human decided” is as much the point as the pause itself.

Because the original call was answered with “approval required” rather than a result, the agent needs a way to learn the outcome. Meandr injects a small meta-tool, _meandr_action_status, into every tool list; the agent polls it with the action’s id to see whether the owner approved, rejected, or is still deciding — and, once resolved, to receive the result.

Where the human is asked

How the request reaches a person is chosen per policy, in one of three presentation modes:

  • Offline — the default, and it works on every MCP client. The agent gets a clean error carrying a link to the dashboard, where the owner reviews and decides. Nothing special is required of the client.
  • Interactive (URL) — the agent shows the dashboard link natively as a prompt.
  • Interactive (form) — an approval form appears inline in the agent’s own UI, and the call’s stream is held open across the human’s wait.

Meandr auto-degrades gracefully: if a policy asks for an interactive form but the client cannot render one, it falls back to a URL prompt, and then to offline. The dashboard review-and-approve path is always available regardless of mode — and it is live today, with the logged-in reviewer’s own session standing as the record of who approved.

One-time codes: authorize and attribute at once

The offline dashboard loop answers “did a human decide?” cleanly, because the person is logged in. In-agent interactive approval raises a subtler question: when someone approves from inside a chat, who exactly was that, and were they allowed to?

The model Meandr uses to answer both at once is a one-time code. On an interactive approval, each configured approver is issued a unique single-use code by email. The approver enters just the code. Because it is unique to them, the code does double duty: it authorizes — only someone holding a valid code, issued only to seated approvers, can approve — and it attributes — the code maps back to a specific person, so the decision is signed. The code is single-use, expires with the action’s deadline, and the first approver to use one wins; the siblings are invalidated. A wrong or missing code resolves the action as unauthorized, and the call never runs.

To be precise about status: the offline dashboard approval loop is live now, and the in-agent one-time-code attribution is the near-term slice of that story. Think of “confirm with a one-time code” as the model the design is built to — the way an approver proves who they are inside the agent — rather than something to reach for in your chat window today.

Around the decision

Approvers sit in seats defined per policy or project, so only the right people are asked. Owners are notified over the channels they choose — in-app, email, SMS, push, or Slack — fanned out by the action’s priority. And a tenant-wide cap on pending actions keeps a runaway agent from flooding mailboxes with approvals faster than anyone could ever answer them.

To put this to work, add an approve rule in your first policy, decide which calls deserve it with argument-level matching, and see the wider frame in MCP governance.