Telemetry integration for Condukt.
Condukt emits telemetry events that can be used for monitoring, logging, and observability.
Events
Agent Events
[:condukt, :agent, :start]- Agent started processing a prompt- Measurements:
%{system_time: integer} - Metadata:
%{agent: module}
- Measurements:
[:condukt, :agent, :stop]- Agent finished processing- Measurements:
%{duration: integer} - Metadata:
%{agent: module}
- Measurements:
[:condukt, :agent, :exception]- Agent raised an exception- Measurements:
%{duration: integer} - Metadata:
%{agent: module, kind: atom, reason: term, stacktrace: list}
- Measurements:
Tool Events
[:condukt, :tool_call, :start]- Tool call started- Measurements:
%{system_time: integer} - Metadata:
%{tool: string}
- Measurements:
[:condukt, :tool_call, :stop]- Tool call completed- Measurements:
%{duration: integer} - Metadata:
%{tool: string}
- Measurements:
[:condukt, :tool_call, :exception]- Tool call raised an exception- Measurements:
%{duration: integer} - Metadata:
%{tool: string, kind: atom, reason: term, stacktrace: list}
- Measurements:
Sub-agent Events
These events wrap the explicit sub-agent delegation lifecycle. They do not include task text, structured input values, or structured output values.
[:condukt, :subagent, :start]- Sub-agent delegation started- Measurements:
%{system_time: integer} Metadata:
%{agent: module | pid, role: atom, child_agent: module, input?: boolean, output?: boolean}
- Measurements:
[:condukt, :subagent, :stop]- Sub-agent delegation finished- Measurements:
%{duration: integer} Metadata:
%{agent: module | pid, role: atom, child_agent: module, input?: boolean, output?: boolean, status: :ok | :error}- Error metadata:
%{error: atom}
- Measurements:
Secret Events
These events never include secret values.
[:condukt, :secrets, :resolve]- Session secrets resolved- Measurements:
%{count: non_neg_integer} - Metadata:
%{agent: module, names: [String.t()]}
- Measurements:
[:condukt, :secrets, :access]- A tool received resolved session secrets- Measurements:
%{count: non_neg_integer} - Metadata:
%{agent: module, tool: String.t(), names: [String.t()]} - Optional metadata:
%{tool_call_id: String.t()}
- Measurements:
Operation Events
Wrap a full Condukt.Operation.run/4 call (input validation, transient
session run, output validation). The inner LLM loop still emits the
[:condukt, :agent, ...] events for free.
[:condukt, :operation, :start]- Operation invocation started- Measurements:
%{system_time: integer} - Metadata:
%{agent: module, operation: atom}
- Measurements:
[:condukt, :operation, :stop]- Operation invocation finished- Measurements:
%{duration: integer} - Metadata:
%{agent: module, operation: atom}
- Measurements:
[:condukt, :operation, :exception]- Operation raised an exception- Measurements:
%{duration: integer} - Metadata:
%{agent: module, operation: atom, kind: atom, reason: term, stacktrace: list}
- Measurements:
Anonymous Run Events
Wrap a Condukt.run/2 call (the runtime entry point that does not require
an agent module). The inner agent and tool events still fire for free.
[:condukt, :run, :start]- Anonymous run started- Measurements:
%{system_time: integer} - Metadata:
%{structured?: boolean, input?: boolean}
- Measurements:
[:condukt, :run, :stop]- Anonymous run finished- Measurements:
%{duration: integer} - Metadata:
%{structured?: boolean, input?: boolean}
- Measurements:
[:condukt, :run, :exception]- Anonymous run raised an exception- Measurements:
%{duration: integer} - Metadata:
%{structured?: boolean, input?: boolean, kind: atom, reason: term, stacktrace: list}
- Measurements:
Example: Attaching Handlers
:telemetry.attach_many(
"my-agent-handler",
[
[:condukt, :agent, :start],
[:condukt, :agent, :stop],
[:condukt, :tool_call, :stop],
[:condukt, :subagent, :start],
[:condukt, :subagent, :stop],
[:condukt, :secrets, :resolve],
[:condukt, :secrets, :access]
],
&MyApp.Telemetry.handle_event/4,
nil
)