Typed answer states
Metatate's answer model is an honesty contract. Every decision-bearing MCP tool reads only the deployed instruction decisions of your workspace's current deployment publication — and when that published state cannot support a decision, the tool says so with a typed answer state and a stable reason code. It never fabricates a decision, and it never dresses up an empty read as governance.
The three statesDirect link to The three states
| State | Meaning | Reason codes |
|---|---|---|
answered | Current published instruction rows are sufficient for the asset and scenario. | — |
review_required | Published rows exist, but the answer explicitly requires review or is conflicted. | decision_requires_review, conflicted_published_state |
not_enough_published_state | Published state is missing, unresolved, insufficient, or not currently in force. | no_current_publication, no_published_instruction_state, unresolved_published_target, scenario_unresolved, not_currently_effective |
These are answer states, not errors. Malformed inputs and infrastructure failures surface separately as typed error codes (invalid_parameters, asset_not_found, and so on).
Reason codes in fullDirect link to Reason codes in full
| Reason code | State | Meaning |
|---|---|---|
no_current_publication | not_enough_published_state | The workspace has no current deployment publication. |
no_published_instruction_state | not_enough_published_state | A publication exists, but no published rule applies to this asset and scenario. |
unresolved_published_target | not_enough_published_state | A published rule targets something that could not be resolved in the catalog. The payload lists the specifics in unresolved_targets. |
scenario_unresolved | not_enough_published_state | A free-text use could not be mapped to exactly one canonical scenario. scenario_key is null. |
not_currently_effective | not_enough_published_state | Rules exist for this asset and scenario, but none is inside its validity window at the evaluation instant. |
decision_requires_review | review_required | The effective decision is an explicit require_review. |
conflicted_published_state | review_required | Applicable rules conflict. The payload carries every opposing source. |
Published, but not in forceDirect link to Published, but not in force
not_currently_effective is the temporal answer state. A policy version may declare a validity window (spec.validity), and every rule extracted from that version carries it. Rules are served only while effective_from <= evaluated_at < effective_until — the lower bound is inclusive, the upper bound is not, and a null bound is unbounded on that side.
Distinguish it from its neighbour carefully:
no_published_instruction_state— there are no rules for this asset and scenario. Fix by authoring coverage.not_currently_effective— there are rules, but the clock is outside every window. Fix by correcting the window and republishing, or by waiting.
The answer deliberately does not tell you which window blocked it or when it opens. Rules that are served carry their own effective_from and effective_until, so inspect_governance_rules is where you go to see the windows themselves.
One tool is deliberately exempt: discover_context is validity-blind. It reports published coverage, not current effectiveness, so an asset appears there even when its governing version is out of window. Use it to map an estate, not to gate an action.
Why zero rows is "not enough published state"Direct link to Why zero rows is "not enough published state"
If no published instruction rows apply to an asset or scenario, the answer is not_enough_published_state with reason code no_published_instruction_state — by design. It is not an empty pass ("nothing forbids this"), and it is not an invented review decision. Absence of published governance is a fact about your workspace, and the tool reports that fact so your team can publish the missing coverage. Each not_enough_published_state payload carries next_actions, and unresolved-target answers include the specific unresolved_targets.
Every answer states its evaluation contextDirect link to Every answer states its evaluation context
authorize_use and validate_query_context carry three provenance fields in all three states:
| Field | Meaning |
|---|---|
evaluated_at | The RFC 3339 UTC instant the answer was evaluated at, minted once per call. Validity windows are filtered against exactly this instant, and it matches the recorded decision evidence byte for byte. |
evaluated_purpose | {purpose_key, purpose_category, registry_version}, or null when the call stated no purpose. |
evaluated_actor_role | The role from the calling token's bound_role, or null. |
get_decision_context and inspect_governance_rules carry evaluated_at — they filter by it — and nothing else, because they serve rules as authored: no purpose substitution and no actor substitution. Inspection shows what your policies say; authorization shows what one caller is told. See Purpose keys for why those two can legitimately differ.
Decision valuesDirect link to Decision values
When an answer cites instruction rows, each row's decision is one of eight values: allow, deny, mask_full, mask_partial, require_review, conditional, log_only, retain. A conditional decision means the use is allowed once specific structured conditions (such as approval or anonymize-first) are met, rather than collapsing to a bare require_review — it appears most often in destination-resolved transfer answers, and can also derive from row-access and AI-governance rules.
Deterministic rankingDirect link to Deterministic ranking
When multiple published rows apply, the effective decision is derived deterministically — same published rows in, same answer out. The first difference wins:
- Specificity — column-level beats table-level; within a level, how the asset entered scope: selector, then collection, then taxonomy.
- Priority — higher instruction priority first.
- Restrictiveness —
deny>mask_full>mask_partial>require_review>conditional>retain>log_only>allow. - Stable instruction key — a lexicographic tiebreak, so ordering never depends on read order.
Conflicts are never ranked away: if any row in the winning tier is conflicted, the answer is review_required with reason code conflicted_published_state, carrying every opposing source.
Chaining: two different kinds of identifierDirect link to Chaining: two different kinds of identifier
There are two chainable identifiers, and conflating them is the most common integration mistake.
| Identifier | Identifies | Explain with |
|---|---|---|
decision_id | One published rule — an instruction serving row. Appears on every cited instruction record, and at the top level of an authorize_use answer for the winner. | {"kind": "decision", "decision_id": "<uuid>"} |
authorization_id | One recorded authorize_use evaluation — the whole call, including the purpose and actor role it used. On every authorize_use answer, in all three states. | {"kind": "authorization", "authorization_id": "<uuid>"} |
validation_id | One recorded validate_query_context evaluation, plus a finding_id per finding. | {"kind": "validation", "validation_id": "<uuid>"} |
explain_why inputs are strict and discriminated on kind: passing the wrong identifier for a kind is invalid_parameters, not a best-effort lookup.
Answers also carry publication provenance — publication_id and published_at — so you always know which publication produced them, and authorization_id is what a blocked agent cites when it files a review request.
What publishes stateDirect link to What publishes state
Answers change only when your workspace publishes a new current deployment publication from its deployable instructions — or when a validity window opens or closes, or when a steward grants or revokes an exception for one specific token. See Deployments for how publishing works, Review requests for exceptions, and the MCP server overview for the tools that read it.