Skip to content

fix(codex): isolate standalone search per Claude Agent - #132

Open
momomuchu wants to merge 1 commit into
raine:mainfrom
momomuchu:fix/agent-owned-standalone-search
Open

fix(codex): isolate standalone search per Claude Agent#132
momomuchu wants to merge 1 commit into
raine:mainfrom
momomuchu:fix/agent-owned-standalone-search

Conversation

@momomuchu

Copy link
Copy Markdown

Summary

Codex standalone WebSearch identified its upstream search session only by the Claude Code session ID. Claude Code Workflow children share that parent session while carrying distinct direct Agent IDs, so sibling searches contended on one upstream search session and returned 409 Search session is busy after the proxy's internal wait.

This applies the ownership contract already established for continuation in #95/#96 to the standalone-search path.

Fixes #131.

Ownership model

  • Main: the Claude Code session ID, byte-identical to current behavior.
  • Agent: a stable, bounded, domain-separated SHA-256 owner derived from the validated (session ID, direct Agent ID) pair, length-prefixed so no delimiter shift can alias two different tuples.
  • Nested Agent: keyed by its own direct Agent ID; the parent Agent ID remains validation-only.
  • Missing, malformed, duplicated, or ambiguous identity: unchanged stateless search-<uuid> fallback.

The raw session and Agent IDs are never sent in the derived owner, and the owner has fixed length regardless of input size.

Change

CodexProvider::handle_messages_inner already receives the parsed ConversationIdentity; the standalone-search branch now passes it to search::build_search_request instead of ctx.session_id.

The same owner also had to reach the wire headers. post_search threads SearchRequest.id through attempt_post_search into build_codex_search_headers, which overrides session_id, x-client-request-id, and x-codex-window-id (<id>:0) for search requests only. Without that, the body was agent-scoped while the headers still carried the shared parent session.

Ordinary generation, continuation, compaction, count-tokens, model routing, and other providers are untouched.

Tests

  • request_identity: same agent stable; siblings distinct; same agent across sessions distinct; length-prefix boundary case (session-aa/gent-a vs session-a/agent-a); bounded length; no raw ID disclosure; Main preserved.
  • providers::codex::search: Main preserves the raw session ID; agent owners stable and isolated; absent identity yields fresh distinct IDs; the existing forced-vs-automatic negative control is unchanged.
  • tests/smoke_cutover.rs::codex_standalone_search_uses_conversation_identity_owner: drives /v1/messages end to end against a mock upstream and asserts all four identity carriers agree, siblings differ, differing parents do not change the owner, Main stays raw, and missing/malformed identity stays stateless.

Validation

just check-ci on the committed tree:

  • format-check
  • clippy (-D warnings) ✓
  • build
  • test ✓ (866 lib + 5 bin + all integration suites, including codex_agent_continuation 12/12)

Measured effect

Local fleet, three authenticated Codex accounts, several concurrent research workflows.

Before, five-minute window: 644 completions, 478 409, 163 200; 409 latency p50 15.1 s, p95 24.5 s.

After, running this build: an eight-agent Workflow issued 24 WebSearch and 8 WebFetch calls across 8 distinct Agent IDs with 0 tool errors, and the proxy log after cutover shows 964 completions, 0 failures, 31 completed searches at p50 2.0 s, p95 3.0 s.

No credentials, request bodies, or target data are included.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

Codex standalone searches collide across Workflow agents sharing a session

1 participant