Skip to content

Duplicate tool calls with cx@ / OpenAI Codex Responses adapter #141

@YamadaHideki

Description

@YamadaHideki

Summary

When running Claude Code through Claudish with the cx@ / OpenAI Codex provider, tool calls are duplicated. The same assistant message and the same tool_use.id appear twice in the Claude Code transcript, causing Claude Code to execute the same tool twice.

This happens even when Claudish debug mode is disabled.

Environment

  • Claudish version: 7.4.0
  • Node path: /home/example-user/.nvm/versions/node/v24.15.0/bin/claudish
  • Provider/model used: cx@gpt-5.5 and cx@gpt-5.5:1
  • Provider shown in Claudish logs: openai-codex
  • Stream adapter involved: openai-responses-sse
  • Claude Code version in transcript metadata: 2.1.139
  • OS: Linux / Arch

Impact

Any tool call can be executed twice, including non-idempotent operations.

Observed duplicated tools include:

  • Bash
  • Read
  • Edit
  • Write
  • TaskUpdate
  • AskUserQuestion
  • EnterPlanMode
  • MCP tools such as mcp__chrome-devtools__*

This can cause duplicate dev servers, duplicate builds, duplicate edits, duplicate task updates, and other unintended side effects.

Concrete example

In this session, a single npm run dev tool call was duplicated and resulted in two identical shell processes being started.

Process list showed two child processes under the same Claude process:

/usr/bin/zsh -c ... eval 'npm run dev' ...
/usr/bin/zsh -c ... eval 'npm run dev' ...

The Claude Code transcript contains two adjacent assistant entries with the same message.id and the same tool_use.id:

line 1383: message_id msg_1780902599569, tool_use_id toolu_call_8FDMksvL5FZlsEWibjcLDTnW, Bash: npm run dev
line 1384: message_id msg_1780902599569, tool_use_id toolu_call_8FDMksvL5FZlsEWibjcLDTnW, Bash: npm run dev

Transcript path used for investigation:

/home/example-user/.claude/projects/-home-example-user-projects-sample-web-app/350bfa23-c318-425c-af9d-1b6be353c303.jsonl

Frequency

This is not isolated to one command. In the same transcript, duplicate assistant message ids were counted:

assistant message ids duplicated: 209

Examples from the transcript include repeated adjacent tool calls with the same tool_use.id:

npm create vite@latest . -- --template react-ts
mkdir -p src/api src/components src/features/auth src/features/monitoring src/styles
npm install
npm run build
npm run dev
git status --short
Read
Edit
TaskUpdate
mcp__chrome-devtools__navigate_page
mcp__chrome-devtools__take_snapshot

Important detail

The duplicated entries reuse the same Claude/Anthropic tool id, not just semantically similar tool calls.

Example:

same message.id:   msg_1780902599569
same tool_use.id:  toolu_call_8FDMksvL5FZlsEWibjcLDTnW
same tool name:    Bash
same command:      npm run dev

This suggests the duplicate is being emitted or forwarded before Claude Code executes tools. Claude Code then executes both entries.

Relevant Claudish log excerpt

Claudish log for one affected run:

Claudish Session Log - 2026-06-08T07:08:51.513Z
Mode: structural (content redacted)

[2026-06-08T07:08:51.534Z] [Proxy] Registered 1 custom endpoint(s) from config
[2026-06-08T07:08:51.537Z] [Proxy] Server started on port 6862
[2026-06-08T07:09:57.406Z] [Proxy] Handler: provider=openai-codex, model=gpt-5.5
[2026-06-08T07:09:57.408Z] [Proxy] Created OpenAI Codex handler (composed): gpt-5.5
[2026-06-08T07:09:59.566Z] [Openai-codex] Response status: 200

Debug mode is not required to reproduce the bug; the debug log only helped confirm which provider and adapter were being used.

Suspected area

The issue appears related to the openai-responses-sse adapter for the OpenAI Codex / cx@ provider.

In the installed bundled file:

/home/example-user/.nvm/versions/node/v24.15.0/lib/node_modules/claudish/dist/index.js

Relevant sections:

line 32134: // src/handlers/shared/stream-parsers/openai-responses-sse.ts
line 32218: event.type === "response.output_item.added"
line 32240: send("content_block_start", { ... content_block: { type: "tool_use", id: callId, ... } })
line 32272: event.type === "response.output_item.done"

Hypothesis: the OpenAI Responses stream can emit repeated response.output_item.added or otherwise repeated function-call events for the same call_id / item_id, and Claudish forwards them as duplicate Anthropic tool_use content blocks without deduplication.

Expected behavior

For a given assistant message, each tool call should be emitted once. A repeated response.output_item.added / function-call event with the same OpenAI call_id or same derived Anthropic tool_use.id should not cause a second Anthropic tool_use block to be sent.

Actual behavior

The same tool call is emitted twice with the same tool_use.id, and Claude Code executes it twice.

Suggested fix

Add idempotency/deduplication in the OpenAI Responses SSE parser before emitting content_block_start for tool_use.

Possible approach:

  • Track seen/opened function calls by OpenAI call_id, OpenAI item.id, and derived Anthropic claudeId.
  • If a function call has already emitted content_block_start, do not emit another start block for the same call.
  • Continue appending argument deltas only once per streamed delta.
  • Ensure content_block_stop is emitted once per opened function call.

Pseudo-shape:

const emittedToolUseIds = new Set<string>();

// before send("content_block_start", tool_use)
if (emittedToolUseIds.has(callId)) {
  continue;
}
emittedToolUseIds.add(callId);

It may be safer to dedupe on all of these keys:

openaiCallId
itemId
callId // derived Anthropic tool_use.id

Workaround

Avoid using cx@... / openai-codex for tool-heavy Claude Code sessions until fixed. Use another provider path such as OpenRouter or non-Responses OpenAI routing if available.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions