Are you an LLM? You can read better optimized documentation at /docs/agent-guard/operations/agent-enforcement-differences.md for this page in Markdown format
Enforcement differences between agents
Most of Agent Guard's enforcement is identical whatever agent you run, because it happens outside the agent: artifact admission runs on the host before the agent starts, and guardrails run in the Jozu AI Gateway that inference traffic passes through. Neither depends on the agent cooperating.
Tool enforcement is different. It depends on how a given agent reports the tool calls it is about to make, and not every agent offers the same hook.
Codex enforces through a translated rule file
Claude Code, OpenClaw, and Antigravity CLI call the policy server for each tool use, so the loaded policies are evaluated as written, with full CEL. A custom runtime's MCP tool calls pass through the Jozu gateway and are evaluated the same way; an action it takes without the gateway is outside policy (see Custom runtime limitations).
Codex does not work that way. Its enforcement surface is a Starlark rules file at .codex/rules/agentguard.rules inside the guest, generated at boot by translating the loaded ToolPolicies into prefix_rule() calls. Codex matches literal command prefixes, so the translation is necessarily lossy.
What survives translation:
- Policies matching the shell tool (
Bash,run_shell_command). Rules on other tools do not translate - Assertions written as
tool.arguments.command.contains("..."). Each literal becomes aprefix_rulepattern Enforce, which becomesdecision="forbidden", andElicit, which becomesdecision="prompt"
What does not:
.matches()regular expressions, which are not recognized at all- Assertions on any argument other than
command. AWebFetchrule ontool.arguments.urlis not recognized - Compound expressions the translator cannot reduce to a literal prefix
Auditpolicies, which have no Codex equivalent
Why this matters for regex rules
Anchored regular expressions are the better way to write shell rules everywhere else. contains("curl") matches concurly and is trivially avoided; matches("(^|[^\\w-])curl([\\s;|&]|$)") is not.
On Codex that preference inverts. A regex rule contributes nothing to the translated file, and if none of your rules translate, the generated file is empty and Codex falls back to a small built-in set: rm -rf /, sudo, git push, npm publish, and reads of /etc/shadow and /etc/passwd. That fallback is not nothing, but it is not your policy either.
The fallback is silent. An empty translation looks the same as "no policies configured," so nothing warns you that your bundle did not apply.
What to do
Check what is actually in force rather than assuming. Inside a Codex session, read the generated file:
bash
cat .codex/rules/agentguard.rulesFor controls that must hold regardless of agent, prefer a layer that does not depend on the agent at all. An ArtifactPolicy blocking an MCP server, or a GuardrailPolicy on inference content, applies to a Codex session exactly as it does to any other.
If a specific rule has to hold on Codex, add a contains() version of it next to the anchored regex. The regex rule is enforced in full wherever policies are evaluated per tool call, and the contains() rule gives Codex a floor. Do this only for those rules: restructuring a whole bundle around contains() weakens it on every agent to suit one translator.
Unaffected by all of this
- ArtifactPolicy. Admission runs on the host before the agent starts, so every agent gets identical treatment
- GuardrailPolicy. Inference traffic passes through the Jozu gateway whatever agent produced it
- Network egress and the microVM boundary. Enforced by the sandbox, not by the agent
