Verdicts and modes
Read one verdict, then take one clear app action. The verdict text is always the source of truth.
Status: Beta Companion docs: Result · Human review · Masking
Six verdicts, six app paths
result.verdict uses one of six lowercase wire values:
passed · corrected · blocked · masked · hitl · failed
What you get back, one verdict, every call
tr.result(resp)Selected track
Passed
- Typed signal
- 200 passthrough
- Application behavior
- Use the output as-is.
- Next action
- Continue the application flow.
Use the value in code, not a display label:
if result.verdict == "passed":
use_response(result.body)
elif result.verdict == "corrected":
use_response(result.body)
record_patch(result.diff)
elif result.verdict == "blocked":
show_safe_fallback()
elif result.verdict == "masked":
keep_masked_text_outside_the_trust_boundary()
elif result.verdict == "hitl":
wait_for_review(result.review)
else: # failed
follow_error_policy()
governance_blocked may appear in the wrapped-response status path. It is not a
wire verdict. The result verdict is blocked.
Inspect the reason and evidence
The result carries common fields and optional context:
Governance result
One object, clear next steps
- Value
- []
- Use
- Policy findings with linked controls.
diff, violations, and compliance use empty collections when there is
nothing to report. Fields such as risk, retrieval, provenance, flow_id,
and receipt may be absent.
Call explain(). Do not read it as a property:
trace_response = result.explain()
if trace_response.ok:
print(trace_response.body.get("steps", []))
const traceResponse = await result.explain();
if (traceResponse.ok) {
console.log(traceResponse.body.steps ?? []);
}
The call needs a result ID and the SDK client attached by tr.result(...).
Corrected means keep moving
A corrected result can carry an RFC 6902 patch in result.diff. Your app can
use the governed response and keep the patch for review.
if result.verdict == "corrected":
for operation in result.diff:
print(operation["op"], operation["path"])
Masked means rehydrate later
Masking keeps the original value away from the provider. Rehydrate only inside your approved trust boundary.
Masked, swap the real values back
Inside your trust boundary
card 4242…4242<TRT::pii_credit_card::…>Outside your trust boundary
<TRT::pii_credit_card::…>The external model sees and returns the token.
Boundary crossing
<TRT::pii_credit_card::…>The proxy swaps the real value for a reversible token on the way out.
The vault gates rehydration to a trust context. A browser or downstream webhook never gets the raw value.
if result.verdict == "masked" and result.flow_id:
masked_text = result.body["choices"][0]["message"]["content"]
unmask_response = result.unmask(masked_text)
if unmask_response.ok:
internal_text = unmask_response.body["text"]
Output governance does not rehydrate content automatically. In TypeScript,
await result.unmask(maskedText) returns the response.
hitl means pause for a person
A hitl result can carry result.review. Keep the app flow held until that
review reaches a decision.
HiTL, close the review loop
r.review, SLA-clocked
The application flow waits for approved, rejected, escalated, or expired.
Choose a transition
Current review state
Pending
A pending review request was created.
The reviewer identity is resolved server-side from the auth context. The actor on a decision cannot be spoofed.
if result.verdict == "hitl" and result.review is not None:
result.review.assign(reviewer="finance-oncall")
decision = result.review.approve(
reason="Order and refund limit were verified.",
)
Review operations require the matching server permissions. A valid API key alone does not grant permission to assign or decide a review.
Receipts are optional
Some results include a signed receipt handle. Check for it before reading or verifying it:
if result.receipt and result.receipt.get("id"):
verification = result.receipt.verify()
print(verification.body.get("verified"))
if (result.receipt?.get("id")) {
const verification = await result.receipt.verify();
console.log(verification.body.verified);
}
Receipt verification uses the public verification endpoint without your bearer token.
Choose how governance runs
The four modes, settable at baseline, scope, asset, or call
Blocks?
Yes, the verdict is binding
Evidence
Inline verdicts and the full closed loop
Pick it for
Production, the default
Your org sets its governance mode in the control plane. The SDK reads it and reconciles. The org setting wins.
Set the mode on the baseline or the supported scoped call surface:
enforcemakes the governance decision part of the app path.monitorrecords and evaluates without making the verdict binding.sampledevaluates selected traffic after the fact.continuoussupports ongoing assurance over live activity.
Account capabilities and server permissions still decide which operations are available.
Where to go next
- The closed loop turns reviewed results into repeatable checks.
- Human review covers the full review lifecycle.
- Receipts shows verification and graph access.