fix(js): inherit parent's ls_agent_type in Vercel _getLsAgentType helper - #3319
Merged
Yoshi (ybathula707) merged 19 commits intoAug 5, 2026
Merged
Conversation
Contributor
JS perf benchmarkLower is better. Noisy on shared runners — treat as a signal, not a gate. Base64-heavy payloadSingle large base64 string per message — the shape the worker-offload path is optimized for.
Structural payloadMany small strings across a wide/nested object graph. Should bypass worker offload and use sync flush.
|
Yoshi (ybathula707)
marked this pull request as ready for review
August 3, 2026 19:39
… integration
on_trace_start and the subagent stamp path both unconditionally overwrote
user-supplied ls_agent_type. RunConfig(trace_metadata={ls_agent_type:
"middleware"}) was silently clobbered back to "root" on trace open,
causing middleware guardrail runs to leak into the main conversation in
the Messages view.
Refactors metadata assembly at both write sites:
- on_trace_start / onTraceStart: reads trace.metadata (was ignored), then
setdefault on ls_agent_type; ls_integration and ls_integration_version
stay force-set as SDK identity.
- on_trace_end / onTraceEnd: also force-set ls_integration to close the
mirror spoof vector (user's trace.metadata could still override on this
later lifecycle write).
- Subagent stamp (AgentSpanData under FunctionSpanData): preserves user
narrowing intent (middleware / compaction) but still applies structural
detection when the current tag is missing, "root" (inherited default),
or already "subagent".
Fixes LSO-3608.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under the reframed model (Arian): default root is stamped ONLY on the trace-root run when the user didn't supply. Nested traces (OAI Agents SDK invoked inside a user's outer traceable) don't get a default stamp — the enclosing traceable's tag propagates via create_child inheritance. User opt-out via ls_agent_type: null / None deletes the key from the run's metadata at both trace-start and trace-end (mirror-lifecycle write site). Subagent structural detection unchanged: still preserves user narrowing tags (middleware / compaction), still overrides root/absent -> subagent so the messages/v2 view can group agent-as-tool spans correctly. This is the documented trade: user-set root at trace level gets overridden at subagent-detected spans because we can't distinguish user-set root from default-stamped root at this write site. Also drops the on_trace_end ls_integration force-set from this PR — scope creep from the original LSO-3608 fix. Can be filed separately if SDK-identity spoofing at trace-end lifecycle is a real concern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…edence Two bot-flagged issues in openai-agents-sdk integration: 1. Nested null opt-out re-inherited parent tag. Deleting the key from merged_metadata / mergedMetadata removed it from the update object only — create_child still copied the parent's ls_agent_type into the child's extra.metadata. Fix: keep None/null in merged metadata so the child's extra.metadata explicitly carries the null value, overriding create_child's inheritance. 2. Trace-end merge reversed user precedence. onTraceStart put trace.metadata after this._metadata (trace wins), but onTraceEnd reversed the order (processor wins). Fix: match onTraceStart order at trace-end so per-invocation user policy wins consistently. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both `on_trace_start` / `onTraceStart` now delegate the default-root stamp to the shared util landed in #3317. Preserves the LSO-3608 precedence guarantee (user-supplied ls_agent_type wins via key-presence check). Subagent-detection sites stay hardcoded — they use a 2-element subset of narrowing tags (excluding subagent), clearer inline than importing.
…nts JS test coverage Adds a shared non-root tag set to the util (matches the vocabulary that OAI-Agents subagent detection and Vercel narrowing inherit already need). OAI-Agents subagent-detection sites now import it instead of hardcoding a 2-value tuple. Python site also tightened via metadata setdefault. Adds 6 JS precedence tests that were previously Python-only: nested-parent no-stamp, trace_end merge precedence, processor-vs-trace merge order, subagent-overrides-root, subagent-preserves-narrowing, subagent-idempotent.
Consolidates the duplicated helper across wrap.ts and telemetry.ts into a shared experimental/vercel/_agent_type.ts. Adds narrowing-parent-tag inheritance (middleware / subagent / compaction) ahead of the existing run_type === "tool" heuristic. Fixes guardrail LLM spans self-stamping "root" and leaking into main conversation via the messages/v2 parser's root-privilege short-circuit. Fixes LSO-3681. Related LSO-3607. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
resolveLsAgentType now returns LsAgentType | undefined. Undefined means "don't stamp" — caller should skip the field so the run has no ls_agent_type on its own metadata (Vercel-safe explicit inheritance covers the propagation gap). Precedence: 1. Any known user-supplied parent tag (root/middleware/subagent/compaction) inherits explicitly (Vercel inner spans don't reliably use traceable's outer_metadata mechanism). 2. parent.run_type === "tool" -> subagent (Vercel-specific convention). 3. undefined when nested with no user signal. 4. "root" only at true top-level (no parent runtree). Adds lsAgentTypeMetadata() spread helper so all 5 call sites cleanly skip stamping when the resolver returns undefined — avoids `ls_agent_type: undefined` landing as a metadata value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ritance Existing telemetry vitest expects a chain nested inside a tool span to be tagged subagent even when the tool span itself carries ls_agent_type=root (default-stamped or user-supplied). The previous ordering inherited root first and never reached the run_type=tool check. New precedence: 1. Narrowing tag (middleware/subagent/compaction) always wins. 2. parent.run_type === "tool" -> subagent (structural override of root). 3. Parent tagged root inherits explicitly. 4. No parent runtree -> root. 5. Otherwise undefined. Renames the constant to NARROWING_TAGS to match the semantic (root is not in the set of tags that beat structural detection). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`traceable({ tracingEnabled: false })` stores a ContextPlaceholder (not
a RunTree) in ALS. The previous loose type guard treated any non-null
object as a runtree, so a nested LangSmithTelemetry({ tracingEnabled:
true }) creating a new root run took the "nested-untagged" branch and
returned undefined — the new root lost its default ls_agent_type=root
stamp.
Replace the ad-hoc check with `isRunTree` from run_trees.js. The
placeholder now falls back to "root", matching the semantic that this
IS the trace root for the newly-enabled telemetry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
_agent_type.ts drops local LsAgentType/NARROWING_TAGS in favor of the shared util (LsAgentType, NON_ROOT_LS_AGENT_TYPES, resolveDefaultLsAgentType, lsAgentTypeMetadata). No-parent → root now delegates to the util; the Vercel-specific composition (narrowing inherit, run_type=tool, root inherit) stays local because AI SDK inner spans bypass traceable's outer_metadata propagation. Exports renamed to avoid collision with util's lsAgentTypeMetadata(tag): - resolveLsAgentType → resolveVercelLsAgentType - lsAgentTypeMetadata(parent) → vercelLsAgentTypeMetadata(parent) 5 caller sites updated (wrap.ts × 4, telemetry.ts × 1). Test suite renamed imports + added null-on-parent case for precedence parity with the OAI-Agents suite.
Yoshi (ybathula707)
force-pushed
the
yashaswibathula/lso-3681-vercel-ls-agent-type-inherit
branch
from
August 4, 2026 01:23
1685ddb to
f754038
Compare
Yoshi (ybathula707)
changed the base branch from
main
to
yashaswibathula/lso-3608-oai-agents-ls-agent-type
August 4, 2026 01:23
Jacob Lee (jacoblee93)
approved these changes
Aug 4, 2026
Base automatically changed from
yashaswibathula/lso-3608-oai-agents-ls-agent-type
to
main
August 4, 2026 23:02
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yoshi (ybathula707)
deleted the
yashaswibathula/lso-3681-vercel-ls-agent-type-inherit
branch
August 5, 2026 00:20
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.
What
Vercel's
_getLsAgentTypehelper onlly checkedparent.run_type === "tool"— never consultedparent.extra.metadata.ls_agent_type. Inner LLM spans created bywrapAISDKinside a middleware-taggedtraceable()self-stampedroot.Both the outer middleware chain run and the real main model call shared conversation key
"root", so guardrail LLM content leaked into the main conversation in the Messages view.How
Consolidates Vercel's ls_agent_type logic into
experimental/vercel/_agent_type.tsatop the shared util ls_agent_type.ts util5 caller sites updated (wrap.ts × 4, telemetry.ts × 1).
Tagging precedence per span:
middleware/subagent/compaction) → inherits explicitly at config-build time.parent.run_type === "tool"→subagentroot→ inheritsrootrootvia the utilundefined;Fixes LSO-3681. Related LSO-3607.
Test Plan
js/src/tests/vercel_agent_type.test.ts20/20 pass.src/tests/vercel/telemetry/methods.vitesttest.ts— 36/36 pass