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

Step-by-Step Guide

Outcome reference

OutcomeMeaningSDK defaultOperator action
approveOutput passes all checksReturn outputNone
retryOutput may be improvableReturn output — the SDK does not log or act on itConsider re-prompting the agent
request_evidenceOutput needs supporting evidenceReturn output; review queueHuman provides evidence
escalateHigh risk; human review requiredConfigurable block/allowReview queue assignment
blockPolicy violation or critical riskRaise BlockedErrorInvestigate and fix policy/agent
pendingNot computed — the decision engine was tier-gated offReturn outputGet a key with the auto_decision capability (Free tier and above)

Risk tiers

Risk tiers influence decision mapping:

TierTypical trigger
lowAll checks pass, high confidence
mediumMinor policy flags or moderate confidence
highPolicy violations, low confidence, adversarial signals
criticalHard 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 threshold

FAQ agent — expected approve:

@harness
def faq_agent(user, input):
    return {"answer": "Our hours are 9am–5pm EST"}
# Returns normally with outcome=approve

Best Practices

  • Log envelope_id with every decision for audit correlation
  • Route escalate and request_evidence to your ticketing system via webhooks (Team+)
  • Use block_on_review=True for high-stakes domains (finance, healthcare) so escalate also halts the call
  • Do not treat retry as automatic — implement explicit retry logic in your agent loop

Common Mistakes

  • Ignoring retry and request_evidence (they still return output, and the SDK logs nothing for retry)
  • Reading pending as "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.reason and validation.failures to operators for debugging

Troubleshooting

IssueFix
Everything blockedReview decision_thresholds.yaml and policy pack rules
Never blocksblock_on_block defaults to True — check instead that the gateway is reachable and AGENTRUST_FAILURE_MODE is not masking an outage
Always pendingYou are on OSS tier, or your key lacks auto_decision — the decision engine never ran. Run agentrust whoami.