Understanding SAT / UNSAT
Understanding SAT / UNSAT
When you check an agent action against a policy, ICME returns one of several possible results. The most common are SAT and UNSAT. This page explains what each result means, what causes each one, and how to interpret the less common results you may encounter.
The basics
ICME uses an SMT (Satisfiability Modulo Theories) solver to evaluate agent actions against your compiled policy. The solver's job is to determine whether a given action is satisfiable — consistent with your policy constraints — or unsatisfiable — in violation of them.
SAT (Satisfiable) means the action is permitted. The solver found that the action is consistent with all constraints in your policy. Your agent can proceed.
UNSAT (Unsatisfiable) means the action is blocked. The solver proved that the action violates at least one constraint in your policy. No combination of circumstances makes the action permissible under your rules.
These are not confidence scores. They are not probabilities. SAT and UNSAT are mathematical conclusions. The same action evaluated against the same policy will always produce the same result.
The full result set
Beyond SAT and UNSAT, you may encounter three additional results in certain circumstances.
SATISFIABLE (conditional) The action is consistent with your policy, but only under certain conditions that weren't fully specified in the action description. The solver found at least one scenario where the action would be permitted and at least one where it would be blocked.
This usually means your policy has a gap, a rule that depends on a variable the action didn't provide, or the action description was ambiguous. See troubleshooting SATISFIABLE results below.
IMPOSSIBLE The action contains premises that directly contradict your policy rules, making it logically impossible to evaluate. This often indicates a conflict within the policy itself rather than a problem with the action.
Example: your policy contains both "all transfers to external wallets are permitted" and "transfers to unverified wallets are blocked" — an action involving an external wallet that is neither explicitly verified nor unverified will return IMPOSSIBLE.
NO TRANSLATION The action description could not be formalized into the logical vocabulary of your policy. This typically means the action describes something your policy has no rules about, or the action was written in a way the formalizer couldn't parse reliably.
What causes UNSAT
An action returns UNSAT when the solver proves it violates at least one constraint. The response body includes a reason field that identifies which rule was violated and why.
Threshold violations
json
Recipient not on approved list
json
Rate limit exceeded
json
Multiple violations When an action violates more than one rule, the response identifies the first violated constraint. Fix that constraint and re-check — there may be additional violations.
What causes SAT
An action returns SAT when the solver confirms it satisfies all constraints in your policy. The response includes the proof receipt regardless of whether the result is SAT or UNSAT.
json
Troubleshooting NO TRANSLATION results
NO TRANSLATION means the formalizer couldn't extract evaluable claims from the action description. This is usually one of three things:
The action is out of scope for your policy Your policy covers financial transactions, but the action describes a database query. The formalizer has no variables to map it to. Either expand your policy to cover the new action type or return NO TRANSLATION as a signal to your agent that this action type requires a different evaluation path.
The action description is too vague "Do the usual thing with the funds." — there is nothing for the formalizer to work with.
Fix: require your agent to produce structured, explicit action descriptions before submitting them for evaluation.
The action description is too complex A very long, multi-part action with many nested conditions may exceed the formalizer's reliable operating range. Break it into individual atomic actions and check each one separately.
Using results in your agent logic
A minimal integration pattern:
python
The proof field should always be stored alongside the action and result — it is your cryptographic receipt that the correct policy was applied to the correct action and produced the correct result.
A note on determinism
Unlike LLM-based guardrails, ICME's results are fully deterministic. Given the same policy and the same action, the solver will always return the same result. This has two practical implications:
You can write unit tests for your guardrails. Build a test suite of actions you expect to be permitted and actions you expect to be blocked. Run it every time you update your policy. If a previously-passing test fails after a policy update, you have an immediate signal that the policy change had unintended consequences.
Caching is safe. If your agent submits the same action repeatedly, the result will not change unless the policy changes. You can cache results for identical action descriptions against the same policy_id to reduce latency and cost.
Last updated

