Skip to content

fix(compose): stabilize duplicate tool call identities - #1480

Open
30bef100w wants to merge 1 commit into
cloudwego:mainfrom
30bef100w:fix/stable-tool-call-identities
Open

30bef100w wants to merge 1 commit into
cloudwego:mainfrom
30bef100w:fix/stable-tool-call-identities

Conversation

@30bef100w

Copy link
Copy Markdown

What type of PR is this?

fix

Check the PR title.

  • The title follows Conventional Commits.
  • The title describes the user-visible fix.
  • Separate user documentation PR (compatibility notes are included in this repository).

Description

ToolsNode currently aliases tool execution addresses and checkpoint result maps when a model emits empty or duplicate tool-call IDs. Assign deterministic batch-local keys to those calls, reserve the generated namespace against all model IDs, and use the same tool-name/key address for execution and legacy interrupt wrapping. Unique non-empty IDs retain their existing keys. Model-facing ToolCallID values and GetToolCallID remain unchanged.

Use the keys consistently in completed-result maps, rerun metadata and stream checkpoint bookkeeping. ToolCallKeys maps public interrupt metadata back to ToolCalls without requiring consumers to parse the key format.

Refs #1290. This keeps the batch-info accessor work in #1289 separate. It fixes legacy address inconsistency, but does not claim to fix the separate legacy UUID-based resume problem tracked by #1269.

Persisted checkpoint compatibility

New checkpoints carry a key-format version. Old ambiguous-ID checkpoints fail before dispatch because their completed-result maps may already have lost information; silently replaying those tools can repeat side effects. Old unique-ID modern checkpoints retain their address/key format. Legacy wrapper addresses change and old legacy interrupts are not transparently migrated. See docs/tool-call-checkpoint-identities.md for details and rollback limitations. Maintainer review of this compatibility policy is requested.

Validation

  • New public-behavior regression tests fail on the original tool_node.go at 4a4b718: 12 duplicate/empty/collision selective-resume cases and 2 legacy address-consistency cases fail; the 4 unique-ID control cases pass.
  • With this patch, selective resume passes for empty, repeated, generated-key-like and unique IDs, with both Invoke/Stream and parallel/sequential execution. Tests verify exact outputs, preserved original IDs, stable addresses and that completed tools are not replayed.
  • Additional tests cover old ambiguous-checkpoint rejection and standard/enhanced stream checkpoint result maps.
  • go test ./compose -count=1: PASS.
  • go vet ./compose: PASS.
  • golangci-lint run --new-from-rev=4a4b7186693d9805539c7f0c36db7d03a3485c6a ./compose/...: 0 issues.
  • git diff --check: PASS.
  • Full-repository tests, production workloads and legacy UUID-based selective resume are not claimed as validated.

Implemented and tested with OpenAI Codex at the author's request. Independent human author review has not been completed; maintainer review is requested.

@CLAassistant

CLAassistant commented Nov 10, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants