Skip to content
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
Dank-del merged 2 commits into
masterfrom
fix/langgraph-chain-name-and-model-id
May 4, 2026
Merged

Dank-del merged 2 commits into
masterfrom
fix/langgraph-chain-name-and-model-id

Conversation

@Dank-del

@Dank-del Dank-del commented May 4, 2026

Copy link
Copy Markdown
Collaborator

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

  • `bun run test` — 173 pass (165 + 8 new)
  • `bun run build` — clean
  • New tests in `src/tests/integrations/_base.test.ts` cover:
    • LangGraph empty-`serialized` path with `runName` + `metadata.langgraph_node`
    • `extraParams.invocation_params` model resolution
    • Each fallback rung of both helpers
    • `extractRunMetadata` round-trip
  • Manual: re-run a LangGraph agent in `@axonpush/sdk` consumer, confirm dashboard shows real node names and model ids.

Migration

None. Purely additive. Existing callers keep working; new trailing args are all optional.

Dank-del added 2 commits May 5, 2026 00:15
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.
@Dank-del
Dank-del merged commit 823ee8e into master May 4, 2026
4 checks passed
@Dank-del
Dank-del deleted the fix/langgraph-chain-name-and-model-id branch May 4, 2026 18:49
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant