fix(ai): name langchain spans from the bare runName string - #4336
Merged
Conversation
LangChain passes runName as a bare string, but _getLangchainRunName only
inspected object arguments, so it fell through to serialized.id[last] and
every tool span was captured as DynamicStructuredTool.
Also test the object branches by value instead of key presence — the LLM
path passes { extraParams, runName }, where the key is always present and
an undefined value skipped the serialized.name fallback.
Contributor
|
Reviews (1): Last reviewed commit: "fix(ai): name langchain spans from the b..." | Re-trigger Greptile |
Contributor
Contributor
|
Size Change: +314 B (0%) Total Size: 17.9 MB 📦 View Changed
ℹ️ View Unchanged
|
marandaneto
approved these changes
Jul 30, 2026
Radu-Raicea
approved these changes
Jul 30, 2026
Member
|
@marco-g-pm should replicate this change in the Python SDK too |
Contributor
Author
Seems like there isn't the same issue with the Python SDK as the logic checks run slightly differently |
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
Every LangChain tool span is captured with
$ai_span_nameset to the runnable's class rather than its actual name — in a typical agent, every tool span in the UI readsDynamicStructuredTool, so they're indistinguishable.LangChain does hand us the right name:
handleToolStartandhandleChainStartreceiverunNameas their last argument and forward it to_getLangchainRunNameas(metadata, tags, runName). But the resolver only inspected arguments wheretypeof arg === 'object', so the bare string was skipped and it fell through toserialized.id[last]. SettingrunNamein the run config doesn't help, so there's no user-side workaround.Changes
_getLangchainRunNamenow accepts a bare string argument as the run name. Two details worth a reviewer's eye:_get_langchain_run_name: explicit name →serialized.name→serialized.id[-1]). OnlyrunNamecan arrive as a string in these call paths —tagsis astring[], which is an object._setLLMMetadatacalls this with{ extraParams, runName }, where'runName' in argis true even whenrunNameisundefined— that returnedundefinedand skipped theserialized.namefallback entirely.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude Code (Opus 5). Found while comparing the JS and Python LangChain handlers against a running agent for docs work — the tool span came back named
DynamicStructuredToolwhile the callback was being handedget_weather.Added a
handleToolStart→handleToolEndtest asserting$ai_span_name. Verified it fails onmain(Received: "DynamicStructuredTool") and passes with the fix;tests/callbacks.test.tspasses (15 tests). Six suites inpackages/aifail to resolveposthog-nodein my local partial workspace install — they fail identically on a cleanmaincheckout here, so they're unrelated to this change; CI runs the full workspace.Kept the change inside
_getLangchainRunNamerather than normalizingrunNameinto an object at each call site — the resolver is the piece with the documented precedence, and the call sites already match LangChain's own callback signatures.