agent() auto-closes the span when the wrapped function returns and captures the return value as ai.agent.output. This works perfectly for non-streaming agents, but breaks for streaming: the function returns a stream object before the output text is assembled.
Pass { streaming: true } / streaming=True to opt into manual span lifecycle.
The contract
- The span stays open when the function returns.
- Call
ctx.complete(output)exactly once, with the assembled text, to recordai.agent.outputand close the span. - If
ctx.complete()is never called, the SDK emits a console warning and the span stays open indefinitely — it will not appear in the Lemma dashboard until closed.
Vercel AI SDK — onFinish pattern
The cleanest approach: call ctx.complete() inside the onFinish callback, which fires once the full output is assembled.
Raw stream consumption
When you consume the stream yourself (e.g. to forward chunks to an SSE response), accumulate the text and callctx.complete() when the loop ends.
- TypeScript
- Python
What happens if you forget ctx.complete()
The SDK emits a warning at runtime:
ctx.complete() inside a stream finish callback or after your accumulation loop.
Next Steps
- Streaming agent recipe — complete copy-paste SSE example with queue-based chunk forwarding
- Overview — the full
agent()V3 lifecycle contract

