Instrumenting a Flue agent
@runtypelabs/flue-otel is OpenTelemetry instrumentation from Runtype for
Flue agents. Install it with Flue’s instrument()
function, configure an OTLP exporter for Runtype, and view each instrumented run
in the dashboard. Runtype displays the model, token usage, cost, loop iterations,
tool calls, and stop reason.
Your agent continues to run with your model credentials. Runtype provides the dashboard where you inspect the run.
When to use this instead of a generic exporter
Reporting telemetry from an external agent covers the general path. A generic exporter sends the GenAI semantic-convention attributes that your spans contain.
This package adds two values that a generic export cannot derive after the spans leave the process:
- An exact loop iteration count. Flue events do not include an absolute ordinal. If you rank turn IDs after export, you count only the turns in the export batch. A five-turn run whose final batch has two turns appears to have two iterations. The instrumentation counts each agent turn before export.
- A run-level stop reason and summed token usage. The instrumentation sums
token counts from model turns and adds the total to the run’s
invoke_agentspan. The run span retains that total when model spans flush in separate batches.
The package reports a delegated sub-agent as a tool call on the parent run. One trace represents one execution, so delegation does not create a second execution.
The package exports no prompts or completions. If you need a transcript or eval capture, read What it does not send before you choose this instrumentation.
Install and start
Use Node 22 or later and a Flue runtime that exposes instrument(). Install the
package and the OpenTelemetry API with this command:
Register the instrumentation with Flue using this code:
The package supports Flue >=1.0.0-beta.9 and 2.x through one entry point.
For OpenTelemetry, the package depends on @opentelemetry/api and does not
include an SDK, provider, exporter, sampler, or resource. Your application
configures those components, and the instrumentation writes spans through the
provider that you register. The instrumentation does not flush spans.
If your application already configures OpenTelemetry, register the
instrumentation and add the resource attributes that identify the Runtype agent.
Use runtypeFlueResourceAttributes({ agentId }) as described in
Attribution.
Create a telemetry key with the Telemetry Ingest permission group. For the key creation steps, see Create a telemetry API key.
Set up an OpenTelemetry pipeline
If your application does not have an OpenTelemetry pipeline, install
@opentelemetry/sdk-trace-node, @opentelemetry/exporter-trace-otlp-http, and
@opentelemetry/resources. Configure the provider, exporter, and instrumentation
with this example:
Set RUNTYPE_AGENT_ID to the ID of the Runtype agent that receives the run. Set
RUNTYPE_API_KEY to the telemetry key.
The following settings keep spans in one trace and preserve the closing run span:
Register the provider. provider.register() installs the OpenTelemetry
context manager. Without it, the API uses a no-op context manager, so each
span becomes a trace root and Runtype stores separate traces instead of one
run.
Flush before the process exits. A BatchSpanProcessor exports child spans
before parent spans. If the process exits without forceFlush() or
shutdown(), the closing invoke_agent span can be lost. A run whose
invoke_agent span never arrives remains in flight. In a serverless handler,
await provider.forceFlush() before returning.
Flue’s instrument() returns a disposer. Call it when you stop instrumentation.
It ends open spans as interrupted. It does not flush spans because your
application owns the exporter.
Attribution: which Runtype agent owns the run
Runtype resolves the agent for each trace in this order:
- The
runtype.agent.idresource attribute. TheruntypeFlueResourceAttributes({ agentId })helper sets it. - The
x-runtype-agent-idrequest header that your exporter sends. - The
runtype.agent.idattribute on the run’sinvoke_agentspan. Theagentsoption sets it.
Use the resource attribute or request header when one process runs one Runtype agent.
Run several agents in one process
When one process runs several agents, map each Flue agent name to a Runtype agent
ID with the agents option:
Replace YOUR_TRIAGE_AGENT_ID and YOUR_BILLING_AGENT_ID with the corresponding
Runtype agent IDs.
The package does not attribute a delegated sub-agent separately. The sub-agent’s work stays in the delegating agent’s trace, and one trace represents one execution.
Keep one agent invocation per trace. Spans inherit the active OpenTelemetry context. If an enclosing span remains active when two agent invocations run, both invocations land in the same trace. An HTTP server span from auto-instrumentation commonly causes this.
Runtype either merges the invocations into one execution, which drops the
second run’s usage and stop reason, or rejects the trace as
ambiguous_agent_attribution when the invocations claim different IDs through
agents and no resource attribute or request header resolves the trace. The
rejected trace produces no run.
To dispatch several agent invocations in one request or job, start each
invocation in its own trace. A separate process per agent lets you set the
resource attribute instead. Flue’s dispatch() does not propagate trace
context, so a direct dispatch() call creates its own trace.
What it emits
The instrumentation emits the following span types and attributes:
Every span also carries the flue.* correlation attributes that the standard
@flue/opentelemetry instrumentation emits. These attributes support dashboards
that group spans by Flue correlation keys.
The following details explain two intentional omissions:
Intentional omissions
runtype.tool.type for ordinary tools. Flue’s origin field identifies
who initiated a call, not its implementation class. The package emits this
attribute only for a sub-agent delegation and maps a 1.x datastore tool to
data_connection.
An unknown stop reason. If a run ends during a tool call, the package
reports unknown. It cannot identify whether a turn cap, tool cap, or host
abort stopped the run.
Compose with other instrumentations
Flue’s instrument() supports multiple subscribers. This package uses a separate
instrumentation key, so it does not replace @flue/opentelemetry.
Send one Flue instrumentation to each Runtype endpoint. If this package and the standard
@flue/opentelemetry instrumentation export to the same endpoint, Runtype receives two
invoke_agent spans for one run and counts the token usage and cost twice. You can send them to
different backends.
If you already export Flue traces to Runtype with the standard
@flue/opentelemetry instrumentation, replace it with this package for that
endpoint.
What it does not send
The package sends no prompts, completions, tool arguments, tool results, error messages, or stack traces. It sends identifiers, structure, metrics, model IDs, token counts, durations, tool names, correlation IDs, error types, and exception class names for failed spans.
This integration does not export content. It does not configure content fields for the spans that it creates.
Before you choose this package, account for these effects:
- Runs have no transcript. You can inspect timing, cost, iteration counts, and the tool call sequence, but not the exchanged text.
- Eval capture is unavailable. Capturing an external run into an eval suite requires content.
The standard @flue/opentelemetry instrumentation exports content by default. If
you need transcripts or eval capture, use that instrumentation instead. This
package provides the exact loop count, stop reason, and summed run-level usage
described in this guide.
The standard @flue/opentelemetry instrumentation exports content by default. Review its exporter
configuration before sending traces to a third-party backend.
Next steps
Continue with these guides:
- Improving your agents from production traces: turn ingested runs into evals and regression cases.
- Authentication: review API key scopes and authentication options.