Flue
Trace a Flue agent in Harbor by registering its OpenTelemetry adapter.
Flue's runtime emits agent activity as an internal event stream, not OpenTelemetry directly.
@flue/opentelemetry is Flue's own adapter that turns that stream into spans using the
GenAI conventions Harbor reads, so the only wiring is registering Harbor's tracer provider
and Flue's instrumentation, in that order.
Install
npm install harbor-ai-sdk @flue/opentelemetry@flue/opentelemetry is Flue's own package, not Harbor's — it ships alongside @flue/runtime
and is what converts Flue's event stream into spans.
Set up
import { createOpenTelemetryInstrumentation } from '@flue/opentelemetry'
import { instrument } from '@flue/runtime'
import { Harbor } from 'harbor-ai-sdk'
export const harbor = new Harbor()
instrument(createOpenTelemetryInstrumentation())Construct Harbor first. It registers the OpenTelemetry tracer provider that
createOpenTelemetryInstrumentation() exports through, and Flue's docs describe the same
ordering: configure the SDK, then register the instrumentation.
What you get
invoke_agent {agent} the agent run
chat {model} a model call
execute_tool {name} a tool the agent invoked
flue.operation shell a shell/caller execution
flue.compaction context compaction, when it runsModel and tool spans carry the same GenAI attributes as any other integration on this
page — model, token usage, tool name and arguments. Flue's own agentName and
conversationId map onto gen_ai.agent.name and gen_ai.conversation.id without any
work on your side, so reusing one conversationId across turns already stitches them into
one Harbor session.
Add the user
Flue has no concept of an end user, so capture supplies it — the same as with the
Vercel AI SDK:
import { capture } from 'harbor-ai-sdk'
const result = await capture('agent-turn', () => agent.run(input), {
userId: user.id,
})sessionId is optional here since conversationId already provides one; pass it only if you
want Harbor's session to follow something other than Flue's own conversation id.
Flue's OpenTelemetry adapter exports conversation content — messages, instructions, tool
arguments — by default. Pass { content: false } to
createOpenTelemetryInstrumentation() to drop it, or { content: { transform } } to redact
it, if that default isn't what you want for this agent.
Spans carry a 56 KiB content budget shared across messages, instructions, tool definitions
and payloads; anything over that is truncated with a [flue:truncated, …] marker rather
than dropped.