PTENES
MODULE 3.1

📕 AGENTS.md, .codex/, and agents in TOML

Codex configuration piece by piece — AGENTS.md as CLAUDE.md’s twin, config.toml, subagents in TOML, and the explicit invocation that catches many people off guard.

7
Topics
35
Minutes
Inter.
Level
Practical
Type

🎯What you get here

Direct Claude → Codex mapping for each configuration component. Leave knowing where each file lives, which syntax to use (TOML vs JSON), and why they’re separate .codex/ × .agents/.

Detailed content

1

📜 AGENTS.md — CLAUDE.md’s sibling

Markdown file in the project root that Codex reads at the start of the session and injects into the system prompt. Identical function to CLAUDE.md. People migrating copy CLAUDE.md, rename it to AGENTS.md, and it works in 90% of cases.

Direct mapping

Claude Code
Codex
~/.claude/CLAUDE.md
~/.codex/AGENTS.md
./CLAUDE.md
./AGENTS.md
./src/api/CLAUDE.md
./src/api/AGENTS.md

⚠️The 10% that DOESN’T port

  • • Backtick-bang inside AGENTS.md → isn’t interpreted; it becomes literal text
  • • Descriptions that are too long may be truncated (hidden limit ~8K chars)
  • • References to Claude-exclusive tools (Task, plan mode) → ignored
  • • Inline hooks/permissions don’t work—they belong to config.toml

Key concepts

Same function
Project system prompt
Same hierarchy
Global → project → subdir
No native bang
Becomes text
Conservative size
~1-2KB
2

📂 Why TWO folders — .codex/ and .agents/

Codex does one intentional separation: what is proprietary (Codex config, agents in TOML) stays in .codex/; what an open spec (Agent Skills) is stays in .agents/. Compatibility with other tools that adopt the spec.

🔧 .codex/ — owner

.codex/
├── config.toml         ← settings (TOML)
├── agents/             ← sub-agents (TOML)
│   ├── reviewer.toml
│   └── doc-writer.toml
└── commands/           ← slash commands
    └── review.md

Things specific to Codex. No other tool understands this.

🌐 .agents/ — open spec

.agents/
└── skills/             ← Agent Skills spec
    └── my-skill/
        ├── SKILL.md
        ├── agents/openai.yaml  ← sidecar
        ├── scripts/
        └── references/

Shareable. Other tools (Cursor, etc.) that follow the spec can read it too.

🚨The most common path error

You read "Codex skill" and instinctively put it in .codex/skills/. Wrong. Skill lives in .agents/skills/ — always. .codex/ is just proprietary config and sub-agents in TOML.

📊 Full comparison

Item
Claude — where
Codex — where
System prompt
./CLAUDE.md
./AGENTS.md
Settings
.claude/settings.json
.codex/config.toml
Sub-agents
.claude/agents/*.md
.codex/agents/*.toml
Skills
.claude/skills/<n>/
.agents/skills/<n>/
Slash commands
.claude/commands/*.md
.codex/commands/*.md
MCP servers
.mcp.json
[mcp_servers] in the toml

Key concepts

Separate config/ext
.codex × .agents
Open spec
.agents = portable
TOML vs JSON
Different syntax
Mirror global
~/.codex and ~/.agents
3

⚙️ config.toml — TOML settings

Equivalent of settings.json from Claude, but in TOML. It’s not harder—it’s DIFFERENT. Section syntax uses brackets, arrays use double brackets, and multiline strings use triple quotes.

commented config.toml

# modelo padrão
model = "gpt-5-codex"
approval_policy = "on-failure"   # quando pedir aprovação
sandbox_mode = "workspace-write" # nível de sandbox

# profiles — perfis nomeados
[profiles.safe]
sandbox_mode = "read-only"
approval_policy = "always"

[profiles.danger]
sandbox_mode = "danger-full-access"
approval_policy = "never"

# MCP servers
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]

[mcp_servers.github.env]
GITHUB_TOKEN = "${GITHUB_TOKEN}"

# model providers
[model_providers.openai]
base_url = "https://api.openai.com/v1"
api_key_env_var = "OPENAI_API_KEY"

TOML syntax in 30 seconds

# comentário
chave = "string"
numero = 42
booleano = true
array = ["a", "b", "c"]

[secao]               # seção (= objeto)
chave = "valor"

[secao.sub]           # sub-seção
outra = "outra"

[[lista_de_secoes]]   # array de seções
nome = "item1"

[[lista_de_secoes]]
nome = "item2"

multiline = """
texto
em várias
linhas
"""

Key concepts

[section]
Object equivalent
[[arrays]]
Array of sections
"""multi"""
Multiline string
${ENV}
Env interpolation
4

👤 Sub-agents in TOML — not Markdown

Sub-agents in Codex are .toml files in .codex/agents/. Structure, not prose. You fill in the fields of a struct: name, description, model, tools, e instructions (multiline string with the system prompt).

Example — .codex/agents/code-reviewer.toml

name = "code-reviewer"
description = "Reviews code for correctness bugs. Call explicitly with 'use code-reviewer to ...'"
model = "gpt-5-codex"
tools = ["read", "grep", "glob", "bash"]

instructions = """
You are a senior code reviewer focused on correctness.

## Your role
- Read the diff carefully
- Flag correctness bugs (NOT style — linter handles that)
- Check edge cases (null, empty, off-by-one, race conditions)
- Note security risks (SQLi, XSS, path traversal, auth bypass)

## Output format
A numbered list of findings:
1. **[severity]** file:line — what's wrong, why, suggested fix

Be terse. No fluff.
"""

🔷 Claude Code agent

---
name: code-reviewer
description: Use proactively...
tools: Read, Grep, Bash
---

You are a senior code reviewer.
...

Markdown with frontmatter. Prose flows naturally.

🟣 Codex agent

name = "code-reviewer"
description = "Call with 'use code...'"
tools = ["read", "grep", "bash"]
instructions = """
You are a senior code reviewer.
...
"""

Structured TOML. Prompt inside a string.

💡Practical conversion

To port a Claude sub-agent to Codex: take the frontmatter and turn it into TOML keys. Take the Markdown body and put it in instructions = """...""". Adjusts the description to mention "call explicitly".

Key concepts

TOML structure
Not Markdown
instructions
Multiline string
tools array
["read", "bash"]
model override
By agent
5

🚦 Explicit invocation — the Claude → Codex gotcha

In Codex, sub-agents Are NOT auto-triggered through the description. You need to call it by name in the prompt. This is the difference that most confuses people coming from Claude.

🔷 Claude — auto

User: "revisa essa PR"

→ Claude lê descriptions
→ Match: code-reviewer
→ Dispara sub-agent
→ Devolve findings

You don’t need to know the agent exists.

🟣 Codex — explicit

User: "revisa essa PR"

→ Codex faz revisão genérica
→ Sub-agent code-reviewer NÃO roda

User: "use code-reviewer para
        revisar a PR #123"

→ AGORA dispara o sub-agent.

You need to remember the agent and call it.

🚨Error symptom

"Why isn’t my agent being called? It’s exactly like in Claude!"

→ Because you didn't call it. In Codex, description is only there to REMIND you that the agent exists, not to trigger it. Call it by name.

Design trade-off

Advantage (Codex):

Predictable. You always know what will run. No surprise like “Claude decided to call X when I wasn’t expecting it.”

Downside (Codex):

Less ergonomic. You HAVE to remember the agents. If you forget, an agent becomes "dead code."

Key concepts

Invocation by name
"use agent X..."
No auto-dispatch
By design
Predictability
Trade-off
Description = reminder
For you, not the LLM
6

🏖️ Sandbox and approval modes

Codex has configurable sandbox via config.toml. Three increasing levels of power + approval policies that control when to ask for confirmation. More granular and explicit than Claude’s equivalent.

🔒

read-only

Read-only. Bash works for ls, cat, grep. No writes, no network. Ideal mode for risk-free analysis.

📝

workspace-write (default)

Writes to the project. Doesn't write outside it. Limited network. Day-to-day mode.

⚠️

danger-full-access

No restrictions. It can write anywhere, the network is open, and any commands are allowed. Only in a real sandbox (container/VM).

Approval policies

"always" — asks for confirmation on EVERY command
"on-failure" — only ask if the first attempt failed (reasonable default)
"on-request" — asks only if the model thinks it needs to
"never" — never prompts (works with a restrictive sandbox)

Key concepts

3 sandbox levels
read / write / full
Approval policy
When to ask
Profiles
Pre-agreed
Network gating
By sandbox
7

🔄 Slash commands in Codex

Codex supports custom slash commands in .codex/commands/ (files .md). Same concept as Claude's — some differences in argument syntax and no backtick-bang.

Example — .codex/commands/review.md

---
description: Revisa o diff atual procurando bugs
---

Revise o diff atual da branch (rode git diff).

Procure:
- Bugs de correção
- Casos não tratados
- Vulnerabilidades comuns

Se passar argumento, foque nesse arquivo.

Retorne lista numerada de findings + severity.

Usage: /review or /review src/api/auth.ts

⚠️No backtick-bang

In Claude, you could write Branch atual: `!git branch --show-current` inside the command, and the result was inserted into the prompt. In Codex, it becomes literal text. Solution: ask the agent to RUN the command (fallback prose) or call a script.

Key concepts

.codex/commands/
Same convention
Frontmatter
minimal description
No bang
Fallback prose
Delegated script
Alternative to injection

🎯Module summary

✓
AGENTS.md ≡ CLAUDE.md — same function, same hierarchy, just without backtick-bang.
✓
Two folders: proprietary .codex/, open spec .agents/ — skills ALWAYS go in .agents/.
✓
config.toml in TOML — [section], [[arrays]], """multiline""", ${ENV}.
✓
Sub-agents = TOML structure — multiline instructions string, not a markdown body.
✓
EXPLICIT agent invocation — “use agent X...” or nothing happens.
✓
3 sandbox levels + 4 approval policies — explicit granularity.
✓
Slash commands without backtick-bang — use fallback prose or a script.

Next module:

3.2 — Skills in Codex and the openai.yaml sidecar (the quirk that causes the most confusion)