Howto codex

Static reading edition · s04-02

Configure a narrow custom Codex agent

Subagents22 min estimatedApp / CLI / IDE

Draft a valid custom role while understanding which settings it can and cannot change.

Understand the approach

A custom Codex agent is a named configuration for a recognizable responsibility. In this capstone, practice_normalizer owns package A: implementing normalizeStatus in starter/normalize.cjs against CONTRACT.md. Keep the stable role instructions separate from the current task input. The role can describe how to preserve unrelated work and report evidence; today's brief still needs the actual workspace, owned path, contract version and expected return.

Current Codex custom agents use standalone TOML files under a documented project or user agents directory. Required fields are name, description and developer_instructions. The lab supplies role-draft.toml outside active discovery paths so you can inspect it without installing anything. A later deliberate scratch-client test must verify that Codex actually loaded and used the role; a file that parses and a plausible normalizer report are not sufficient proof.

Subagents inherit the parent's execution settings, provider and MCP servers. A sentence saying own one file is a behavioral instruction, not an independent filesystem sandbox. Do not insert unsupported permission overrides into the role and assume they changed access. First verify the bounded code result with padded statuses, wrong types and unsupported values. Then, if a real custom-role exercise is performed, inspect both its actual role activity and its final diff as separate evidence.

For deliberate project activation, place the whole role draft at .codex/agents/practice_normalizer.toml inside the disposable lab. Current standalone files need no role registration table in parent config. The guide provides PowerShell and POSIX copy steps that preserve existing work. Start a fresh client context if needed, request practice_normalizer for A, then inspect its actual role activity and output. Omitted model/effort settings inherit parent defaults. Supported reductions such as features.shell_tool=false can remove shell execution for a read-heavy role, but are inappropriate for a worker expected to run checks. This file cannot override parent sandbox, approval, provider or MCP settings.

A role file specializes instructions within inherited boundaries

The parent session supplies execution limits and connected capabilities. A TOML role supplies focused instructions. A particular delegated task narrows the immediate work further; the role description does not expand its permissions.

The parent session supplies execution limits and connected capabilities. A TOML role supplies focused instructions. A particular delegated task narrows the immediate work further; the role description does not expand its permissions.

Open the full diagram

Practice and acceptance

A custom role states behavior; inherited permissions and actual client role loading must be checked separately.

About your environment

Checked 21 October 2026. Protected configuration paths and managed policies may affect how a role is installed; the course does not apply the file.

Try it step by step

  1. Read work package A and the inactive TOML draft; confirm name, description and developer_instructions.
  2. Compare the role's owned path with the frozen contract and remove unrelated responsibilities.
  3. Implement or review normalization in the disposable capstone copy, using boundary cases in the tests.
  4. If you choose a real custom-role exercise, place a reviewed copy only in that scratch project's documented agents directory and request that actual role.
  5. Record role-loading evidence separately from code correctness; the inactive draft and deterministic tests prove neither client loading nor isolation.

A useful starting example

Illustration · adapt before use.

Complete role at the documented active path toml
# .codex/agents/practice_normalizer.toml
name = "practice_normalizer"
description = "Implement only the bounded normalization work package in a disposable lab."
developer_instructions = """
Read CONTRACT.md and work package A.
Own starter/normalize.cjs only.
Trim and lowercase supported status strings; reject wrong types and unsupported values per CONTRACT.md.
Preserve unrelated changes and return file evidence and checks.
Do not modify report.cjs, fixtures, tests, runner, baseline, solution or configuration.
"""
# Parent permissions/provider/MCP remain inherited. Prose ownership is not an independent sandbox.


From input to result

A concrete role's expected evidence

The draft role owns only normalization.

Worked input toml
name = "practice_normalizer"
description = "Implement the bounded normalization package."
developer_instructions = "Read CONTRACT.md; own starter/normalize.cjs only; return checks and limits."
Expected result · compare with your run
Required schema fields: present
Owned implementation: one file
Reference cases: padded DONE -> done; null -> TypeError; later -> RangeError

The full inactive TOML is supplied in the lab. These reference expectations are not a claim that Codex loaded it.

Hands-on exercise

Your turn

Adapt the supplied inactive role for work package A, then solve or review that package using the actual contract and tests. Deliver the exact TOML, owned-file diff and checks. Optionally run it through a deliberately chosen scratch Codex custom role; otherwise mark role loading and delegated execution not run. Do not add a fake sandbox override.

Try the exercise before opening its reference answer. Use a disposable practice folder.

Run the practice

Draft a role around an executable ownership contract

Extract into a new practice folder and keep the included labs folder. Run these commands from that extraction root, or from the course folder, using an existing Node.js installation.

  1. Command 1 text
    node --test labs/delegation-capstone/capstone.test.cjs

    Check: 7 reference checks pass against the frozen baseline/ modules and supplied solution/ modules; they do not grade an edited starter.

  2. Command 2 text
    node --test labs/delegation-capstone/candidate.test.cjs

    Check: The unedited starter intentionally fails 4 candidate checks; all 4 should pass after both fixes.

A custom role states behavior; inherited permissions and actual client role loading must be checked separately.

Check your result

  • The draft has the three required TOML fields and makes no independent sandbox/provider/MCP override claim.
  • The normalizer handles padded case and rejects invalid values according to the contract.
  • Actual role loading is evidenced by the client or explicitly marked not run.
Reference answer & rubric Try the exercise before opening

The required three TOML fields define a bounded normalizer role. The role inherits parent permissions and cannot enforce its file ownership through prose alone.

  1. Keep the role name distinct from built-ins to avoid accidental shadowing.
  2. Supply CONTRACT.md, package A and starter/normalize.cjs as explicit task context.
  3. Verify padded strings, non-string rejection and unsupported status behavior against the reference tests.
  4. For a real client run, inspect the role actually used and the diff; do not infer loading from the presence of a TOML file.
Think it through

Check your understanding

What happens if a custom Codex role claims its own mcp_servers configuration?

  1. It automatically creates an isolated connector account.
  2. It does not override the inherited parent MCP configuration.
  3. It grants the role all tools from every server.
Reveal the answer and explanation

Answer 2: It does not override the inherited parent MCP configuration.

Configure connections in the parent session. Role prose and unsupported fields do not establish new server access.

Take this quiz in the interactive lesson to save your answer in the browser.

When it does not work

The agent edits another file despite the role description.

Likely cause: Behavioral instructions were mistaken for a filesystem sandbox.

What to try: Correct scope, inspect the diff and use the parent's actual permission controls as appropriate.

The role is never available in the client.

Likely cause: The draft is inactive or discovery/path/refresh differs from the intended environment.

What to try: Check the documented .codex/agents location and actual client evidence; do not change global permissions to compensate.

Common mistakes

  • Copying .claude/agents/example.md and expecting it to become a Codex custom agent.
  • Claiming a do-not-edit sentence creates a separate read-only sandbox.
Source mapping & differences · different

Codex uses standalone custom-agent TOML and inherited parent controls, not Claude's YAML agent definitions and permissionMode fields.

Source topic: Configuration ↗

Go to the source

Official documentation, checked 21 October 2026. Product names, controls and availability may vary with your version, platform or account.

Continue in the interactive lesson →

Completion and quiz progress are saved
only in the interactive course.