observability · assistant-ui — Claude Code skill: AI SDK traces and react-o11y
Wires Langfuse, LangSmith or Helicone into assistant-ui AI SDK backend routes and renders collected spans with the experimental @assistant-ui/react-o11y.
npx skills add assistant-ui/skills --skill observability -a claude-codeWhat observability does
The skill keeps two layers apart. Backend instrumentation is Langfuse, LangSmith or Helicone — they collect data about model calls. Rendering is @assistant-ui/react-o11y, and it displays spans your app already collected. It sends nothing to a provider and derives no spans from the assistant runtime.
Pick a provider by the data model you need. Langfuse receives the OpenTelemetry spans AI SDK emits when experimental_telemetry is on, giving a hierarchical trace across an agent turn, tool calls and model calls. LangSmith wraps AI SDK functions through wrapAISDK(ai). Helicone proxies the provider request and shows logs, cost and latency without changing the call shape. Langfuse and Helicone can run together because they sit at different levels.
The order matters: choose the provider, add its server environment variables, instrument one route and confirm a real request reaches the dashboard. On Vercel, Lambda or another serverless runtime traces vanish without a forced flush before the function exits — Langfuse needs await langfuseSpanProcessor.forceFlush(), LangSmith needs await client.awaitPendingTraceBatches(). Langfuse also returns no spans if LangfuseSpanProcessor is registered in the edge runtime, since OpenTelemetry does not run there. Keep provider keys and metadata on the server; they have no place in a client component.
What it helps with
- hook Langfuse up to an AI SDK route and get a trace tree
- fix traces that vanish on Vercel and Lambda
- make Helicone actually proxy provider requests
- render a span tree or timeline in the UI
- attach provider metadata to an AI SDK call
Example prompts for the agent
- Set up observability for my AI SDK route with Langfuse
- Traces disappear on Vercel — add forceFlush before the function exits
- Render the collected spans with SpanResource and SpanPrimitive
How to install observability
1Skills CLI (Vercel)
npx skills add assistant-ui/skills --skill observability -a claude-code2Manually: put the files in place
~/.claude/skills/observability/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/observability/
1Skills CLI (Vercel)
npx skills add assistant-ui/skills --skill observability -a codex2Manually: put the files in place
.agents/skills/observability/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add assistant-ui/skills --skill observability -a cursor2Manually: put the files in place
.cursor/skills/observability/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install assistant-ui/skills observability2Manually: put the files in place
.github/skills/observability/SKILL.md1Skills CLI (Vercel)
npx skills add assistant-ui/skills --skill observability -a gemini-cli2Platform CLI
gemini skills install https://github.com/assistant-ui/skills --path assistant-ui/skills/observabilityManually: put the files in place
.devin/skills/observability/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add assistant-ui/skills --skill observability -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about observability
How do I install observability in Claude?
Run npx skills add assistant-ui/skills --skill observability -a claude-code. The skill lands in ~/.claude/skills/observability/SKILL.md.
What does the observability skill do?
It helps instrument assistant-ui AI SDK backend routes with Langfuse, LangSmith or Helicone, and render already collected spans through @assistant-ui/react-o11y.
Why does Langfuse show no spans?
Set experimental_telemetry: { isEnabled: true } on each streamText or generateText call, and register LangfuseSpanProcessor in the Node runtime only.
Source text
SKILL.md · MIT
---
name: observability
description: "Instruments assistant-ui AI SDK backend routes with Langfuse, LangSmith, or Helicone, and renders independent trace data with the experimental @assistant-ui/react-o11y SpanResource and SpanPrimitive APIs. Use it when traces are missing, serverless spans are dropped, an AI SDK call needs provider metadata, Helicone is not proxying a provider, or a trace tree or timeline needs rendering. For streaming transport use streaming, for initial application wiring use setup, for Assistant Cloud persistence use cloud, and for copied styled trace UI use elements."
license: MIT
---
# assistant-ui Observability
**Always consult [assistant-ui.com/llms.txt](https://www.assistant-ui.com/llms.txt) for the latest API.**
Observability has two separate layers. Langfuse, LangSmith, and Helicone instrument backend model calls. `@assistant-ui/react-o11y` renders span data already collected by your application. It does not send traces to a provider or derive spans from the assistant runtime.
## References
- [./references/langfuse.md](./references/langfuse.md) -- OpenTelemetry setup, trace attributes, and serverless flushing for Langfuse.
- [./references/langsmith.md](./references/langsmith.md) -- `wrapAISDK`, metadata, and serverless flushing for LangSmith.
- [./references/helicone.md](./references/helicone.md) -- Helicone proxy setup for AI SDK and OpenAI SDK routes.
- [./references/react-o11y.md](./references/react-o11y.md) -- `SpanResource`, every exported span primitive part, span contracts, timeline attributes, and the styled TraceWaterfall option.
## Choose the backend integration
Use one provider based on the data model you need.
- **Langfuse** receives the OpenTelemetry spans AI SDK emits when `experimental_telemetry` is enabled. Use it for a hierarchical trace across an agent turn, tool calls, and model calls.
- **LangSmith** wraps AI SDK functions through `wrapAISDK(ai)`. Use it when traces, evaluations, and prompt management belong with LangChain or LangGraph tooling.
- **Helicone** proxies the provider request. Use it for request logs, costs, latency, and prompt diffs without changing the AI SDK call shape.
Langfuse and Helicone can run together because one consumes OpenTelemetry spans while the other proxies provider traffic. LangSmith is its own wrapper path, so use its wrapped AI SDK functions instead of the originals.
## Implementation order
1. Select the provider integration that owns the telemetry destination.
2. Add its server environment variables and startup instrumentation or provider configuration.
3. Instrument one route and verify a real request reaches the provider dashboard.
4. Add serverless flushing before treating traces as reliable in production.
5. Render a separate `SpanData[]` feed with react-o11y only when the product needs an in app trace view.
## Route handler boundary
Keep provider credentials and instrumentation on the server. Every example uses `openai("gpt-5.6-luna")`, awaits `convertToModelMessages(messages)`, and returns the AI SDK UI message response. The integration pages do not use an assistant-ui route helper. If a route needs one, import it from `@assistant-ui/ai-sdk`; `@assistant-ui/react-ai-sdk` re-exports the same API for older installs.
Resolve trace attributes from real auth and thread state. Do not put a provider key, Langfuse user ID, LangSmith metadata, or Helicone header in a client component.
## Render collected spans
`SpanResource({ spans })` accepts the complete raw `SpanData[]` list, normalizes parent relationships, sorts visible spans by start time, and owns collapse state. Mount it at an isolated provider root:
```tsx
const config = AuiConfig({ span: SpanResource({ spans }) });
<AuiProvider extends={null} config={config}>
<SpanPrimitive.Children components={{ Span: SpanRow }} />
</AuiProvider>;
```
The `SpanRow` component is automatically scoped to one visible span. Use `SpanPrimitive.Timeline` and `SpanPrimitive.TimelineBar` when rows must share a time axis. Use the copied `TraceWaterfall` element when a styled flat message and tool waterfall better fits the data you have.
## Common Gotchas
**Traces disappear on Vercel, Lambda, or another serverless runtime**
- Langfuse needs `await langfuseSpanProcessor.forceFlush()` before the function exits, or a deployment specific `waitUntil` path.
- LangSmith needs `await client.awaitPendingTraceBatches()` before the function exits.
**Langfuse has no spans**
- Set `experimental_telemetry: { isEnabled: true }` on each traced `streamText` or `generateText` call.
- Register `LangfuseSpanProcessor` only in the Node runtime. OpenTelemetry does not run in the edge runtime.
**LangSmith does not trace the route**
- Call the destructured functions from `wrapAISDK(ai)`, not the originals from `ai`.
- Set `LANGSMITH_TRACING=true` in the runtime environment.
**Helicone traffic still goes directly to OpenAI**
- The provider `baseURL` must be `https://oai.helicone.ai/v1` and the request must carry `Helicone-Auth` as well as the provider authorization header.
**A react-o11y view renders no rows**
- Mount `SpanResource` with `AuiConfig({ span: SpanResource({ spans }) })` and render beneath `<AuiProvider extends={null} config={config}>`.
- Pass a complete `SpanData[]` list. `SpanPrimitive.Children` reads the current span scope and does not fetch traces.
**A documented span component is missing**
- `SpanPrimitive.ChildByIndex` is not re-exported by the current source. Use the exported `SpanByIndexProvider` with a row component when explicit index scoping is necessary.
## Related Skills
- [streaming](../streaming/SKILL.md) -- AI SDK stream transport and route response handling.
- [setup](../setup/SKILL.md) -- Project creation, CLI setup, and runtime installation.
- [cloud](../cloud/SKILL.md) -- Assistant Cloud persistence and run reporting configuration.
- [elements](../elements/SKILL.md) -- Copied styled elements, including TraceWaterfall.
© assistant-ui · MIT · assistant-ui/skills
Similar skills
Everything for AI and ML →observability by other authors comes first.