Skip to content

Codex standalone searches collide across Workflow agents sharing a session #131

Description

@momomuchu

Summary

Codex standalone WebSearch keys /alpha/search requests only by the Claude Code session ID. Claude Code Workflow children share that parent session ID but carry distinct direct Agent IDs, so concurrent sibling searches contend on one upstream search session and frequently return 409 Search session is busy after the proxy's internal wait.

This is the same ownership topology addressed for Codex continuation in #95/#96, but the standalone-search path still discards the parsed ConversationIdentity.

Affected snapshot: main@55bf0b5818b461e1860964809726f99d2fd52c10 (also observed on release 0.1.35 with Claude Code 2.1.260/2.1.263).

Observed topology

A Workflow has one Claude session and each child has a stable direct Agent ID:

  • Agent A: session=S, agent=A
  • Agent B: session=S, agent=B

The proxy already parses those headers into ConversationIdentity::Agent(S, A) and ConversationIdentity::Agent(S, B) and uses that identity for continuation ownership.

Current standalone-search path

dispatch_request parses ConversationIdentity and passes it to CodexProvider::handle_messages_with_conversation_identity. In the standalone-search branch, however, src/providers/codex/mod.rs calls:

search::build_search_request(&body, &resolved.model, ctx.session_id.as_deref())

src/providers/codex/search.rs then uses that shared session ID as SearchRequest.id. The direct Agent ID never participates.

Production evidence

Under several concurrent research workflows across three authenticated proxy accounts:

  • 5-minute sample before mitigation: 644 completed requests, 478 status 409, 163 status 200;
  • 409 latency: p50 15.1 s, p95 24.3 s;
  • exact upstream message: Search session is busy after waiting with exponential backoff for the current turn to finish. Retry after a short delay.

A temporary downstream mitigation that removed the shared session header only for forced standalone searches reduced the observed search-session 409 count to zero, but makes each search stateless. The intended fix is stable per-Agent ownership.

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

Expected behavior

Standalone search should follow the existing identity ownership contract:

  • Main: session ID;
  • Agent: (session ID, direct Agent ID);
  • nested Agent: its direct child Agent ID; parent ID remains validation-only;
  • missing/malformed/ambiguous identity: stateless safe fallback.

Two turns from one Agent should retain a stable search owner. Sibling Agents sharing one parent session must receive distinct owners. Ordinary generation, continuation, count-tokens, other providers, and model routing should remain unchanged.

Proposed tests

  1. Same Agent and session produce the same search owner.
  2. Sibling Agents under one session produce different owners.
  3. Same Agent ID under different sessions produces different owners.
  4. Main preserves the existing session owner.
  5. Invalid or absent identity remains stateless.
  6. Standalone-search provider path receives that owner; ordinary generation remains unchanged.

I am preparing a focused PR with the tests first and the minimal identity plumbing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions