Did the task happen, or just get claimed?
Outcome and policy are graded from the trace and the system of record, never from words.
| kind | what it reads | example verdict |
|---|---|---|
| outcome | a composite over the sub-predicates below, as a met / of fraction | met 3 / of 3 → pass |
| tool_call | the ingested trace spans, never the transcript | issue_refund span present → pass |
| tool_result | a tool’s returned value, from the trace | refund result ok → pass |
| tool_error | a tool’s raised error, from the trace | charge raised timeout → fail |
| state | a state adapter snapshot: the system of record | balance shows the credit → pass |
| state_change | a before / after delta (mock adapter) | balance moved by the refund → pass |
| sequence | an ordered set of steps across tools | lookup before refund → pass |
| count | a bounded number of occurrences | at most one refund → pass |
What the agent did.
tool_result and tool_error read the authenticated voice_trace. The span is the evidence a tool ran.
What your data shows.
state and state_change query a post-call state adapter: your DB or API. Absent adapter → INCONCLUSIVE.
What a person confirmed.
An Ed25519-signed human label record: the final word when a machine can’t settle it.
Three authorities: the trace, your data, a human.
Every verdict is grounded in one of three sources, and structurally cannot read a fourth.
A state query resolves three ways: match (PASS), no such row (a grounded FAIL), or unreachable (INCONCLUSIVE, with a reason).
A model’s opinion never wears Authority 1 or 2.
A model verdict lives on its own advisory lane and never certifies an outcome.
version: 1 assertions: - id: disclosure-and-language kind: policy # banned language + required disclosures dimension: policy # a named, versioned, offline pack - id: workflow-order kind: tool_call # from the ingested trace require_order: [verify_identity, lookup_account, issue_refund] never_before: {tool: issue_refund, until: verify_identity}
never_before constraint on issuing the refund, plus its required order.- policy pack · versioned
- tool_call · required order
- value never echoed
Did it follow the rules? Same evidence, same lane.
A versioned, offline policy pack checks banned language and disclosures; a tool_call assertion holds the workflow to its required order.
The same deterministic machinery grounds both: no model runs, byte-stable on a fixed version.
Outcome answers whether the task happened. Conversation checks whether it listened; Speech checks what was said.
Prove it happened. Not just claimed.
Eleven deterministic outcome checks and a versioned policy pack, in one command.
$ uvx hotato start --demo
One recording is enough to start. Get started → · Turn-taking →