Are you an LLM? You can read better optimized documentation at /docs/agent-guard/policies/how-policies-work.md for this page in Markdown format
How policies work
A policy is a YAML file that tells Agent Guard whether to allow, block, or modify some action the agent is about to take. Every policy uses: an API version, a kind, a match expression that decides whether the policy applies, an action (what to do when it does), and a list of rules with assertions written in CEL.
The three policy kinds
Each kind has a different scope, evaluates at a different point in the agent's lifecycle, and supports a different set of actions.
- ArtifactPolicy: Governs what the agent can pull into its runtime and is evaluated at admission time, before the artifact loads. Decisions can be based on the registry, repository, tag, signature, attestations, license, or Kitfile metadata of an OCI artifact. Best used for supply chain controls (only pull from trusted registries, require cosign signatures, block known-bad versions).
- ToolPolicy: Governs which tools the agent can invoke and what arguments those calls can have. Evaluated at every tool call, both for the agent's built-in tools served through a harness (
Bash,Read,Write,WebFetch, etc.) and for tools exposed by any MCP servers the agent has loaded. Best used to block destructive or dangerous tools like file deletion, force merge, drop database, etc... - GuardrailPolicy: Governs the content of prompts and responses (toxicity thresholds, PII redaction, prompt injection patterns). Evaluated against findings from configured scanning engines (LLM Guard, Presidio, custom scanners) on inference inputs, outputs, or both.
Actions
Each policy type supports its own set of actions. All policies include Enforce to block the operation outright, and Audit to allow the action to execute, but log its details. Beyond those:
- ToolPolicy adds
Elicit, which pauses to ask the user for confirmation before proceeding. Useful for destructive operations that are sometimes legitimate (recursive delete, dropping a database table). - GuardrailPolicy adds
Redact, which lets the response through with the sensitive content masked.
Fail-closed
All policy evaluation fails closed. If Agent Guard cannot parse a policy or hits an evaluation error, the operation is blocked. A misconfigured policy will keep the agent from doing useful work, which is the intended trade-off: silent allow-on-error would be a worse failure mode for a security product. For this reason we recommend starting all policies with Audit as the only action and evaluating policy evaluation matches expectations before moving actions to Enforce, Elicit, or Redact.
Picking the right kind: supply chain example
A ToolPolicy could match on Bash and assert that the command does not contain npm install <bad-package>. That works, but it requires you to enumerate every possible install tool (npm, yarn, pnpm, pip, pip3, pipx, uv, bun, ...) and every possible bad package. New install tools appear; new bad packages appear; the rules go stale.
An ArtifactPolicy blocks the registry instead of the tool. If the agent cannot reach registry.npmjs.org, no install tool can pull a package from it. The blast radius is narrower and the rule does not need updating when a new install tool ships.
This is why the Supply Chain pre-built tier is implemented as ArtifactPolicies, not ToolPolicies. The same reasoning applies whenever a control can be expressed either way: prefer the kind that closes off the source rather than the kind that lists every consumer.
Writing assertions: the convention
This is the single most important thing to internalize before you write a policy.
Write assert as a statement of what a safe call looks like. The action (block, elicit, redact) fires when the statement evaluates to false.
In plain language: assert that things are good. If things are not good, the action runs.
assert: true → call allowed
assert: false → action firesThis is the opposite of the convention used in OPA/Rego deny rules, AWS IAM, or firewall match-and-act rules, where you describe the bad case and the engine acts when it matches. Agent Guard inverts that: you describe the good case, and the engine acts when reality deviates.
The practical consequence is that most assertions are written with ! (logical NOT). To block git push --force, you assert that the command does not contain that string:
yaml
assert: |
!tool.arguments.command.contains("git push --force")If the command is ls, the assertion is true (safe), and the call is allowed. If the command is git push --force origin main, the assertion is false (not safe), and Enforce fires.
To audit every call without blocking anything, the assertion is the literal "false" (quoted so YAML parses it as a CEL string, not a boolean). This guarantees the assertion always fails and the Audit action always fires:
yaml
spec:
action: Audit
rules:
- name: log-every-bash-call
assert: "false"
message: "audit-everything"That is the only common case where you write an assertion without a negation.
A small example
The smallest useful ToolPolicy is one rule, against one tool, with one assertion. This one blocks git push --force:
yaml
apiVersion: gerty.jozu.dev/v1
kind: ToolPolicy
metadata:
name: no-force-push
spec:
match:
tool:
names:
- "Bash"
action: Enforce
rules:
- name: no-force-push
assert: |
!tool.arguments.command.contains("git push --force") &&
!tool.arguments.command.contains("git push -f")
message: "Force push is prohibited"A few things to notice. The match is on Bash, not git. Git is invoked through the agent's Bash tool, so the policy hooks into that. The assertion uses !contains(...) for both forms of force push so either one fires the action. The action is Enforce, which blocks the call and returns the message to the agent.
See Write your first policy for a step-by-step walkthrough.
Where policies live in Agent Guard's flow
The Agent Guard AI Gateway runs inside the microVM. Every tool call from the agent is sent to the gateway, which evaluates the call against the loaded ToolPolicies and either passes the call through, blocks it, or pauses for confirmation. ArtifactPolicies evaluate when the agent pulls a new OCI artifact (an MCP server, a skill, another agent definition). GuardrailPolicies evaluate against the inference traffic as it flows through the gateway.
Performance impact
The latency introduced by policy evaluation is generally unnoticeable. A simple policy can be evaluated in microseconds, more complex policies in milliseconds. Guardrail policies may take longer because they are determined by the prompt or response length.
Hub-side policies
What is described above is Agent Guard's runtime policy enforcement. Jozu Hub has its own policy layer that can block ModelKit artifact pulls at the registry before they ever reach Agent Guard. Hub-side pull blocking is heavier-handed than ArtifactPolicy in Agent Guard, because it affects every developer and CI system trying to pull the artifact, not just one agent running in a specific runtime. Reserve Hub-side blocks for "stop work" cases (known-malicious package, revoked license). Use Agent Guard's ArtifactPolicy for per-runtime trust decisions.
Hub cannot block pushes. The artifact has to be in the registry for any policy to evaluate against it. Scanning, signing, and attestation happen after the push lands.
