Skip to content

feat(agents): let codex and opencode agents select built-in tools - #465

Merged
aidan-sims merged 6 commits into
mainfrom
aidan/fde-2584-builtin-tools-codex-opencode
Nov 4, 2026
Merged

aidan-sims merged 6 commits into
mainfrom
aidan/fde-2584-builtin-tools-codex-opencode

Conversation

@aidan-sims

@aidan-sims aidan-sims commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Owner: Aidan Sims

The codex and opencode agents had no way to turn off their CLI's own tools, so a task that needs strict no-tools (FDE-2584) still offered shell, edit and similar tools to the model. Both agents now accept a builtin_tools selection ({"disable": "*" | [...]} or {"only": [...]}) in their agent config, as claude_code already does. With no selection, the config and argv stay exactly as before.

  • opencode: the selection becomes opencode's permission config. disable: "*" and only deny "*" but still allow agent-env's MCP tools (<server>_*) and the CLI's two non-tool checks (external_directory, doom_loop). Without them, MCP tools disappear and kept file tools refuse paths outside the workspace.
  • codex: the selection becomes -c overrides added after the role overrides (for example features.shell_tool=false). Codex turns some tools on and off together, so a list must name a whole group (for example exec_command with write_stdin), otherwise it is rejected.
  • codex apply_patch: no setting turns it off; each GPT model's catalog entry offers it. When a selection drops it, the agent writes a copy of the CLI's own catalog (codex debug models --bundled, or the model_catalog_json config.toml names) with apply_patch_tool_type: null and passes it with -c model_catalog_json=.... The copy is made from the installed CLI, so it follows the pinned version. If the catalog can't be read, the turn fails instead of keeping the tool.
  • Each card's agent-config schema lists the tool names as an enum, so deploy_agent accepts a selection.

Validation: pytest tst/unit/agents/opencode tst/unit/agents/codex tst/unit/task_step/test_verify_a2a_builtin_tools.py tst/unit/agents/claude_code gives 592 passed and 39 skipped, and the new tests fail on main. ruff check is clean on the touched files. ruff format --check fails on them, and the files weren't reformatted. With the pinned CLIs (opencode-ai 1.17.18, codex 0.147.0) and a local fake model, opencode under disable: "*" offers only the MCP tool, and codex on gpt-5.4 offers no tools (only its MCP tools when an MCP server is configured).

Not in this PR:

  • A run of either agent image (the pinned CLIs were run directly instead).
  • The ticket's AC2 expects exactly {"*": "deny"}. This PR adds the allows above so agent-env's MCP tools stay available.
  • The ticket's AC3 expects per-tool lists for codex. Grouped tools must be listed together instead.
  • Publishing new hub agent versions (done separately by Env Pod after release).

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge, with no new actionable findings.

Summary

Adds builtin_tools selections to the Codex and OpenCode agents while preserving their default behavior and MCP tools.

  • Codex turns agent tool selections into per-turn CLI settings.
  • OpenCode agent settings can narrow the tools a turn receives.

There are no changes since the previous reviewed revision. No new actionable issues were found.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A["Agent config: builtin_tools"] --> B{"Agent"}
  B -->|OpenCode| C["Build permission rules"]
  C --> D["Run OpenCode with MCP tools preserved"]
  B -->|Codex| E["Build tool settings"]
  E --> F{"Remove apply_patch?"}
  F -->|Yes| G["Copy catalog with apply_patch disabled"]
  F -->|No| H["Run Codex"]
  G --> H
Loading

Reviews (3) · Last reviewed commit: "ci: retrigger Integration Tests" · Reviewed by Greptile

aidan-sims and others added 4 commits November 3, 2026 10:15
OpenCodeConfig takes builtin_tools, as claude-code's does (#437), and turns it into the
config's permission: a denied tool is left out of the model's tool list. disable "*" and
only keep the tools of agent-env's MCP servers, which a "*" deny would also remove. The
names are opencode-ai 1.17.18's permission names. Without a selection the config and argv
are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodexConfig takes builtin_tools and turns it into -c overrides on the turn's CLI. disable "*"
also turns off the multi_agent_v2 collaboration tools. The MCP tools agent-env gives the agent
stay. Tools that one setting switches together must be named together. apply_patch is left
out: codex 0.147.0 has no setting that turns it off. Without a selection the overrides are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ool selection

With {"disable": "*"} or {"only": [...]}, the permission's "*": "deny" also
denied external_directory, so a kept read or edit could no longer reach a
path outside the workspace, and doom_loop. Both stay allowed, as they are
without a selection. A new agent-level test checks that the agent passes
the stored selection to each turn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… selection drops it

No codex 0.147.0 setting removes apply_patch: the model catalog offers it to every bundled GPT model through
apply_patch_tool_type. When a builtin_tools selection drops it (disable "*", a disable list naming it, or an only
list without it), the agent now writes a copy of the catalog the CLI would use, from `codex debug models --bundled`
or the file config.toml's model_catalog_json names, with apply_patch_tool_type null for every model, under
CODEX_HOME, and points the turn's CLI at it with -c model_catalog_json. apply_patch joins CodexTool. With no
selection, or one that keeps apply_patch, the overrides and config.toml are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aidan-sims
aidan-sims marked this pull request as ready for review November 3, 2026 16:08
@aidan-sims
aidan-sims requested a review from a team as a code owner November 3, 2026 16:08
aidan-sims and others added 2 commits November 3, 2026 11:26
…t on cancel

The catalog read now counts against timeout_seconds, run_codex gets what is left,
and a timed-out or cancelled read kills its `codex debug models` child. Names the
stderr tail limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aidan-sims
aidan-sims merged commit 80c93eb into main Nov 4, 2026
40 of 42 checks passed
@aidan-sims
aidan-sims deleted the aidan/fde-2584-builtin-tools-codex-opencode branch November 4, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants