Skip to content

fix: fix empty assistant message crash in Agent - #12544

Closed
sjrl wants to merge 5 commits into
mainfrom
fix/agent-contentless-assistant-reply
Closed

sjrl wants to merge 5 commits into
mainfrom
fix/agent-contentless-assistant-reply

Conversation

@sjrl

@sjrl sjrl commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Related Issues

Proposed Changes:

Fixed a crash in Agent on the LLM call following a reply from which a Chat Generator discarded a malformed tool call. Such a reply has no content parts, which Chat Message converters reject. The Agent now leaves it out of the message history, so the next call and any follow-up turn built from the returned messages stay sendable. Its token usage is still recorded, and a length or content_filter finish reason on it still ends the run.

How did you test it?

New tests, and also tested locally that the model does recover.

Notes for the reviewer

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
haystack-docs Ignored Ignored Preview Sep 1, 2026 9:01am UTC

Request Review

@github-actions github-actions Bot added topic:tests type:documentation Improvements on the docs labels Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/components/agents
  agent.py
Project Total  

This report was generated by python-coverage-comment-action

Comment thread haystack/components/agents/agent.py Outdated
return [
message
if message._content or not message.is_from(ChatRole.ASSISTANT)
else ChatMessage.from_assistant(text="", meta=message.meta, name=message.name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall reasoning be carried over?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll be going for a different approach, but that shouldn't matter here anyways because if reasoning content is present then if message._content would trigger and we would return the original message.

@datbth datbth Sep 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that could return a message with present reasoning, but text=None, right? Not sure if that message is accepted. It seems utils/hf.py#convert_message_to_hf_format doesn't accept it

@sjrl sjrl Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah our conversions across providers are not consistent (sometimes for good reason). For openai responses chat generator it does accept a text=None but a resoning content not None.

Would have to look into the hugging face to see if we are being too strict with the conversion.

Comment thread haystack/components/agents/agent.py Outdated
Comment on lines 1105 to 1108
# A contentless reply is kept out of the history because converters reject it. Usage and the exit reason
# still come from the raw replies: the call was billed and may have been truncated.
exe_context.state.set("messages", _drop_contentless_replies(messages=llm_messages))
_record_llm_usage(state=exe_context.state, llm_messages=llm_messages)

@datbth datbth Sep 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sorry if I'm being disruptive)

While this keeps the accumulated/aggregated token usage in the result, it removes the contentless messages and hence their token usage from the result.
I'm actually relying on that (the usage in individual message's meta) to calculate and monitor cost per tool call/message

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem thanks for the feedback. Yeah I was also worried about this so I was looking to see if server-side if providers like OpenAI accept content-less messages and we are being too strict. It seems with some initial testing they do accept them so that could be a solution that doesn't require dropping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah OpenAI seems to accept them, though Anthropic seems not

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe anthropic accepts it if you send [] as the empty content and not ""

@sjrl

sjrl commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

@datbth we are closing this PR in favor of this one #12545

Most providers actually accept empty assistant messages. Our converters were too strict so we will now be working on relaxing our constraints on our other integrations.

@sjrl sjrl closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent crashes on the next LLM call after a Chat Generator discards a malformed tool call

2 participants