A2A.Telemetry (A2A v0.3.0)

Copy Markdown View Source

Telemetry events emitted by the A2A library.

A2A uses :telemetry to emit events at key lifecycle points. Library users attach handlers in their application to observe agent behaviour in production.

Spans

Spans are emitted via :telemetry.span/3 and automatically produce :start, :stop, and :exception suffixed events.

[:a2a, :agent, :call]

Wraps the full A2A.call/3 and A2A.stream/3 lifecycle.

Start measurements: %{system_time: integer()}

Start metadata:

%{agent: GenServer.server(), streaming: boolean()}

Stop measurements: %{duration: integer()}

Stop metadata (adds to start):

%{task_id: String.t(), status: atom(), context_id: String.t() | nil}

When the agent replies {:message, parts} there is no task, so stop metadata is instead:

%{message_id: String.t(), context_id: String.t() | nil}

On error, stop metadata instead contains %{error: term()}.

[:a2a, :agent, :message]

Wraps the handle_message/2 callback execution inside the agent GenServer.

Start measurements: %{system_time: integer()}

Start metadata:

%{agent: module(), task_id: String.t(), context_id: String.t() | nil}

Stop measurements: %{duration: integer()}

Stop metadata (adds to start):

%{reply_type: :reply | :message | :stream | :input_required | :error}

A :message reply type means the agent answered out-of-band: the task_id in this span's metadata is the transient task the runtime built for the callback, which was then discarded and never persisted.

[:a2a, :agent, :cancel]

Wraps the handle_cancel/1 callback execution.

Start measurements: %{system_time: integer()}

Start metadata:

%{agent: module(), task_id: String.t(), context_id: String.t() | nil}

Stop measurements: %{duration: integer()}

Discrete Events

[:a2a, :task, :transition]

Emitted on every task state change.

Measurements:

%{system_time: integer()}

Metadata:

%{
  task_id: String.t(),
  context_id: String.t() | nil,
  from: atom() | nil,
  to: atom()
}

[:a2a, :push_notification, :delivery]

Emitted once per registered webhook per task state change, after the A2A.PushNotificationSender callback returns. Delivery is best-effort and runs off the agent process, so this event is the only report of whether a webhook was actually reached.

Measurements:

%{duration: integer()}

Metadata:

%{
  task_id: String.t(),
  context_id: String.t() | nil,
  config_id: String.t() | nil,
  url: String.t(),
  result: :ok | {:error, term()}
}