Skip to main content

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

Governed calltr.result(resp)

Selected track

Passed

Typed signal
200 passthrough
Application behavior
Use the output as-is.
Next action
Continue the application flow.
PassedThe output is fine.200 passthrough
CorrectedSomething was off. Trinitite fixed it.200 + JSON Patch
BlockedSomething was dangerous. Trinitite stopped it.403 GOVERNANCE_BLOCKED
MaskedSensitive data was swapped for a token on the way out.masking hook in proxy
HiTLA human needs to look.pending review, SLA-clocked
FailedThe check itself broke.guardian error, surfaced

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

Selected field
violations
violations
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
mask
<TRT::pii_credit_card::…>

Outside your trust boundary

<TRT::pii_credit_card::…>

The external model sees and returns the token.

tr.unmask

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

PendingHeld

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.

pendingpendinghash-chained transition log

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:

  • enforce makes the governance decision part of the app path.
  • monitor records and evaluates without making the verdict binding.
  • sampled evaluates selected traffic after the fact.
  • continuous supports ongoing assurance over live activity.

Account capabilities and server permissions still decide which operations are available.

Where to go next