Guide
Import existing policies
Policies written for the Agent Governance Toolkit can be imported as they are. Each rule is translated into a typed AgentFox policy rule, translated with a note where the meaning shifts, or listed as not translatable with the reason. Nothing is dropped silently, and no deny comes out weaker.
When to use this
You already have rule files (apiVersion: governance.toolkit/v1, with rules and default_action) or policy manifests (agent_control_specification_version, bound to a Rego bundle), and want them evaluated by the deterministic AgentFox engine, with simulation before enforcement.
| You want to | Run |
|---|---|
| See what a file would become | agentfox policy import FILE |
| Import it, watching | agentfox policy import FILE --apply |
| Import over HTTP | POST /api/import/agent-governance |
In the web app Policies → Library → Import → Agent governance YAML or policy manifest
Read the plan first
Run the import without --apply
support.yaml apiVersion: governance.toolkit/v1 name: support-agent default_action: deny rules: - name: allow-reads condition: "tool_name startswith 'read_'" action: allow - name: big-refunds-need-approval condition: "amount > 500 and tool_name == 'refund'" action: require_approval - name: owner-only condition: "user.id == resource.owner" action: denybash agentfox policy import support.yamlOutput default (imported-support-agent): Unmatched calls are blocked by the `default-deny` rule on tool_args. status rule effect why with note allow-reads allow an exception to the default deny: calls it matches are not blocked by the default-deny rule (other block rules still apply) with note big-refunds-need-approval escalate context field `amount` is read as the tool-call argument `amount`; when the field is missing or not a number their deny rule fires and this one does not; escalates to the approval queue not translated owner-only — compares two fields (`user.id == resource.owner`); a condition here compares a field with a value, and their evaluator does not recognise this syntax: there it matches every call for a deny rule and no call for an allow rule 0 translated, 2 with a note, 1 not translated; 0 text pattern(s) become custom rules lint: no policy issuesThe plan is also printed as JSON with
--json, and comes with the result of the policy linter run on what would be saved.Check the default
default_action: allowmeans a call no rule matches passes. The plan puts that first, as Unmatched calls pass, because it is easy to miss in a long file.default_action: denybecomes adefault-denyblock rule, with the allow rules carved out of it where they test only the tool or agent name.Read what was not translated
Every rule the plan marks not translated is absent from the import. Common reasons:
- A comparison of two fields, such as
user.role == resource.owner. A condition here compares a field with a value. The source evaluator cannot compare two fields either: it treats them as unrecognised syntax, so such a deny there matches every call. Fields both known to the engine (tool, agent, surface, environment) are translated. - Negations (
not ...), rate limits, and conditions on the call's context or budget. - More than one argument comparison in one condition.
- Cedar policies, annotations (classifier calls) and conditional verdict rules in Rego.
- A comparison of two fields, such as
How meaning carries over
denybecomes block,require_approvalbecomes escalate (the approvals queue),warnandlogare recorded when they fire.- Priorities do not carry over. When several rules match, the strongest effect wins, so an allow never overrides a block. That is stricter than first-match-by-priority, and the plan says so on each allow rule.
- Conditions are parsed, not pattern-matched:
==,!=,in [...],contains,startswith,endswith, numeric comparisons,andandor. Anoror aninlist on the tool becomes one rule per branch. - A regular expression or substring test on message text becomes a custom pattern rule that only detects; the imported policy rule acts on that detection.
- A manifest is checked against the published JSON Schemas before anything else. Each Rego policy bound to an intervention point is read for its decision rules (
deny contains msg if { ... },escalations,allows…);input,output,pre_tool_callandpost_tool_callmap to the input, output, tool-argument and tool-result surfaces. Rego is never executed.
Import, watching
agentfox policy import support.yaml --apply
agentfox policy import manifest.yaml --bundle ./rego --applyImported policies are saved in observe: they record what they would have done and block nothing. A policy that is already live keeps its mode; the new version waits. To enforce, replay recorded traffic first with agentfox policy simulate, then promote it.
Over HTTP
curl -s -X POST localhost:8080/api/import/agent-governance/plan \
-H 'content-type: application/json' \
-d '{"source": "<the YAML>", "files": {"policy.rego": "<the Rego>"}}'The plan lists items (each with status, effect, notes and reason), default_action, unmatched_pass, schema_errors and lint. Post the same body to /api/import/agent-governance to apply it; skip takes positions in items to leave out.