Concepts
Decision Outcomes
approve, block, escalate, retry, request_evidence, and pending outcomes.
Decision Outcomes
Overview
AgentTrust returns one of six governance decisions for every agent execution: approve, retry, request_evidence, escalate, block, or pending. Each outcome drives different SDK behavior and operator workflows.
Why It Matters
Your application must handle each outcome correctly — especially block (which can raise BlockedError) and escalate (which routes to human reviewers).
Prerequisites
- How It Works
- Gateway or embedded mode running
Step-by-Step Guide
Outcome reference
| Outcome | Meaning | SDK default | Operator action |
|---|---|---|---|
approve | Output passes all checks | Return output | None |
retry | Output may be improvable | Return output — the SDK does not log or act on it | Consider re-prompting the agent |
request_evidence | Output needs supporting evidence | Return output; review queue | Human provides evidence |
escalate | High risk; human review required | Configurable block/allow | Review queue assignment |
block | Policy violation or critical risk | Raise BlockedError | Investigate and fix policy/agent |
pending | Not computed — the decision engine was tier-gated off | Return output | Get a key with the auto_decision capability (Free tier and above) |
Risk tiers
Risk tiers influence decision mapping:
| Tier | Typical trigger |
|---|---|
low | All checks pass, high confidence |
medium | Minor policy flags or moderate confidence |
high | Policy violations, low confidence, adversarial signals |
critical | Hard policy block, trust chain violation |
Configuring block behavior
from agentrust_sdk import harness
@harness(
block_on_block=True, # default True — raise BlockedError on `block`
block_on_review=False, # default False — also raise on escalate / request_evidence
)
def my_agent(user, input):
return {"result": "..."}There is no block_on_escalate parameter — escalation is covered by block_on_review.
Handling in direct client code
decision.reason is a single explanatory string. The list of failed checks lives on
validation.failures.
outcome = result.decision.outcome
if outcome == "block":
raise RuntimeError(f"Blocked: {result.decision.reason} — {result.validation.failures}")
elif outcome == "escalate":
notify_reviewer(result.envelope_id)
elif outcome == "retry":
return rerun_with_feedback(result.decision.reason)Examples
Payment agent — expected block:
@harness
def payment_agent(user, input):
return {"transfer": 100000, "currency": "USD"} # triggers financial policy
# Raises BlockedError if amount exceeds policy thresholdFAQ agent — expected approve:
@harness
def faq_agent(user, input):
return {"answer": "Our hours are 9am–5pm EST"}
# Returns normally with outcome=approveBest Practices
- Log
envelope_idwith every decision for audit correlation - Route
escalateandrequest_evidenceto your ticketing system via webhooks (Team+) - Use
block_on_review=Truefor high-stakes domains (finance, healthcare) soescalatealso halts the call - Do not treat
retryas automatic — implement explicit retry logic in your agent loop
Common Mistakes
- Ignoring
retryandrequest_evidence(they still return output, and the SDK logs nothing forretry) - Reading
pendingas "the judge is still working" — it means the decision engine was tier-gated off - Blocking all agents on any non-approve outcome in production (too aggressive)
- Not surfacing
decision.reasonandvalidation.failuresto operators for debugging
Troubleshooting
| Issue | Fix |
|---|---|
| Everything blocked | Review decision_thresholds.yaml and policy pack rules |
| Never blocks | block_on_block defaults to True — check instead that the gateway is reachable and AGENTRUST_FAILURE_MODE is not masking an outage |
Always pending | You are on OSS tier, or your key lacks auto_decision — the decision engine never ran. Run agentrust whoami. |