Skip to content

fix(tool runner): preserve state across iterations#966

Open
jeanpierrecarvalho wants to merge 1 commit intoanthropics:mainfrom
jeanpierrecarvalho:fix/toolrunner-container-propagation
Open

fix(tool runner): preserve state across iterations#966
jeanpierrecarvalho wants to merge 1 commit intoanthropics:mainfrom
jeanpierrecarvalho:fix/toolrunner-container-propagation

Conversation

@jeanpierrecarvalho
Copy link
Copy Markdown

Fixes #964

Summary

This fixes two related BetaToolRunner iteration-state bugs:

  • carry message.container.id into the next request when the runner receives a container-backed assistant response
  • preserve the current assistant/tool turn when setMessagesParams() changes non-message params between iterations

Root cause

BetaToolRunner treated any setMessagesParams() call as if the message history had been fully replaced.

That caused two bad outcomes:

  • changing something like max_tokens prevented the runner from persisting the current assistant turn before generating the next request
  • when code execution returned a container, that container.id was not forwarded into the next request, which breaks pending tool-use follow-ups

In practice this could cause duplicate tool-call loops and eventually fail with:

container_id is required when there are pending tool uses generated by code execution with tools.

What changed

  • track whether messages were actually replaced, instead of treating every param mutation the same way
  • continue persisting the assistant turn and generated tool result when only non-message params change
  • forward message.container.id into the next request when container was not explicitly set by the caller
  • add regression tests for both behaviors

Validation

  • ./node_modules/.bin/jest tests/lib/tools/ToolRunner.test.ts --runInBand
  • real end-to-end beta.messages.toolRunner() run against the Anthropic API with code_execution_20260120

Before fix

Using upstream/main with the same live repro:

  • request 2 still had container: null
  • the assistant/tool history was dropped when only max_tokens changed
  • the loop repeated the same tool call
  • the API then failed with container_id is required when there are pending tool uses generated by code execution with tools.

After fix

With this branch:

  • request 2 includes the forwarded container
  • request 2 preserves the assistant server_tool_use, assistant tool_use, and generated tool_result
  • the non-message param update (max_tokens) is preserved
  • the loop completes successfully with the final result

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.

Bug: toolRunner does not propagate container.id across iterations, and setMessagesParams causes duplicate tool call loops

1 participant