Agent traces and steps for externally deployed agents

Send spans from wherever your agent runs. A trace linked to a run turns its spans into the run's steps: model steps, tool steps, and generic operations with hierarchy, timing, status, and errors.

How telemetry is shaped

A trace is one unit of agent work, identified by a 32-character lowercase hex trace_id. It contains spans, each with a 16-character span_id and an optional parent_span_id. These are the W3C Trace Context id formats, so ids your tracing already produces can be sent as they are.

kindStep typeTypical fields
spanGeneric operationname, status, timing
generationModel stepprovider, model, input_tokens, output_tokens, cached_input_tokens, reported_cost_usd
toolTool stepname, tool_call_id

Put run_id (and optionally agent_id) on the root span only. When the root is linked to a run in the same environment, every span in that trace is a step of the run. An id that does not match a run is stored unlinked rather than rejected.

Send a batch

POST /v1/agent-telemetry accepts 1 to 50 spans per request, up to 1 MiB. Each item gets its own outcome, so one bad span does not reject the others.

curl -X POST https://api.flowyn.dev/v1/agent-telemetry \
  -H "Authorization: Bearer $FLOWYN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "event_id": "0b8d6f1e-5a43-4c2e-9d11-7f3c2a1b0e01",
        "emitted_at": "2026-09-30T10:00:04Z",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "span_id": "00f067aa0ba902b7",
        "name": "handle-refund",
        "kind": "span",
        "started_at": "2026-09-30T10:00:00Z",
        "status": "running",
        "agent_id": "7d0f6c1e-2b1a-4c55-9f53-1a2b3c4d5e6f",
        "run_id": "3b9d2f7a-8c41-4e0b-a5d6-0f1e2d3c4b5a"
      },
      {
        "event_id": "1c9e7a2f-6b54-4d3f-8e22-8a4d3b2c1f02",
        "emitted_at": "2026-09-30T10:00:04Z",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "span_id": "5c1a9e7d3b2f4a60",
        "parent_span_id": "00f067aa0ba902b7",
        "name": "classify-request",
        "kind": "generation",
        "started_at": "2026-09-30T10:00:00.2Z",
        "ended_at": "2026-09-30T10:00:01.1Z",
        "status": "succeeded",
        "provider": "openai",
        "model": "gpt-4.1-mini",
        "input_tokens": 812,
        "cached_input_tokens": 512,
        "output_tokens": 64
      },
      {
        "event_id": "2d0f8b3a-7c65-4e4a-9f33-9b5e4c3d2a03",
        "emitted_at": "2026-09-30T10:00:04Z",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "span_id": "9e2d4b6a8c0f1e35",
        "parent_span_id": "00f067aa0ba902b7",
        "name": "lookup_order",
        "kind": "tool",
        "tool_call_id": "call_7Hq2",
        "started_at": "2026-09-30T10:00:01.2Z",
        "ended_at": "2026-09-30T10:00:01.5Z",
        "status": "succeeded"
      }
    ]
  }'
outcomeMeaning
acceptedA new span was stored, or a running span moved to its terminal status.
duplicateThis event_id was already stored with identical content.
ignored_staleNothing changed, for example a running snapshot after the span finished.
conflictNothing changed; code says why, such as span_conflict.
invalidThe item failed validation and was not stored; its event_id can be reused.

Span updates

event_id makes each write idempotent. A span may be sent once as running and once more, under a new event_id, with its terminal status (succeeded, failed, or cancelled), ended_at, and any token fields not yet stored. Identity fields such as name, kind, and parent_span_id cannot change.

What is not accepted

Telemetry is metadata. Prompts, completions, tool arguments, tool results, headers, and URLs are not fields of the API, and a body with an unknown field is rejected. Error messages are limited to 240 characters.

Read traces and steps

bash
curl https://api.flowyn.dev/v1/agent-telemetry?run_id=3b9d2f7a-8c41-4e0b-a5d6-0f1e2d3c4b5a \
  -H "Authorization: Bearer $FLOWYN_API_KEY"

curl https://api.flowyn.dev/v1/agent-telemetry/4bf92f3577b34da6a3ce929d0e0e4736 \
  -H "Authorization: Bearer $FLOWYN_API_KEY"

A trace reads back as a flat page of up to 200 spans ordered by start time, each with duration_ms, tokens, cost, and error. incomplete means a root or parent span is missing; truncated means the trace has more spans than the page.

Span status and run status are independent

A failed tool step does not fail the run, and finishing the run does not close open spans. Your runtime reports each one.

Retention

Telemetry, and therefore steps, are kept for 30 days. The run record stays.

Next step

Model usage and cost.