Fix: Ensure step messages represent input only#884
Conversation
…dStep in text handlers
277c64f to
041d7de
Compare
|
@sixlive Currently after this change:
I'm questioning whether The concern: We're duplicating state. The assistant's response is already available via:
Having it also in
Two options:
What's the intended design for messages? |
|
I just checked the stream handler, and when the finish reason is stop, the assistant message is not added to the request before dispatching the step-finish and stream-end events. I think the same behavior should apply to the text request state as well—the messages should represent only the input messages sent to the LLM to generate the output for that step. I also checked what happens when the finish reason is tool_calls in the stream handlers. In that case, the assistant message is added before dispatching the step-finish event. |
…ol result messages in stream handlers
|
The inconsistency is intentional - they serve different purposes:
This way, users can pass $response->messages directly to continue a conversation without manually reconstructing the assistant message. |
Description
Updated text handlers and stream handlers across all providers where step messages contained both input and output messages.
In text handlers: The assistant message (response) was being added to the request before
addStep()was called, which caused each step'smessagesarray to include the assistant's response alongside the input messages.In stream handlers: The assistant and tool result messages were being added to the request before the
StepFinishEventwas dispatched, which caused the same issue where each step's messages would include the output alongside the input.The Problem
In multi-step tool call scenarios:
messageswas including the assistant message (output) that was generated during that stepstep->messagesshould represent only the input to that steptext,toolCalls,toolResults, etc.)The Fix
Text Handlers: Moved the assistant message addition to after
addStep()in all provider text handlers.Stream Handlers: Moved the assistant and tool result message additions to after yielding
StepFinishEventin all provider stream handlers.Affected providers:
Anthropic,OpenAI,OpenRouter,DeepSeek,Gemini,Groq,Mistral,Ollama,XAINow in multi-step scenarios:
messages=[user message](input only)messages=[user message, assistant message from step 1, tool results](input only)Tests Updated
Added assertions across all provider test files to verify:
Breaking Changes
Text Handlers
step->messageswill no longer include the assistant message generated during that step - only the input messages to that step. If you were accessing the assistant message via$response->steps[N]->messages, you should now use$response->steps[N]->textor$response->steps[N]->toolCallsinstead.No breaking change for
$response->messages->last()- it still returns the final assistant message for conversation continuation.Stream Handlers
When the
StepFinishEventis dispatched after tool results are executed, the request messages will no longer contain the assistant and tool result messages at that point. These messages are now added to the request after theStepFinishEventis yielded. If you were accessing$request->messages()in aStepFinishEventlistener expecting to see the assistant response and tool results, they will no longer be present at that time.