Claude Sonnet 3.7 is calling tools in a loop sometimes
I'm using the Vercel AI SDK with this OpenRouter provider in my Next.js project. I'm streaming text from the Sonnet 3.7 "online" model to my front end with it.
I'm also using tools with that SDK, and I frequently get a tool call loop, meaning the same tool with the same parameters gets called repeatedly for seemingly no reason. The only way to stop it is to stop the stream altogether, otherwise, it just keeps going.
Added onToolCallResult and onStepFinish to log tool results, and it all looks like it should in the tool response, also, no errors are logged.
When I'm using the Anthropic provider directly, so directly going to the Anthropic API, this doesn't happen.
"ai": "^4.2.8", "@openrouter/ai-sdk-provider": "^0.4.5",
I think the bug is because OpenRouter tool_call_id is so simple (not unique as other providers). So let say
- In 1 turn first request, it trigger 2 tools call (id : "tool_0_readfile", id: "tool_1_readfile" )
- Then after requests, it trigger other tool calls (but still count from 0, let say id : "tool_0_readfile", id: "tool_1_writefile" ) => So even 2 tools call is different time, different intent, it has same ID => conflict with old toolcall
I think we should fix this, add something random into id each toolcall so it's unique
Thanks
Thanks @khanhicetea for looking into this! By the way, I didn't get this one anymore after upgrading to the latest version of the provider package, so maybe this is solved...
But what you are saying sounds somewhat related to this issue https://github.com/OpenRouterTeam/ai-sdk-provider/issues/45 that I'm also still experiencing, would be nice if your suggested solution would solve both once and for all.
I think the @OpenRouterTeam can fix it by add unique random string into tool_call_id format Until it, I have to add the message_id into prefix of tool_call_id to generate new tool_call_id in my code
Hey @khanhicetea, are you achieving that fix via a patch to this package or as an external user? Do you have an example?
@peterje temporary way is write a middleware then transform the tool_call_id into unique id