TelemetryEvent is the SDK’s primitive for product telemetry — user actions, tool calls, agent
decisions, anything you’d send to a product analytics tool. Events are pushed independently of
trajectories, and can be correlated to them via trace_id (see
Linking Events to Trajectories).
Quickstart
For telemetry-only usage, onlyproject_id and trajectory_api_key are required in init() —
no provider credentials needed.
Constructing Events
TelemetryEvent is a frozen dataclass. Only event_type and session_id are required; every
other field has a sensible default.
| Field | Type | Default | Description |
|---|---|---|---|
event_type | str | required | Dotted event name (e.g. user.accept, tool.call). |
session_id | str | required | Session grouping. Defaults to trace_id when produced via TraceContext.event(...). |
properties | dict | {} | Free-form event payload. |
event_id | str | new UUID4 hex | Idempotency key (see below). |
timestamp | str | now (UTC ISO) | Event time. Pass an explicit value to backdate. |
user_id | str | None | None | End-user identifier. |
trajectory_id | str | None | None | Backend trajectory ID once known. |
trace_id | str | None | None | Caller-owned correlation key. Always set when producing events via TraceContext. |
source | str | "sdk" | Where the event originated. |
metadata | dict | None | None | Additional context not part of properties. |
Idempotency
event_id is the idempotency key. The default UUID4 means re-runs of the same code produce
different IDs (and the backend will accept both as separate events).
For at-least-once delivery pipelines — webhooks, retries, replay from a queue — set event_id
deterministically from your own primary key so duplicate pushes are coalesced server-side:
event_id is a no-op on the backend.
Pushing Events
tj.push_events(events) validates, chunks, retries, and pushes a batch of events.
| Parameter | Type | Default | Description |
|---|---|---|---|
events | list[TelemetryEvent] | required | Events to push. |
organization_id | str | None | None | Logged client-side for attribution. The backend derives the authoritative org from the API key. |
chunk_size | int | 1000 | Max events per HTTP request. The SDK splits longer lists automatically. |
max_retries | int | 3 | Per-chunk retry budget on transient failures. |
PushResult:
| Field | Type | Description |
|---|---|---|
pushed | int | Events accepted by the backend. |
skipped | int | Events dropped client-side as invalid. |
errors | list[str] | One message per invalid event. |
Invalid events are dropped with a logged warning rather than raising. This matches the
pattern used by
upload() for empty trajectories: bad inputs don’t poison a whole batch.
Inspect result.errors to see what was rejected.Producing Events via TraceContext
When you’re already inside aTraceContext (the recommended path for SDK-instrumented agent
runs), use trace.event(...) so events automatically inherit the trace_id:
TraceContext.event(...) sets session_id = trace_id automatically. Override either via the
keyword arguments if you need a different grouping.
See Linking Events to Trajectories for the full
workflow, including tj.upload_trace() which uploads a trajectory and pushes correlated events
in one atomic call.
Related
Linking Events to Trajectories
The
trace_id correlation story end-to-end.API Reference
Full signatures for
push_events, TelemetryEvent, PushResult.