Skip to content

Replace codex-agent-driver with the official openai-codex SDK - #53

Merged
nabinpkl merged 1 commit into
mainfrom
refactor/codex-sdk-migration
Jun 6, 2026
Merged

Replace codex-agent-driver with the official openai-codex SDK#53
nabinpkl merged 1 commit into
mainfrom
refactor/codex-sdk-migration

Conversation

@nabinpkl

@nabinpkl nabinpkl commented Jun 6, 2026

Copy link
Copy Markdown
Owner

What

Migrates the codex agent runtime off the hand-written codex-agent-driver path-dependency (sibling second-brain repo) and onto OpenAI's official openai-codex Python SDK. The SDK is the harness the driver emulated — it drives codex app-server, exposes native threads, streams typed notifications, supports read-only sandbox + server-enforced output_schema, and bundles the codex binary. Recorded in ADR 17 (supersedes ADR 15's mechanism).

Agent plane (agent-service/)

  • One shared AsyncCodex app-server at lifespan; each chat thread is one native codex thread (thread_start / thread_resume). Drops the per-thread codex_home machinery (CODEX_HOME_ROOT), the state-sqlite model-read hack, and the worker-thread/queue bridge in favour of async for over the SDK turn stream.
  • codex_config.py — per-thread config overlay mounting the data-plane MCP server (four-tool allow-list) + the built-in-tool lockdown, plus the writable-CODEX_HOME builder.
  • codex_events.py — parses the SDK's typed notifications back to their camelCase wire dict, insulating the driver from beta SDK attribute churn.
  • Helper calls (constitution gate / eval judge / repeat detector) run on a separate codex helper app-server (own CODEX_HOME, ephemeral threads, no MCP) — preserves the no-bleed separation.
  • codex_profile.py removed; tests, smoke script, env, Docker, compose, and CI (agent-service job re-enabled) updated. SDK is Beta, pinned exactly with the accepted risk in docs/dependency-exceptions.md.

Data plane (backend/src/mcp.rs)

The bundled codex (0.137) forwards MCP tool input schemas to the OpenAI API verbatim, which rejects a root $ref schema in strict mode. The three transparent-newtype args (wallet_profile, community_summary, get_token_info) now implement JsonSchema manually to inline the object at the root. Regenerated the tools/list snapshot consumed by the hermetic-eval mock.

Evals

model_assertions_codex.yaml asserted the constitution gate uses the pydantic-ai policy model, contradicting the all-or-nothing helper routing (under codex runtime the gate runs via codex and emits no gen_ai model span). Replaced that probe with a functional "gate fired" check; re-minted the baseline.

Verification

  • 345 agent-service unit tests pass (<5s, no live LLM); 360 collect clean; ruff clean on edited files.
  • 22 backend mcp:: tests pass (incl. schema snapshot drift test).
  • Full stack docker compose up -d --build; live codex turns confirmed: token streaming, wallet_profile MCP dispatch, lockdown, model stamping, constitution gate fires + approves.
  • Codex live-eval suite 5/5 pass (turn-root, codex-primary-model-used, no-error, no-builtin-tool-call, constitution-gate-fired).

🤖 Generated with Claude Code

@nabinpkl
nabinpkl force-pushed the refactor/codex-sdk-migration branch 2 times, most recently from 5012e3c to 20a172e Compare June 6, 2026 20:24
Swap the codex agent runtime off the hand-written codex-agent-driver
path-dependency (sibling second-brain repo) and onto OpenAI's official
openai-codex Python SDK. The SDK is the harness the driver emulated:
it spawns and drives `codex app-server`, exposes native threads, streams
typed notifications, supports read-only sandbox and server-enforced
output_schema, and bundles the codex binary. ADR 17 records the
decision and supersedes ADR 15's mechanism.

Agent plane (agent-service/):
- One shared AsyncCodex app-server built at lifespan; each chat thread
  is one native codex thread (thread_start / thread_resume). Drops the
  per-thread codex_home machinery (CODEX_HOME_ROOT), the state sqlite
  model-read hack, and the worker-thread/queue bridge in favour of
  `async for` over the SDK turn stream.
- codex_config.py: the per-thread config overlay that mounts the
  data-plane MCP server (four-tool allow-list) and disables every codex
  built-in tool (lockdown), plus the writable-CODEX_HOME builder.
- codex_events.py: parses the SDK's typed notifications back to their
  camelCase wire dict so the driver is insulated from beta SDK
  attribute churn.
- Helper calls (constitution gate, eval judge, repeat detector) run on
  a separate codex helper app-server (own CODEX_HOME, ephemeral threads,
  no MCP), preserving the no-bleed separation.
- codex_profile.py removed; tests, smoke script, env, Docker, and
  compose updated. The SDK is Beta, pinned exactly with the accepted
  risk recorded in docs/dependency-exceptions.md.

Data plane (backend/src/mcp.rs):
- The bundled codex (0.137) forwards MCP tool input schemas to the
  OpenAI API verbatim, which rejects a root $ref schema in strict mode.
  The three transparent-newtype args (wallet_profile, community_summary,
  get_token_info) now implement JsonSchema manually to inline the object
  at the root instead of emitting a root $ref. Regenerated the
  tools/list snapshot consumed by the hermetic-eval mock.

Evals:
- model_assertions_codex.yaml asserted the constitution gate uses the
  pydantic-ai policy model, which contradicts the all-or-nothing helper
  routing: under codex runtime the gate runs via codex and emits no
  gen_ai model span. Replaced that probe with a functional check that
  the gate fires, and re-minted the baseline.

CI:
- This commit introduces the CI workflow (.github/workflows/ci.yml was
  previously untracked), so its first run had to be made green. The
  backend job installs the librdkafka build deps (libcurl/sasl/zlib) the
  Dockerfile uses; frontend and wire-drift use pnpm 10 (pnpm 9 rejects
  the settings-only pnpm-workspace.yaml); wire-drift pins protoc 34.1
  for the buf python plugin; the re-enabled agent-service job runs the
  documented <5s unit baseline (the integration suite has pre-existing
  pytest_httpx mock drift, excluded until repaired separately).
- Regenerated the switches wire types (Rust + TS): the .proto doc
  comment had been edited without re-running codegen, so the committed
  generated files were stale. Doc-comment-only delta, no schema change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nabinpkl
nabinpkl force-pushed the refactor/codex-sdk-migration branch from 20a172e to c502e46 Compare June 6, 2026 20:27
@nabinpkl
nabinpkl merged commit efde097 into main Jun 6, 2026
4 checks passed
@nabinpkl
nabinpkl deleted the refactor/codex-sdk-migration branch June 6, 2026 20:50
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.

1 participant