
bug(sdk-python): LangChain tool observations should use structured inputs when available
快速结论:当使用 Langfuse Python SDK 的 langfuse.langchain.CallbackHandler 与结构化 LangChain 工具结合时,工具观测记录会显示原始 Python 字典字符串(如 str(dict)),而不是结构化的 JSON 输入。优先排查 SDK 版本是否已包含修复 PR。
问题场景
用户在使用 Langfuse Python SDK(langfuse.langchain.CallbackHandler)与 LangChain 结构化工具(如通过 @tool 装饰器定义的工具)时,在 Langfuse UI 中发现工具观测的输入字段显示的是原始 Python 字典字符串(例如 "{'path': '/tmp/example.md', 'content': '# Title\\n\\nThis is ...'}"),而非格式化的结构化 JSON。
报错原文
# 这不是一个传统报错,而是观测数据格式异常:
# 工具观测输入显示为:
input: "{'path': '/tmp/example.md', 'content': '# Title\\n\\nThis is ...'}"
# 而非期望的:
input: {"path": "/tmp/example.md", "content": "# Title\n\nThis is ..."}
原因分析
LangChain 在 on_tool_start 回调中提供了两个参数:input_str(字符串形式)和 kwargs["inputs"](结构化字典形式)。Langfuse 的 CallbackHandler.on_tool_start 当前仅存储 input=input_str,这会导致复杂字符串参数(如多行文本、包含引号或 JSON-like 内容的字段)在 UI 中显示为原始的 Python 字典字符串,而无法被 UI 的启发式解析正确格式化。
环境排查
- 确认使用的
langfusePython SDK 版本(受影响版本:v4.x) - 确认
langchain-core版本(受影响版本:v1.x) - 确认 Langfuse 部署版本(社区版或云版本均可复现,不特定于部署类型)
- 检查是否使用了结构化工具(如通过
@tool装饰器传入字典参数的工具)
解决步骤
- 更新修复版本:当前已知修复 PR 在 langfuse-python#1719 中。请检查是否已有包含该修复的 SDK 版本发布,或手动应用该 PR 的修改。
- 手动补丁(临时方案):在
CallbackHandler.on_tool_start中,修改存储逻辑为优先使用kwargs.get("inputs"),当inputs为None时回退到input_str。代码修改示例如下(需定位到 SDK 源码中的on_tool_start方法):
# 原始代码:
span = self._get_parent_observation(parent_run_id).start_observation(
name=self.get_langchain_run_name(serialized, **kwargs),
input=input_str, # 仅使用字符串形式
...
)
# 修改后的代码:
structured_inputs = kwargs.get("inputs")
span = self._get_parent_observation(parent_run_id).start_observation(
name=self.get_langchain_run_name(serialized, **kwargs),
input=structured_inputs if structured_inputs is not None else input_str,
...
)
验证方法
使用结构化工具(如文件写入工具)调用一次,在 Langfuse UI 中查看对应的工具观测记录:
- 确认输入字段显示为结构化的 JSON 对象(如
{"path": "/tmp/example.md", "content": "# Title\n\n..."}) - 确认对于非结构化工具(如直接传入字符串的工具),回退行为仍能正确显示字符串输入



