This repository was archived by the owner on Aug 26, 2026. It is now read-only.
fix(0.0.7): derive real chain/model name from langchain.js callbacks - #4
Merged
Merged
Conversation
LangChain.js callbacks pass `serialized={}` for any anonymous Runnable —
notably every LangGraph node — and put the actual identity in the
trailing positional `runName` arg plus `metadata.langgraph_node`. The
SDK was reading only `serialized.name` and falling back to the literal
string "unknown", which made every graph step in the AxonPush dashboard
show up as `chain_type: "unknown"`. The same shape applies to LLM
events, which were emitting `model: "ChatOpenAI"` (the wrapper class)
instead of the configured model id (which lives in
`extraParams.invocation_params.model` at call time).
Pulled out three helpers in `src/integrations/_base.ts`:
deriveRunnableName(serialized, runName, metadata)
runName -> metadata.langgraph_node -> serialized.name
-> last segment of serialized.id -> "Runnable"
deriveModelName(serialized, extraParams)
invocation_params.model/model_name -> extraParams.{model,model_name}
-> serialized.kwargs.{model,model_name} -> serialized.name -> "unknown"
extractRunMetadata(tags, metadata, runType)
propagates langgraph_{node,step,triggers}, thread_id, run_type
and tags into the per-event metadata block so the UI can group
events by node and tag without the user passing a custom
metadata at handler construction time.
`handleChainStart` and `handleLLMStart` (in both langchain.ts and
langgraph.ts) now accept the trailing positional args LangChain.js
already passes (tags, metadata, runType, runName for chain start;
extraParams, tags, metadata, runName for LLM start) and use the
helpers above. Old callers that ignore those args keep working.
Eight new unit tests cover the LangGraph empty-serialized path and
the invocation_params-based model resolution. 173 unit tests pass,
build is clean.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
What
Fix the long-tail of `chain_type: "unknown"` and `model: "ChatOpenAI"` (the wrapper class instead of the configured model id) in AxonPush traces emitted from LangGraph and modern Chat* integrations.
Sister PR to axonpush/python-sdk#6 — same bug, same fix.
Why
LangChain.js's `handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName)` was originally designed for plain `Chain` classes that populate `serialized.name`. LangGraph nodes — which compile down to anonymous Runnables — instead pass `serialized={}` and put the node identity into the trailing `runName` arg + `metadata.langgraph_node`. The handler was reading only `serialized.name` and falling back to the literal string `"unknown"`, so every graph step in the dashboard rendered as `chain_type: "unknown"`.
Same problem applied to `handleLLMStart`: `serialized.name` returns the wrapper class (`ChatOpenAI` / `ChatAnthropic` / …), not the model id. The actual model lives in `extraParams.invocation_params.{model,model_name}` at call time.
How
Three helpers in `src/integrations/_base.ts`:
```ts
deriveRunnableName(serialized, runName, metadata)
// runName -> metadata.langgraph_node -> serialized.name
// -> last segment of serialized.id -> "Runnable"
deriveModelName(serialized, extraParams)
// invocation_params.model/model_name -> extraParams.{model,model_name}
// -> serialized.kwargs.{model,model_name} -> serialized.name -> "unknown"
extractRunMetadata(tags, metadata, runType)
// pulls langgraph_{node,step,triggers}, thread_id, run_type, tags
// into the event metadata dict so the UI can group/filter by node + tag
```
`handleChainStart` and `handleLLMStart` (in both `langchain.ts` and `langgraph.ts`) now accept the trailing positional args LangChain.js already passes (`tags`, `metadata`, `runType`, `runName` for chain start; `extraParams`, `tags`, `metadata`, `runName` for LLM start) and use the helpers above. Old callers that ignore those args keep working — purely additive at the public surface.
Test plan
Migration
None. Purely additive. Existing callers keep working; new trailing args are all optional.