fix(langchain): serialize tools and ToolMessage metadata in generation input#859
Open
filippostanghellini wants to merge 1 commit into
Open
fix(langchain): serialize tools and ToolMessage metadata in generation input#859filippostanghellini wants to merge 1 commit into
filippostanghellini wants to merge 1 commit into
Conversation
|
@filippostanghellini is attempting to deploy a commit to the langfuse Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LangChain tools (function definitions passed via
invocation_params.tools) andToolMessageoutputs were not serialized in the generation input, so they didnot appear in the Langfuse UI. The JS SDK diverged from the Python SDK behavior
(
__on_llm_action/_convert_message_to_dict), where tools are appended as{role: "tool"}messages andToolMessageis serialized withrole: "tool"+tool_call_id.Changes
packages/langchain/src/CallbackHandler.ts:handleGenerationStart: readinvocation_params.toolsand append each as{role: "tool", content: tool}to the generation input (matches Python's__on_llm_action).extractChatMessageContent: forToolMessage, setrole: "tool"andpropagate
tool_call_id(matches Python's_convert_message_to_dictforToolMessage). Previouslyrolewas set tomessage.nameandtool_call_idwas dropped.tool_call_idfield toLlmMessage/AnonymousLlmMessagetypes.
Verification
pnpm format:checkpnpm lintpnpm typecheckpnpm test(scoped:vitest run --project=unit --project=integration→ 389/389 passed; e2e project excluded)pnpm test:integration(included in the scoped run above;langchain.integration→ 3/3 passed)pnpm test:e2e(not run: requiresLANGFUSE_BASE_URL,LANGFUSE_PUBLIC_KEY,LANGFUSE_SECRET_KEY,OPENAI_API_KEYand a reachable Langfuse server)pnpm --filter @langfuse/langchain buildNote:
pnpm test:e2ecould not run because it requires a reachable Langfuseserver and credentials, which are not available in this environment. The e2e
suite is not affected by this change (no modifications to export protocols,
media upload, or API client).
Release info
Bump level
Libraries affected
Changelog notes
@langfuse/langchainnot including tools (invocation_params.tools) andToolMessagemetadata (role,tool_call_id) in the generation input,aligning behavior with the Python SDK.
Greptile Summary
This patch fixes the LangChain callback handler to include tool definitions (
invocation_params.tools) andToolMessagemetadata (role,tool_call_id) in the Langfuse generation input, aligning the JS SDK with Python SDK behavior.handleGenerationStartnow readsinvocation_params.toolsand appends each entry as a{role: "tool", content: tool}message in the generation input.extractChatMessageContentnow correctly setsrole: "tool"and propagatestool_call_idfor tool-type messages; previouslyrolewas set tomessage.nameandtool_call_idwas dropped.LlmMessageandAnonymousLlmMessagegain an optionaltool_call_idfield, and two integration tests verify both new behaviors end-to-end via span attribute assertions.Confidence Score: 4/5
The change is narrowly scoped to display/serialization of tool metadata and does not touch any API calls, data persistence, or authentication paths; it is safe to merge.
Both new behaviors are covered by integration tests and the logic is straightforward. The one open question is whether role:"tool" for tool definitions (function schemas from invocation_params.tools) could confuse users in the Langfuse UI, since the same role is also used for tool result messages — there is no runtime breakage, but the ambiguity is worth resolving before the release if trace readability matters.
packages/langchain/src/CallbackHandler.ts — specifically the role assigned to tool definitions appended in handleGenerationStart.
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant LC as LangChain participant CH as CallbackHandler participant LF as Langfuse (OtelSpan) LC->>CH: handleChatModelStart(messages, extraParams) CH->>CH: extractChatMessageContent per message Note over CH: ToolMessage maps to role:tool + tool_call_id CH->>CH: handleGenerationStart(prompts, extraParams) CH->>CH: read invocation_params.tools alt tools present CH->>CH: append role:tool + content:toolDef for each tool end CH->>LF: startAndRegisterOtelSpan with inputMessages%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant LC as LangChain participant CH as CallbackHandler participant LF as Langfuse (OtelSpan) LC->>CH: handleChatModelStart(messages, extraParams) CH->>CH: extractChatMessageContent per message Note over CH: ToolMessage maps to role:tool + tool_call_id CH->>CH: handleGenerationStart(prompts, extraParams) CH->>CH: read invocation_params.tools alt tools present CH->>CH: append role:tool + content:toolDef for each tool end CH->>LF: startAndRegisterOtelSpan with inputMessagesPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(langchain): serialize tools and Tool..." | Re-trigger Greptile