The Tool System manages the registration, configuration, orchestration, and execution of tools that the model can invoke during a conversation turn. It provides a unified framework for:
For information about MCP-specific tool configuration and external server management, see MCP. For sandbox implementation details, see Sandboxing Implementation.
The ToolsConfig struct determines which tools are available for a given session based on feature flags, model capabilities, and configuration settings.
Diagram: Tool Configuration Flow
Sources: codex-rs/core/src/tools/spec.rs36-122
The ToolsConfig::new() method evaluates features and model capabilities to determine:
| Configuration Field | Determined By | Possible Values |
|---|---|---|
shell_type | Feature::UnifiedExec, Feature::ShellTool, Feature::ShellZshFork, ConPTY availability | UnifiedExec, ShellCommand, Disabled |
apply_patch_tool_type | ModelInfo::apply_patch_tool_type, Feature::ApplyPatchFreeform | Freeform, Function, None |
web_search_mode | Config web_search_mode setting | Live, Cached, Disabled |
search_tool | Feature::Apps | true / false |
collab_tools | Feature::Collab | true / false |
js_repl_enabled | Feature::JsRepl | true / false |
Sources: codex-rs/core/src/tools/spec.rs57-111
Tool availability is controlled by feature flags defined in the Feature enum:
Sources: codex-rs/core/src/features.rs71-146 codex-rs/core/src/tools/spec.rs63-109
Tools are defined using a JsonSchema enum that represents a subset of JSON Schema sufficient for tool parameter definitions:
Sources: codex-rs/core/src/tools/spec.rs124-178
Tools are represented as either Function or Freeform tool specifications:
| Spec Type | Structure | Use Case |
|---|---|---|
ToolSpec::Function(ResponsesApiTool) | Structured JSON parameters with name, description, parameters: JsonSchema | Shell commands, apply_patch (JSON variant), MCP tools |
ToolSpec::Freeform(FreeformTool) | Grammar-based parsing with type, format, grammar, description | apply_patch (freeform variant) with Lark grammar |
Sources: codex-rs/core/src/tools/spec.rs1-30 codex-rs/core/src/tools/handlers/apply_patch.rs37-38
exec_command Tool
Sources: codex-rs/core/src/tools/spec.rs221-294
apply_patch Tool (Function variant)
Sources: codex-rs/core/src/tools/spec.rs997-1018
All tool implementations satisfy the ToolHandler trait:
Sources: codex-rs/core/src/tools/registry.rs50-100 (inferred from handler implementations)
| Handler | Tool Names | Kind | Purpose |
|---|---|---|---|
ShellHandler | shell | Function / LocalShell | Execute shell commands via execvp() |
ShellCommandHandler | shell_command | Function | Execute shell scripts via user's default shell |
UnifiedExecHandler | exec_command, write_stdin | Function | Interactive PTY-backed execution sessions |
ApplyPatchHandler | apply_patch | Function / Custom | Parse and apply file patches |
McpHandler | mcp__* (prefixed) | Function | Route calls to external MCP servers |
MultiAgentHandler | spawn_agent, send_input, wait, close_agent | Function | Multi-agent orchestration |
RequestUserInputHandler | request_user_input | Function | Elicit structured input from user |
ViewImageHandler | view_image | Function | Load and display local images |
ReadFileHandler | read_file | Function | Read file contents with indentation awareness |
GrepFilesHandler | grep_files | Function | Search files by regex pattern |
SearchToolBm25Handler | search_tool_bm25 | Function | BM25 search over app/MCP tools |
Sources: codex-rs/core/src/tools/handlers/mod.rs1-52
The ToolOrchestrator provides a unified execution pipeline for tools that require approval and sandboxing:
Diagram: Tool Orchestration Flow
Sources: codex-rs/core/src/tools/orchestrator.rs1-300 (inferred structure)
The ExecApprovalRequirement determines when user approval is needed:
| Policy | Condition | Behavior |
|---|---|---|
NoApprovalRequired | Known safe command or approval policy is Never | Execute immediately |
RequireApproval { ... } | Mutating command with OnRequest policy | Prompt user with justification |
BypassApprovalByTrustRule | Command matches trusted prefix rule | Execute with cached approval |
Sources: codex-rs/core/src/exec_policy.rs1-200 (inferred from usage patterns)
The orchestrator selects a sandbox backend based on platform and policy:
Sources: codex-rs/core/src/sandboxing/mod.rs1-500 (inferred)
Three shell tool variants are available depending on configuration:
Diagram: Shell Tool Selection
Sources: codex-rs/core/src/tools/spec.rs71-84
The ShellCommandHandler wraps user commands in the default shell:
Sources: codex-rs/core/src/tools/handlers/shell.rs83-106 codex-rs/core/src/tools/handlers/shell.rs254-368
Shell tools inherit environment variables from the turn context and apply unified exec conventions:
NO_COLOR=1
TERM=dumb
LANG=C.UTF-8
LC_CTYPE=C.UTF-8
LC_ALL=C.UTF-8
COLORTERM=
PAGER=cat
GIT_PAGER=cat
GH_PAGER=cat
CODEX_CI=1
Sources: codex-rs/core/src/unified_exec/process_manager.rs55-66
The UnifiedExecProcessManager orchestrates interactive PTY sessions for the exec_command and write_stdin tools:
Diagram: Unified Exec Architecture
Sources: codex-rs/core/src/unified_exec/mod.rs118-161 codex-rs/core/src/unified_exec/process_manager.rs1-100
Process IDs are allocated deterministically in tests and randomly in production:
Sources: codex-rs/core/src/unified_exec/process_manager.rs106-133
Diagram: exec_command Execution
Sources: codex-rs/core/src/tools/handlers/unified_exec.rs108-246 codex-rs/core/src/unified_exec/process_manager.rs157-295
Subsequent write_stdin calls reuse the persisted process:
Sources: codex-rs/core/src/unified_exec/process_manager.rs297-400
The start_streaming_output task continuously reads from the PTY and emits delta events:
Sources: codex-rs/core/src/unified_exec/async_watcher.rs39-101 codex-rs/core/src/unified_exec/async_watcher.rs142-172
The spawn_exit_watcher emits ExecCommandEnd when the PTY exits, even if no further tool calls are made:
Sources: codex-rs/core/src/unified_exec/async_watcher.rs106-140
The intercept_apply_patch function detects when shell commands contain apply_patch invocations and routes them to specialized handling:
Sources: codex-rs/core/src/tools/handlers/apply_patch.rs173-230 codex-rs/core/src/tools/handlers/unified_exec.rs171-185
Apply patch can execute in two modes:
| Mode | Condition | Behavior |
|---|---|---|
| Internal | Patch targets single directory with simple operations | Directly apply using Rust file operations |
| Delegated | Complex patches, approval required, or cross-directory | Execute via PatchApplyRuntime with sandbox |
Sources: codex-rs/core/src/apply_patch.rs1-300 (inferred)
Diagram: Delegated Patch Execution
Sources: codex-rs/core/src/tools/runtimes/apply_patch.rs1-200 (inferred)
The freeform apply_patch tool uses a Lark grammar to parse patch syntax:
*** Begin Patch
*** Add File: path/to/new/file.txt
+First line of new file
+Second line of new file
*** Update File: path/to/existing/file.txt
-Old line to remove
+New line to add
*** Move File: old/path.txt -> new/path.txt
*** Delete File: path/to/delete.txt
*** End Patch
Sources: codex-rs/core/src/tools/handlers/apply_patch.rs37
The ToolEmitter enum provides zero-allocation event emission for different tool types:
Sources: codex-rs/core/src/tools/events.rs90-149
Each tool emitter handles three stages:
Sources: codex-rs/core/src/tools/events.rs52-62 codex-rs/core/src/tools/events.rs151-280
Tool output is formatted differently for structured vs freeform tools:
Structured (shell, exec_command)
Exit code: 0
Duration: 1.234 seconds
Stdout:
<output>
Stderr:
<errors>
Freeform (shell_command)
<output>
Sources: codex-rs/core/src/tools/format.rs1-200 (inferred from usage)
| Event Type | Emitted By | Purpose |
|---|---|---|
ExecCommandBegin | Shell tools, unified exec | Signal command start with parsed command structure |
ExecCommandOutputDelta | Unified exec streaming task | Stream PTY output in real-time |
ExecCommandEnd | Shell tools, unified exec | Signal command completion with exit code and aggregated output |
PatchApplyBegin | Apply patch handler | Signal patch application start with file changes preview |
PatchApplyEnd | Apply patch handler | Signal patch completion with success status |
TerminalInteraction | write_stdin handler | Record stdin written to PTY session |
TurnDiff | Turn diff tracker | Summarize file modifications at turn end |
Sources: codex-rs/core/src/protocol/event.rs1-500 (inferred from event definitions)
Every tool handler receives a ToolInvocation containing all necessary context:
Sources: codex-rs/core/src/tools/context.rs1-100 (inferred structure)
Primary source files for this documentation:
Refresh this wiki