Skip to content

fix: inject handoff instructions into last ToolMessage to avoid "user after tool" API error - #55

Closed
JumpLink wants to merge 1 commit into
LibreChat-AI:mainfrom
faktenforum:fix/handoff-avoid-user-after-tool
Closed

JumpLink wants to merge 1 commit into
LibreChat-AI:mainfrom
faktenforum:fix/handoff-avoid-user-after-tool

Conversation

@JumpLink

@JumpLink JumpLink commented Feb 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #54

When the receiving agent's filteredMessages end with a ToolMessage (e.g. the router ran list_upload_sessions before the handoff), we previously appended handoff instructions as a HumanMessage. That produced the sequence … tool → user, which many chat APIs reject with 400 Unexpected role 'user' after role 'tool'.

This change: if the last message is a ToolMessage, we extend its content with the handoff instructions instead of adding a new HumanMessage. The next turn is then a valid assistant response. If the last message is not a tool message, behaviour is unchanged (we still append a HumanMessage with the instructions).

Token map handling is updated so the instructions are counted in either the extended tool message or the new human message.

Testing

Seems to be working now (compare this with the screenshot in the issue):
grafik

… after tool" API error

When the receiving agent's filtered messages end with a ToolMessage
(e.g. from
list_upload_sessions before the handoff), appending handoff instructions
as a
HumanMessage produced the sequence tool → user, which many chat APIs
reject
(400 Unexpected role 'user' after role 'tool'). Now we extend the last
ToolMessage's content with the instructions instead, so the next turn is
validly an assistant response.
@danny-avila

Copy link
Copy Markdown
Collaborator

Closing in favor of #58

Let me know if my solution also works for you

@danny-avila

Copy link
Copy Markdown
Collaborator

follow-up PR to retain stronger steering of the human message for task instructions: https://github.com/danny-avila/agents/pull/59/changes

@danny-avila

Copy link
Copy Markdown
Collaborator

Also note, I couldn't reproduce the original issue anyway, so some context about the exact model/provider used would help inform

@JumpLink

Copy link
Copy Markdown
Contributor Author

Closing in favor of #58

Let me know if my solution also works for you

Yes works, thank you.

JumpLink added a commit to faktenforum/agents that referenced this pull request Feb 16, 2026
…ystem prompt)

Revert PR LibreChat-AI#55 approach (inject instructions into last ToolMessage) and
restore upstream fix from LibreChat-AI#58: handoff instructions are injected into
the system prompt via AgentContext.setHandoffContext and
buildIdentityPreamble. This avoids the bridge AIMessage and the
'400 Unexpected role user after role tool' API error (issue LibreChat-AI#54).

Co-authored-by: Cursor <cursoragent@cursor.com>
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] 400 Unexpected role 'user' after role 'tool' when handoff follows a tool call

2 participants