- Gates compose in both single-agent mode and for orchestration workers. A
single-agent run reports
scope.kind = "single"; an orchestration worker reportsscope.kind = "worker". - Webhook routing works for unattended approvals.
- Conversational routing works for attended approvals over an open SSE stream. The AURA CLI in HTTP mode is the first attended client.
- Matching tool calls are blocked until the configured route approves them.
- Human denials are returned to the model as normal tool feedback, so the agent can explain the denial without treating it as a transport failure.
- Timeouts, cancellation, and webhook channel failures still fail closed as tool errors.
- Conversational HITL requires
stream=true; non-streaming requests are rejected because approval prompts are delivered over SSE. - Approval lifecycle events emit on streaming responses. Webhook emits
aura.approval_requestedandaura.approval_completed; conversational also emitsaura.approval_pendingwhile the tool call is parked.
Configure a webhook gate
Add a top-level[hitl] table and a required [hitl.route] table:
require_approval is a list of glob patterns matched against MCP tool names.
When an agent calls a matching tool, Aura requests approval through the
configured route before the MCP tool runs.
A tool is gated if it matches any pattern in the list, so pattern order does
not affect whether a tool is gated. To leave a tool ungated, do not list a
pattern that matches it. When more than one pattern matches, the first in config
order is reported as origin.matched_pattern in the webhook payload and SSE
events; that is the only effect of ordering.
The request_approval tool is never matched by these globs. It is excluded from
the gate so the agent can ask for approval without triggering the gate itself.
timeout_secs defaults to 300 for webhooks. If the webhook does not return a
decision before the timeout, the tool does not run.
Orchestration example
Webhook request
Aura sends a JSON request to the configured webhook URL. The request uses a flat wire shape withkind tags for scope and origin:
Webhook response
Approve the tool call:SSE lifecycle events
Approval routes emit lifecycle events on streaming responses. These events are emitted even whenAURA_CUSTOM_EVENTS=false because clients may need to react to
approval state.
aura.approval_requested includes decision_id, tool_name, origin, and
scope. aura.approval_pending is emitted only by the conversational route and
contains the attended prompt payload that an Aura-aware client renders before
posting a decision. aura.approval_completed includes decision_id, terminal
outcome, duration_ms, and scope. Outcome kinds are approved, denied,
timed_out, cancelled, and errored; errored means the approval channel
failed before a human decision was obtained.
Conversational route
Use conversational routing when the approver is present on the chat stream. The server parks the worker tool call, sendsaura.approval_pending over SSE, and
waits for a decision on the approval ingress endpoint:
stream=true. Aura rejects non-streaming requests for
conversational HITL because there is no channel for the pending approval prompt.
An attended client resolves a pending approval by POSTing the same decision shape
as a webhook response:
aura.approval_pending, prompts for approve/deny, and POSTs the decision back to
the server. One-shot CLI mode fails loud instead of prompting because it has no
interactive approval surface.
Webhook manual smoke test
Start a webhook service that accepts the request shape above and returns an approval response. Then run Aura with an orchestration config that uses:mock_tool (the tool name from the bundled math orchestration example config)
so the glob matches a tool the worker actually calls. Put the webhook on a
different port than the mock MCP server (9999) to avoid a collision.
Ask an orchestration worker to use the gated tool. An approval should let the
tool run. A denial with a custom reason should produce a successful blocked tool
result containing that reason.
Conversational manual smoke test
Run Aura with an orchestration config that usesmode = "conversational", a
route timeout shorter than [orchestration.timeouts].per_call_timeout_secs, and
at least one gated worker tool. Connect with the AURA CLI in HTTP mode and send a
query that forces the worker to call the gated tool.
Expected behavior:
- The CLI renders an approval prompt from
aura.approval_pending. - Approving the prompt POSTs to
/v1/approvals/{decision_id}and lets the tool run. - Denying the prompt POSTs the denial and returns blocked-action feedback to the worker.
Current limitations
- The webhook route is synchronous. Aura waits for the webhook response during the tool call.
- Conversational approvals are in-process only. The parked approval must be
resolved by the same server process that emitted
aura.approval_pending. - Durable approval parking and cross-pod resume are not implemented yet.
- Webhook egress has no built-in authentication layer. Put auth, signing, or network controls in front of the webhook service.

