Expand description
Emits uniform telemetry for Rig agents and companion crates.
rig-tap defines a stable, versioned ObservabilityEvent stream for
prompt, tool, context, memory, and dispatch lifecycle events. Producer
crates can use the same event vocabulary whether the event came from a Rig
agent hook, rig-compose dispatch, rig-memvid memory behavior, or host
application code.
See the crate README for the full schema and consumer recipe. The two consumer-facing types are:
TelemetryHook— implementsrig::agent::PromptHookand emitsprompt.*andtool.*events.ObservedMemory— wraps anyrig::memory::ConversationMemoryand emitscontext.sampledon every load.
Plus ChainedHook for composing two PromptHooks on a single agent.
§Why rig-tap (vs. Rig’s hooks today)
Rig already exposes the raw callbacks and data: rig::agent::PromptHook
(on_completion_call / on_completion_response / on_tool_call /
on_tool_result), the Usage token counts on CompletionResponse, typed
PromptError / CompletionError values, and GenAI span conventions. That
is a callback surface scoped to one agent loop — ephemeral, provider-shaped,
with no on-the-wire form. Nothing leaves the process, correlates across
calls, or speaks a vocabulary other crates share unless you write that glue.
rig-tap turns those callbacks into a stable, versioned, queryable
telemetry contract:
- A versioned wire schema, not just callbacks — every event is a flat,
serde-stableObservabilityEventenvelope.SCHEMA_VERSION+#[non_exhaustive]make additive evolution non-breaking. - One vocabulary across the ecosystem — the same
EventKindcovers agent prompts/tools,rig-composekernel dispatch, memory/context, eval reports, and stateful provider sessions.PromptHookonly sees the in-loop agent path. - OTel-routable scalars — each event surfaces
ScalarFieldsas first-classtracingattributes (model,tool_name,call_id,error_class, …) plusspan_idmirroring, so collectors route without parsing JSON. - Lifecycle pairing — a stable
call_idpairstool.invokedwith its terminal event;previous_response_idchains stateful turns. - Failure semantics —
ErrorClassnormalizes provider errors into a backend-agnostic taxonomy with aretriableflag and HTTP status. - Visibility the hooks lack — provider-hosted tools (
tool.hosted_*), latency milestones (duration_ms,time_to_first_token_ms), and Responses-WebSocket sessions (response.*) have noPromptHookanalog. - Operational plumbing — pluggable
SamplingPolicy, payload truncation, an in-processEventQuery, runtime-agnostic emission.
rig-tap is additive to Rig’s GenAI span conventions: its events live
under a separate tracing target and can be filtered independently.
§Wire format
All events are emitted as a single tracing::info! event on the
EVENT_TARGET target ("rig_tap"). The string field event carries the
JSON-encoded ObservabilityEvent, while scalar rig_tap.* fields expose
kind, conversation_id, version, tick, and occurred_at_millis for
OpenTelemetry collector routing and indexing without JSON parsing.
§Subscriber sizing
Emission is synchronous: every event runs serde + the registered
layers on the calling task. Per-request hot paths (every prompt, every
tool call, every memory load) call into the tracing dispatcher
directly. For production deployments — especially ones that ship
events off-host — wire a non-blocking sink (e.g.
tracing_appender::non_blocking or a bounded channel feeding an
async exporter) so a slow consumer can’t backpressure the agent.
In-process counters and the bundled doc-test layer are fine
synchronous.
§Example
use rig_tap::{TelemetryHook, ObservedMemory};
use rig::memory::InMemoryConversationMemory;
let memory = ObservedMemory::new(InMemoryConversationMemory::new());
let hook = TelemetryHook::<M>::with_defaults("gpt-4o", "thread-1");
// agent.memory(memory).with_hook(hook)Re-exports§
pub use emit::EVENT_TARGET;pub use emit::build_event;pub use emit::current_span_id;pub use emit::emit;pub use emit::emit_kind;pub use emit::try_emit;pub use extract::extract_event;
Modules§
- emit
- Tracing transport for
ObservabilityEvent. - extract
- Extraction helpers for decoding emitted observability events.
Structs§
- Always
Sample - Policy that keeps every event. The default for
TelemetryHook. - Chained
Hook - Combine two
PromptHooks into one. See module docs for combination semantics. - Event
Filter - Predicate used by
EventQueryto select observability events. - Event
Query - Immutable query view over a snapshot of
ObservabilityEventvalues. - Observability
Event - A single observability event with envelope metadata.
- Observed
Memory - Wraps any
ConversationMemoryand emits acontext.sampledevent on everyload.appendandclearpass through unchanged. - Rate
Policy - Per-kind rate sampler with deterministic, paired-event-safe decisions.
- Scalar
Fields - Per-variant scalar correlation fields surfaced as direct
tracingattributes alongside the JSON event blob. SeeEventKind::scalar_fields. - Telemetry
Hook - Per-request hook that emits structured observability events from the five
PromptHooklifecycle methods. - Telemetry
Hook Config - Conversation identifier to stamp on emitted events when the agent runtime
does not surface one to the hook. The Rig
PromptHooksignature does not currently propagate the conversation ID, so the hook stamps events with a constant chosen by the caller (typically"default"for single-thread agents, or a unique value per agent instance for multi-thread setups).
Enums§
- Error
- Errors produced when serializing or processing observability events.
- Error
Class - High-level classification of a prompt or tool failure.
- Event
Kind - Payload variants. Tagged on the wire as
"kind": "<dotted.name>".
Constants§
- PAYLOAD_
TRUNCATE_ BYTES - Maximum byte length of inline
args_json/result_jsonpayloads before they are truncated and marked with"truncated": true. - SCHEMA_
VERSION - Current schema version. Bumped on breaking changes to the wire format.
Traits§
- Sampling
Policy - Decide whether to emit a given event based on its kind discriminant and a stable correlator string.
Functions§
- truncate_
utf8 - Truncate a UTF-8 string to at most
max_bytes, returning the (possibly truncated) string and a flag indicating whether truncation occurred.
Type Aliases§
- Conversation
IdResolver - Caller-supplied resolver for the conversation ID stamped on emitted
events. Consulted on every emission; when it returns
Some(id), that value wins overTelemetryHookConfig::conversation_id. - Model
Resolver - Caller-supplied resolver that pulls the actual model identifier out of a provider response. Useful for routed providers (OpenRouter, Bedrock model-routing, vendor multi-model endpoints) where the model recorded at hook construction is a logical alias and the response’s raw payload carries the concrete model that served the request.
- Previous
Response IdResolver - Caller-supplied resolver that returns the chain ancestor for the current
turn (the
previous_response_idargument sent to the provider) so it can be stamped onprompt.completed.