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 policy engine
Policies are evaluated by the policy engine embedded in Agent Guard. It reads your YAML, compiles the CEL in each rule, and returns an allow or deny decision for every request.
You will see the name "gerty" in the gerty.jozu.dev/v1 API version at the top of every policy file. That is Jozu's internal name for the engine. It appears in the API version and in the CLI below, and nowhere else you need to care about.
Agent Guard runs it for you, so writing and shipping policies takes no separate setup. It is also available as a standalone CLI for validating and evaluating policies on your own machine before you publish them, which is worth having once you are writing rules regularly. Contact Jozu for access to the CLI.
Agent definitions use a different API version, agentguard.jozu.dev/v1. Policies are always gerty.jozu.dev/v1.
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 asks a human to approve the operation. Useful for destructive operations that are sometimes legitimate (recursive delete, dropping a database table). WriteElicitwhen you mean "ask" rather than "never" — the two are different intents. See Elicit for the full shape. - 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. This holds inside an Audit policy too: an Audit rule that errors denies the operation rather than logging and moving on, so a rule that crashes never becomes a rule that passes. 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
The three kinds are not severity levels on one control. Each sees something the others cannot, so the question is never "which is stronger" but "which one can see the thing I care about."
ArtifactPolicy sees OCI artifacts on their way into the agent: the agent definition, each MCP server, each skill, each policy bundle. Its unit is an artifact with a registry, a repository, a tag, a digest, and possibly a signature. If a control is about what the agent is made of, it belongs here, and it runs once, before the agent starts.
It sees nothing else. Ordinary files inside the microVM are not artifacts and never reach it. Controlling which files an agent may read or write is ToolPolicy on Read, Write and Edit, which is what the pre-built tiers use for their credential fences and file-write fences.
ToolPolicy sees what the running agent does: which tool was called, and with what arguments. If a control is about an action the agent takes, it belongs here.
Supply chain protection needs both, because the phrase covers two different things.
A malicious MCP server is an artifact. It arrives as an OCI pull, it has a registry and a signature, and ArtifactPolicy can refuse it at the boundary before it ever loads. Nothing at runtime can help you here: by the time a tool call happens, whatever was installed is already installed.
A malicious npm package is not an artifact, at least not one Agent Guard admits. It arrives because the agent ran npm install in a shell. There is no OCI pull to evaluate, so ArtifactPolicy has no opinion and could not form one. Restricting where package managers may install from is a ToolPolicy on the shell, and that is what the Supply Chain tier is.
Command-level rules have a cost: a rule keyed on pip does not catch python -m pip, pipx, or uv pip, so it is written against the invocations you expect and needs revisiting as new wrappers appear.
There is a source-level option that avoids this, and it is also a ToolPolicy. An egress allowlist on the shell and network tools can refuse traffic to registry.npmjs.org outright, which stops every installer at once regardless of which wrapper the agent reaches for. It is the blunter control: it blocks the good installs with the bad, so it suits an environment with an internal mirror or proxy. The two compose well, with egress rules closing off the source and command rules handling the cases you want to allow selectively.
What does not apply here is ArtifactPolicy. It governs OCI registries, meaning where agent definitions, MCP servers, skills and policy bundles come from, not the package registries npm and pip talk to.
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, Writing rules for the patterns that keep rules from misfiring, and A layered policy, worked through for all three kinds composed against one threat.
Where policies live in Agent Guard's flow
The Jozu AI Gateway runs inside the microVM. Every tool call from the agent is sent to the Jozu 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 Jozu 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.
