Skip to content

fix(langchain): keep message names in generation input - #2038

Merged
hassiebp merged 1 commit into
langfuse:mainfrom
mosafariuk:fix/langchain-message-name
Oct 28, 2026
Merged

hassiebp merged 1 commit into
langfuse:mainfrom
mosafariuk:fix/langchain-message-name

Conversation

@mosafariuk

@mosafariuk mosafariuk commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

The LangChain CallbackHandler drops the name of every message from the captured generation input.

_convert_message_to_dict only reads message.additional_kwargs["name"]. Current LangChain stores the name on the message itself (BaseMessage.name), so it never reaches Langfuse. That includes HumanMessage(name="alice"), ToolMessage(name=...) and FunctionMessage, whose name is required, even though LangChain does send those names to the provider. For example, with a real ChatOpenAI and only the HTTP layer mocked:

Sent to OpenAI (names): [('user', 'alice'), ('assistant', None), ('tool', None), ('function', 'get_weather')]
Langfuse input (names): [('user', None), ('assistant', None), ('tool', None), ('function', None)]

This PR reads message.name and falls back to additional_kwargs["name"], so integrations that still put it there keep working. With the change:

Langfuse input (names): [('user', 'alice'), ('assistant', None), ('tool', 'get_weather'), ('function', 'get_weather')]

The langfuse-js counterpart (#950) describes this as matching what the Python SDK already does, so this brings the Python behaviour in line with that.

Fixes # (no existing issue)

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor
  • Documentation update
  • Tooling, CI, or repo maintenance

Verification

uv run pytest tests/unit/test_langchain.py tests/unit/test_langchain_utils.py   # 30 passed
uv run pytest tests/unit                                                        # 946 passed; 18 errors in test_prompt.py, identical on unmodified main (fixture issue addressed by #1979)
uv run ruff check . && uv run ruff format --check .
uv run mypy langfuse

The new test_chat_model_input_keeps_message_names in tests/unit/test_langchain.py follows the existing exporter-local pattern (patched ChatOpenAI._generate, in-memory exporter). It covers message.name on human, tool and function messages, plus the legacy additional_kwargs["name"] fallback. It fails on main (('user', None) != ('user', 'alice')) and passes with this change.

Checklist

  • I self-reviewed the diff using code_review.md.
  • I added or updated tests for behavior changes.
  • I updated docs, examples, or .env.template if needed.
  • I did not hand-edit generated files; if generated files changed, I used the upstream regeneration path.
  • I did not commit secrets or credentials.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge.

Summary

The PR keeps message names in LangChain generation input.

  • Langfuse records names attached directly to LangChain messages.

No actionable issues were found. Tests were not run during this review.

Reviews (1) · Last reviewed commit: "fix(langchain): keep message names in ge..." · Reviewed by Greptile

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@CLAassistant

CLAassistant commented Oct 21, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@chrikrah chrikrah left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@mosafariuk I'd merge this at d9cec13. On langchain-core 1.2.22 the name lives on BaseMessage.name. The merge base reads only additional_kwargs, so a name set with name= never reached the input.

$ .venv/bin/python -m pytest tests/unit/test_langchain.py tests/unit/test_langchain_utils.py -q -p no:cacheprovider   # d9cec13, langfuse from the tree
30 passed in 5.10s

# langfuse/langchain/CallbackHandler.py from 21834c5 (merge base), your test kept
FAILED tests/unit/test_langchain.py::test_chat_model_input_keeps_message_names
E         At index 0 diff: ('user', None) != ('user', 'alice')
1 failed, 29 passed in 3.94s
# not run: the rest of tests/unit, mypy, and a live provider

non-blocking: _convert_message_to_dict also builds the generation output at CallbackHandler.py:1309. A named AIMessage from the model now keeps its name there too. That looks right to me, but no test pins it. One assertion on the output span would cover it.

@hassiebp when both are set, message.name now wins over additional_kwargs["name"]. I'd keep that order. The old value still shows, because additional_kwargs is copied in whole. Does any integration you know read name from the old place?

@mosafariuk

Copy link
Copy Markdown
Contributor Author

@hassiebp could you take a look when you have a moment? It's approved by @chrikrah, CI is green and the CLA is signed. It's a small fix: the LangChain handler now reads message.name, falling back to additional_kwargs["name"], so message names reach the generation input again.

@hassiebp
hassiebp enabled auto-merge (squash) October 28, 2026 09:36
@hassiebp

Copy link
Copy Markdown
Collaborator

thanks for your contribution!

@hassiebp
hassiebp merged commit f5deab7 into langfuse:main Oct 28, 2026
21 checks passed
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.

4 participants