Get release news

Approvals

Named calls that pass through the gate wait for your yes.

If you give your agent tools that pay, send or delete, name one in the Agentfile and its calls that pass through the gate wait for a yes.

How it works

  1. 01

    Name the tool.

    Put the exact MCP tool name under require_approval_for, with enabled: true and an approver_pubkey.

    human_gates:
      enabled: true
      require_approval_for: [pay_invoice]
      approver_pubkey: did:key:z6Mk…  # constle webhook-keygen
      on_timeout: abort  # the default
  2. 02

    The call waits at the gate.

    You see the exact call and its arguments. At the terminal, arguments too large to show can only be denied.

  3. 03

    Answer it.

    Say yes at your terminal, or send a signed decision from your own endpoint. Both wait at once, and the first answer wins.

  4. 04

    No answer.

    By default, no answer in five minutes means the call is refused and the run stops.

A signed yes you can check later.

A signed approval is bound to the exact call it answers, so it can’t be replayed onto another one. With an identity, approvals are kept in the signed log, and constle audit verify re-checks every signed decision offline.

Terminal approvals are recorded too, but they are not signed.

Sample decisions, signed and checked here with Ed25519subject_digest: SHA-256 of the sample arguments

    Why it lives outside the agent.

    Constle never passes the approver’s signing key into the sandbox, and you give it to whoever runs the decision endpoint. A decision that fails verification is a denial.

    Where it stops.

    Gates match MCP tool names exactly, once you turn them on. Traffic to hosts you allow isn’t gated. If an allowed host shares a server with an MCP server, a request can reach that MCP server past the gate, with no approval.

    A terminal answer is unsigned, and a line typed ahead can answer a later prompt. There is one approver per agent.

    Can the agent approve its own call?

    Constle never passes the approver’s key into the sandbox, and a decision that doesn’t verify is a denial. A terminal answer comes from whoever is at the terminal.

    Can I approve without sitting at the terminal?

    Yes, if you run your own decision endpoint, which sends a signed decision.

    What if nobody answers?

    By default, no answer means no, so the call is refused and the run stops. With on_timeout: proceed, it is forwarded unapproved.

    Can I gate on the arguments?

    No. Gates match the tool name, and you see the arguments when you decide. At the terminal, arguments too large to show can only be denied.

    Does it gate actions that aren’t MCP tool calls?

    No. Pair gates with a short allowed_hosts list and a tool allowlist.

    The current source and its signed releases aren’t public yet.