fix(api): recover LangChain tool calls dropped during openinference ingestion#4407
fix(api): recover LangChain tool calls dropped during openinference ingestion#4407mmabrouk wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ngestion The openinference LangChain instrumentation flattens llm.input_messages with only role and content. The assistant tool_calls and the tool tool_call_id/name survive only inside input.value, serialized in the LangChain constructor format. For chat spans the adapter then deletes the input.value mapping in favor of the flattened messages, so the tool fields were lost. A conversation replayed from such a trace failed OpenAI validation, since a tool message had no preceding assistant declaring its call. The adapter now parses input.value, recognizes the LangChain serialized shape, and merges the recovered tool_calls (converted to the OpenAI shape), tool_call_id, and name onto the prompt by index. The merge uses setdefault so it only fills fields the flattened messages lacked, and it is gated to genuine LangChain payloads so other integrations are untouched. Adds four unit tests built from a real n8n HTTP_Request span.
b512ea4 to
1ad49e4
Compare
cfc15be to
451c2be
Compare
Railway Preview Environment
|
Summary
A chat conversation traced from LangChain (via openinference) lost its tool-call structure during ingestion. The stored
ag.data.inputs.promptshowed an assistant message with notool_callsand a tool message with notool_call_id. Replaying such a conversation failed withInvalid parameter: messages with role 'tool' must be a response to a preceeding message with 'tool_calls'.Root cause: the openinference LangChain instrumentation flattens
llm.input_messageswith onlyroleandcontent. The assistanttool_callsand the tooltool_call_id/namesurvive only insideinput.value, serialized in the LangChain constructor format ({"messages": [[{lc, type, id, kwargs}, ...]]}). For chat spans the adapter then deletes the genericinput.valuemapping in favor of the flattened messages, making the loss permanent.The fix teaches
OpenInferenceAdapterto recover the dropped fields. It parsesinput.value, recognizes the LangChain serialized shape, and merges the recoveredtool_calls(converted from LangChain{id, name, args, type}to the OpenAI{id, type: "function", function: {name, arguments}}shape),tool_call_id, andnameonto the prompt by index. The merge usessetdefault, so it only fills fields the flattened messages lacked, and it is gated to genuine LangChain payloads (thelangchain_core/constructormarkers), so other integrations are untouched.Testing
Verified locally
Restarted the API and tracing worker, re-ran the n8n LangChain agent, and confirmed the newly ingested trace now carries
tool_callson the assistant andtool_call_id/nameon the tool message. Combined with the playground loader fix (#4406), the trace then replays without the OpenAI tool-pairing error.Added or updated tests
Four unit tests in
test_openinference_adapter.py, built from a real n8n HTTP_Request span: tool_calls recovered onto the assistant in OpenAI shape, the tool message link (tool_call_id+name) recovered, role and content preserved, and a non-LangChaininput.valueleft untouched. Full adapter suite passes (16 tests).ruff formatandruff checkclean.QA follow-up
The recovery runs at ingestion, so it only affects newly ingested traces, not ones stored before this change. Validate with fresh traces from LangChain agents that use tools, including multi-tool turns.
Demo
N/A. Backend ingestion change.
Checklist