Action Integrity
Policies and approvals
Deterministic rules (allow, deny, require approval, limit), the policy builder, replay, versions and human approvals.
Policies are your rules for agent actions: JSON, versioned, and evaluated as deterministic code. The same facts always give the same decision, and every action stores the policy versions and the rules that matched. A language model can help draft a rule; it never decides an action.
An example policy
jsonPolicy version
{ "default_effect": "allow", "rules": [
{ "id": "refund-auto", "effect": "allow",
"match": { "agents": ["support-agent"], "action_types": ["refund.create"], "amount": { "lte": 10000, "currency": "USD" } } },
{ "id": "refund-approval", "effect": "require_approval",
"match": { "action_types": ["refund.create"], "amount": { "gt": 10000, "currency": "USD" } },
"approval": { "roles": ["owner", "admin"], "timeout_minutes": 1440 } },
{ "id": "discount-velocity", "effect": "limit",
"match": { "action_types": ["discount.create"] },
"limit": { "kind": "velocity", "max_count": 5, "window_minutes": 1440, "per": "customer", "on_exceed": "deny" } },
{ "id": "no-annual-cancel", "effect": "deny",
"match": { "action_types": ["subscription.cancel"], "conditions": [{ "attr": "subscription.interval", "op": "eq", "value": "year" }] } }
] }Matching
agents: agent ids or slugs.action_types: for examplerefund.create.amount:gt,gte,lt,ltein minor units, with a requiredcurrency.conditions: anattrfrom the provider context orparams.*/metadata.*, witheq,neq,in,not_in,gt,gte,lt,lte,exists,not_exists.time:days_of_week(1–7),hoursfrom–to and atimezone.
Effects
denywins overrequire_approval, which wins overallow.limitacts only when exceeded, as itson_exceed: a per-action cap, a rolling budget or a velocity limit, per agent, customer, resource or organization.- With no matching allow, deny or approval rule,
default_effectapplies (deny if any active policy says deny). With no policy at all, the action is allowed, and the built-in business rules still run.
The policy builder
- Describe the rule in plain language: “Refunds up to $100 autonomously, above needs a manager”, “Max 5 discounts per customer per day”, “Never cancel annual subscriptions”, “No more than $1,000 in refunds per agent per day”.
- Draft: Audon turns it into a structured rule. With a language model configured, the model must answer through a tool whose input schema is the rule schema (temperature 0); the output is validated and rejected if it names unknown agents. Without one, or when the output is invalid, a deterministic phrase parser handles the common phrasings.
- Validate and replay: the draft is checked against the schema and replayed over your stored actions and audited history. You see how many would be allowed, denied or sent for approval, which decisions change, the matches per rule, and warnings:
always_allows,never_matches,matches_everything. - Confirm: drafts never apply on their own. A signed-in person activates the version (
confirm: true), which re-validates and replays it and stores the confirmer, the source text, the validation and the replay. Active versions are immutable.
Approvals
A require_approval rule puts the action on hold: decision pending_approval, outcome awaiting_approval.
- The people with the approval’s roles get an email and your webhook gets
integrity.approval.requested; in a single-person organization, the owner. - Deciding needs
integrity:approvals:decide(owner and admin) and a signed-in person. No agent key can hold it. - The first decision wins; a second decider gets
conflict. On approval, Audon re-checks business rules and duplicates against fresh provider state under the resource lock, then runs the action once. If the state changed meanwhile, it is denied withchanged_since_request. - At the timeout the approval expires, and an expired approval is a denial.
Tune in monitoring first
Would deny
In monitoring mode, actions your rules would deny still run and are recorded as would_deny, and approvals aren’t waited for. Review them, adjust the rules, then switch to enforcing.