Are you an LLM? You can read better optimized documentation at /docs/agent-guard/policies/write-your-first-policy.md for this page in Markdown format
Write your first policy
Writing a policy from scratch is the fastest way to understand how Agent Guard's policy engine works. This guide walks through a ToolPolicy that blocks the agent from reading .env files. The policy is small enough to fit on one screen, and you can test it in under a minute.
Before starting, read Writing assertions: the convention if you have not already. The short version: assert describes the safe case. The action fires when the assertion is false. That's why every rule below uses ! (logical NOT).
The example
.env files often hold secrets (API keys, database URLs, OAuth client secrets). The agent has no need to read them, but it will try if you ask it to summarize your project or trace a configuration issue. A one-rule ToolPolicy blocks the read.
Save this file at ~/.agentguard/policies/global/no-env-reads/no-env-reads.yaml:
yaml
apiVersion: gerty.jozu.dev/v1
kind: ToolPolicy
metadata:
name: no-env-reads
spec:
match:
tool:
names:
- "Read"
action: Enforce
rules:
- name: block-dotenv-files
assert: |
!tool.arguments.file_path.orValue("").endsWith(".env") &&
!tool.arguments.file_path.orValue("").endsWith(".env.local") &&
!tool.arguments.file_path.orValue("").endsWith(".env.production") &&
!tool.arguments.file_path.orValue("").contains("/.env.")
message: "Reading .env files is not allowed"The directory structure matters. Agent Guard expects policy files under global/<source-name>/ or workspaces/<hash>/<source-name>/. The <source-name> portion can be any short identifier (it shows up in agentguard policy list).
What each section does
- apiVersion and kind:
gerty.jozu.dev/v1andToolPolicy. The policy engine refuses anything else, so these have to match exactly. - metadata.name: Identifies the policy in logs and audit output. Pick something descriptive (
no-env-readsrather thanpolicy-1). - spec.match.tool.names: A list of tool names the policy applies to.
Readis Claude Code's built-in file-reading tool. To cover Gemini or Codex add their equivalent names (read_file,Read) or move the list to a broader match. - spec.action:
Enforceblocks the tool call when the assertion fails. Other options areElicit(prompt the user) andAudit(allow but log). - spec.rules.assert: The CEL expression. Returns
trueto allow the call,falseto fire the action. The convention is to assert that the call is safe and use!to invert checks for unsafe conditions (see the!endsWith(".env")pattern above). - spec.rules.message: What the agent sees when the rule fires. The agent uses this to decide what to do next, so write it as instructions for an audience that is half-human, half-agent.
Test it
Drop the file in place, then run Claude Code against any workspace that contains a .env file:
bash
agentguard run claude-code --workspace ~/projects/myappInside the microVM, ask Claude to do something that should trigger the rule:
Show me what's in the .env file.
Agent Guard denies the Read call. The terminal output will look like:
[policy] BLOCK tool=Read file_path=/workspace/.env
rule=block-dotenv-files
message="Reading .env files is not allowed"Claude then receives the error message as the tool result and decides what to do next. It will usually explain that it could not read the file because of a policy block.
Iterating without publishing
Policies in ~/.agentguard/policies/global/ are picked up on every run. You do not need to push to a registry to test. Edit the YAML, save, run again, watch the behavior change. This is the right loop while you are figuring out an assertion.
When you are ready to share the policy with the rest of your team, package it into an OCI artifact and push it to your Hub. See Manage policies for the publishing flow.
CEL gotchas
Once you start writing more rules, a few CEL patterns will trip you up: missing arguments that need orValue(""), the YAML-vs-CEL false literal, .contains() being substring not regex, and path traversal. See the CEL helpers and gotchas section of the policy schema reference for the full list with examples.
