Skip to content

DurableAgent never emits its streamText span even though experimental_telemetry reaches it (sibling generateObject steps emit fine) #3582

Description

@shtefcs

We run DurableAgent on the managed Vercel world and our agent spans never show up in our OTel backend (Langfuse span processor registered through @vercel/otel). Steps in the same workflow that call generateObject directly emit fine. Two days of production traffic: hundreds of routing spans, zero agent spans.

Versions: workflow 5.0.0-beta.24, @workflow/ai 5.0.0-beta.11, ai 6.0.141, next 16.2.9, @vercel/otel v2, Node 20 on Vercel.

What we ruled out before filing:

  • The config reaches the SDK. We logged it in the workflow body at the .stream() call site and got the full object: {"isEnabled":true,"functionId":"agent.general.main","metadata":{...}}.
  • Instrumentation is registered. Our register() log line appears in the same invocation's logs as the run.
  • Ingestion is healthy. routing.classify spans from the very same run (a generateObject inside a "use step") arrive a couple minutes later. The agent's own span from that run never does.
  • Not our local patch. We carry a small patch on @workflow/ai for step latency attributes, but it doesn't touch agent/telemetry.js or recordSpan, and the loss reproduces with the config confirmed intact at the boundary.

Where it seems to sit, from reading the dist: doStreamStep wraps model.doStream with recordSpan('ai.streamText.doStream') from agent/telemetry.js. So either options.experimental_telemetry doesn't survive the step argument serialization into doStreamStep (that options bag also carries transforms, which are functions), or getTracer / startActiveSpan silently no-ops inside the step invocation. The outer 'ai.streamText' span from streamTextIterator probably can't exist at all, since the iterator runs in the workflow body where import("@opentelemetry/api") fails and recordSpan takes the no-op path by design.

Is experimental_telemetry expected to work end to end through DurableAgent on the managed world? If yes, a pointer on where to instrument next would help. Happy to test a nightly build or add debug output on our side, we can reproduce this on demand.

Repro sketch: any DurableAgent with experimental_telemetry set and a span processor registered via @vercel/otel, compare span arrivals against a plain generateObject inside a "use step" in the same workflow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions