## Why `core/src/tools/spec.rs` still owned the pure `tool_search` and `tool_suggest` spec builders even though that logic no longer needed `codex-core` runtime state. This change continues the `codex-tools` migration by moving the reusable discovery and suggestion spec construction out of `codex-core` so `spec.rs` is left with the core-owned policy decisions about when these tools are exposed and what metadata is available. ## What changed - Added `codex-rs/tools/src/tool_discovery.rs` with the shared `tool_search` and `tool_suggest` spec builders, plus focused unit tests in `tool_discovery_tests.rs`. - Moved the shared `DiscoverableToolAction` and `DiscoverableToolType` declarations into `codex-tools` so the `tool_suggest` handler and the extracted spec builders use the same wire-model enums. - Updated `core/src/tools/spec.rs` to translate `ToolInfo` and `DiscoverableTool` values into neutral `codex-tools` inputs and delegate the actual spec building there. - Removed the old template-based description rendering helpers from `core/src/tools/spec.rs` and deleted the now-dead helper methods in `core/src/tools/discoverable.rs`. - Updated `codex-rs/tools/README.md` to document that discovery and suggestion models/spec builders now live in `codex-tools`. ## Test plan - `cargo test -p codex-tools` - `CARGO_TARGET_DIR=/tmp/codex-core-discovery-specs cargo test -p codex-core --lib tools::spec::` - `CARGO_TARGET_DIR=/tmp/codex-core-discovery-specs cargo test -p codex-core --lib tools::handlers::tool_suggest::` - `just argument-comment-lint` ## References - #16154 - #15923 - #15928 - #15944 - #15953 - #16031 - #16047 - #16129 - #16132 - #16138 - #16141
codex-tools
codex-tools is intended to become the home for tool-related code that is
shared across multiple crates and does not need to stay coupled to
codex-core.
Today this crate is intentionally small. It currently owns the shared tool
schema and Responses API tool primitives that no longer need to live in
core/src/tools/spec.rs or core/src/client_common.rs:
JsonSchemaAdditionalPropertiesToolDefinitionToolSpecConfiguredToolSpecResponsesApiToolFreeformToolFreeformToolFormatToolSearchOutputToolResponsesApiWebSearchFiltersResponsesApiWebSearchUserLocationResponsesApiNamespaceResponsesApiNamespaceTool- code-mode
ToolSpecadapters andexec/waitspec builders - JS REPL spec builders
- MCP resource,
list_dir, andtest_sync_toolspec builders - local host tool spec builders for shell/exec/request-permissions/view-image
- collaboration and agent-job
ToolSpecbuilders for spawn/send/wait/close,request_user_input, and CSV fanout/reporting - tool discovery and suggestion models /
ToolSpecbuilders fortool_searchandtool_suggest parse_tool_input_schema()parse_dynamic_tool()parse_mcp_tool()create_tools_json_for_responses_api()mcp_call_tool_result_output_schema()tool_definition_to_responses_api_tool()dynamic_tool_to_responses_api_tool()mcp_tool_to_responses_api_tool()mcp_tool_to_deferred_responses_api_tool()augment_tool_spec_for_code_mode()tool_spec_to_code_mode_tool_definition()
That extraction is the first step in a longer migration. The goal is not to
move all of core/src/tools into this crate in one shot. Instead, the plan is
to peel off reusable pieces in reviewable increments while keeping
compatibility-sensitive orchestration in codex-core until the surrounding
boundaries are ready.
Vision
Over time, this crate should hold tool-facing primitives that are shared by multiple consumers, for example:
- schema and spec data models
- tool input/output parsing helpers
- tool metadata and compatibility shims that do not depend on
codex-core - other narrowly scoped utility code that multiple crates need
The corresponding non-goals are just as important:
- do not move
codex-coreorchestration here prematurely - do not pull
Session/TurnContext/ approval flow / runtime execution logic into this crate unless those dependencies have first been split into stable shared interfaces - do not turn this crate into a grab-bag for unrelated helper code
Migration approach
The expected migration shape is:
- Move low-coupling tool primitives here.
- Switch non-core consumers to depend on
codex-toolsdirectly. - Leave compatibility-sensitive adapters in
codex-corewhile downstream call sites are updated. - Only extract higher-level tool infrastructure after the crate boundaries are clear and independently testable.
That means it is normal for codex-core to temporarily re-export types or
helpers from codex-tools during the transition.
Crate conventions
This crate should start with stricter structure than core/src/tools so it
stays easy to grow:
src/lib.rsshould remain exports-only.- Business logic should live in named module files such as
foo.rs. - Unit tests for
foo.rsshould live in a siblingfoo_tests.rs. - The implementation file should wire tests with:
#[cfg(test)]
#[path = "foo_tests.rs"]
mod tests;
If this crate starts accumulating code that needs runtime state from
codex-core, that is a sign to revisit the extraction boundary before adding
more here.