Writing Effective Policies
Writing Effective Policies
Your policy is the foundation of everything ICME does. The quality of your guardrail is directly determined by the quality of your policy. This page covers how to write policies that compile cleanly, enforce precisely, and cover the edge cases that matter.
How ICME reads your policy
Before writing, it helps to understand what happens to your words. When you submit a policy, an LLM translates each statement into SMT-LIB formal logic. The compiler then checks the resulting rules for internal consistency. What makes it to the solver is a precise, mathematical representation of what you wrote.
This means two things:
Clarity beats cleverness. Write policies the way you would explain rules to a new employee, not the way you would write a legal contract. Short, declarative sentences formalize more reliably than long, nested clauses.
Be explicit about edge cases. The solver can only enforce what is in the policy. If a rule has an exception, write the exception. If a limit applies under certain conditions, write the conditions. Ambiguity in natural language becomes ambiguity in the logic — and ambiguous rules produce SATISFIABLE results rather than clean SAT or UNSAT.
Policy structure
A good policy is a numbered list of plain English rules. Each rule should express a single constraint.
Good:
1. Transfers over 1000 USDC are not permitted.
2. Transfers to wallets not on the approved list are not permitted.
3. No more than 3 transfers may be made within a 60-second window.Harder to formalize:
1. Large transfers to unknown wallets are generally not permitted unless
pre-approved, and the agent should also be careful about frequency.The second version will compile, but the rules it produces will be less precise. "Large" is undefined. "Generally" introduces ambiguity. "Should also be careful" is not a constraint.
Policy examples by use case
DeFi and crypto agents
Autonomous payment agents
Enterprise AI assistants
Agentic coding tools
Healthcare and regulated industries
Common mistakes and how to fix them
Using relative terms without defining them
❌ Large transactions require approval. ✅ Transactions over $5,000 require approval.
The solver needs a value it can evaluate. "Large" is meaningless to formal logic.
Writing policies that conflict with each other
❌
This compiles but will produce IMPOSSIBLE results for any action involving an external wallet that hasn't been explicitly verified or unverified. ICME's consistency checker will flag this, use it as a signal to refine your rules.
✅
Leaving implicit exceptions implicit
❌ No transfers over 1000 USDC.
This blocks a transfer of 1000 USDC to an emergency fund, even if you intended that to be allowed.
✅
Using process language instead of constraint language
❌ The agent should check the whitelist before making transfers.
"Should check" describes a process, not a constraint. The solver doesn't evaluate processes.
✅ Transfers are only permitted to wallets on the approved whitelist.
Writing compound rules that bundle multiple constraints
❌ Large transfers to new wallets outside business hours require approval and must be logged.
This bundles four separate constraints into one sentence. Break it up.
✅
Testing your policy before deploying
Before integrating your policy into a live agent, test it with a range of actions, including ones you expect to be blocked. Use /v1/checkIt during development.
Useful test patterns:
Boundary testing: if your policy blocks transfers over 1000 USDC, test exactly 999, exactly 1000, and exactly 1001.
Adversarial testing: try phrasing actions the way a bad actor might: vague descriptions, split transactions designed to stay under limits, indirect references to blocked actions.
Edge case testing: what happens if a field is missing? What if the wallet address is malformed? Write test cases for incomplete or unexpected inputs.
Contradiction hunting: if the solver returns IMPOSSIBLE on a reasonable action, it usually means two rules are conflicting. Revisit your policy for overlapping or contradictory constraints.
Policy versioning
Every call to /v1/makeRules produces a new policy_id. Treat these like code — keep a record of each version and what changed. If you need to roll back to a previous policy, you can do so immediately by switching the policy_id your agent passes to /v1/checkIt.
Good practice is to maintain at least three versions: production, staging, and draft. Test policy changes in staging before promoting to production.
Last updated

