Docs Demo
How it works

Decision types

Every call produces exactly one decision. It always has the shape { decision, reason, ruleId } and is written to the audit log.

DecisionMeaningWhat the agent sees
ALLOWThe call passed policy and inspectors; the tool ran.The (scanned) tool result.
BLOCKPolicy violation, secret/PII, injection or loop. In the request phase the tool is not run. In the response phase (suspicious result) the tool already ran; only the result is withheld from the agent.A safe error message.
ESCALATEThe call awaits a human's approval (Slack). If approved it proceeds; if denied or timed out it becomes BLOCK.A result or an error depending on the outcome.
SHADOW_BLOCK"Would have been blocked" in shadow mode. The call is not stopped.The normal result.
SHADOW_ESCALATE"Would have gone to approval" in shadow mode. The call is not stopped.The normal result.

The decision object

{
  "decision": "BLOCK",
  "reason": "argument \"amount\" = 750 exceeds max 500",
  "ruleId": "issue_refund"
}

ruleId points at the rule that decided: usually the tool name, or a detector name such as loop-breaker, dlp_exfiltration, drip-exfiltration or ingress_prompt_injection.

How a blocked call reaches the agent

Through the MCP proxy the agent receives a standard tool error containing the reason. In the SDK an AvertGateSecurityError is thrown; with catchErrors: true it is returned as { error: "..." } instead (handy for feeding back into an LLM loop).