Expand description
Event-specific hooks for observing and steering an agent run.
AgentHook replaces the old universal event/action pair with one lifecycle
method and one action type per event. Unsupported combinations are therefore
rejected by the compiler instead of being interpreted at runtime.
Hooks are independent of the agent’s CompletionModel:
managed response events carry canonical Rig messages, content, usage, and
message IDs. Use the direct completion or streaming APIs when a hook-like
integration needs the provider’s typed raw response.
Hooks run in registration order through HookStack. Completion-call
RequestPatch values accumulate and merge; tool-call argument rewrites and
tool-result presentation rewrites chain into later hooks. A
ModelTurnAction::Retry or stop action short-circuits the remaining hooks
for that event. Nested stacks obey the same rules as flat stacks, including
preserving an argument rewrite when an inner stack later skips or stops.
Register observe-only hooks before steering hooks when every observation is
required: a steering stop intentionally prevents later observers from
running. Tool-result rewrites change the effective presentation sent to
the model and recorded as result-content telemetry. The
ToolResultEvent::raw_result and its ToolResultEvent::tool_context
remain unchanged for policy decisions and execution-outcome metadata. A
tool-result stop omits result content from telemetry.
Blocking and streaming agents share model-turn, request, tool-call, and
tool-result resolution. Streaming adds delta-specific observations, but
shared lifecycle actions have identical semantics on both surfaces. Streamed
deltas are provisional until the model turn is accepted; a retry is surfaced
as MultiTurnStreamItem::ModelTurnRetried
so consumers can discard the rejected turn’s deltas.
§Example
use rig_agent::agent::{
AgentHook, CompletionResponseEvent, HookContext, ObservationAction,
};
struct ResponseLogger;
impl AgentHook for ResponseLogger {
async fn on_completion_response(
&self,
_ctx: &HookContext,
event: CompletionResponseEvent<'_>,
) -> ObservationAction {
println!(
"message {:?}: {:?} ({:?})",
event.message_id, event.content, event.usage
);
ObservationAction::continue_run()
}
}§Retrying a completed model turn
A hook can reject a tool-free turn and either reuse the same prompt and
preceding history with fresh request preparation, or preserve the rejected
response and append corrective feedback. Retries use the run’s existing
total model-call budget. A narrower policy limit belongs to the hook and can
be stored in the run-scoped Scratchpad:
use std::{collections::HashMap, sync::atomic::{AtomicUsize, Ordering}};
use rig_agent::agent::{AgentHook, HookContext, ModelTurnAction, ModelTurnFinished};
use rig_core::message::AssistantContent;
static NEXT_HOOK_ID: AtomicUsize = AtomicUsize::new(1);
#[derive(Clone, Default)]
struct RetryCounts(HashMap<usize, usize>);
struct RetryOnMarker {
id: usize,
max_retries: usize,
}
impl RetryOnMarker {
fn new(max_retries: usize) -> Self {
Self {
id: NEXT_HOOK_ID.fetch_add(1, Ordering::Relaxed),
max_retries,
}
}
}
impl AgentHook for RetryOnMarker {
async fn on_model_turn_finished(
&self,
ctx: &HookContext,
event: ModelTurnFinished<'_>,
) -> ModelTurnAction {
let rejected = event.content.iter().any(|content| {
matches!(content, AssistantContent::Text(text) if text.text.contains("RETRY"))
});
if !rejected {
return ModelTurnAction::continue_run();
}
let attempt = ctx.scratchpad().update::<RetryCounts, _>(|counts| {
let attempt = counts.0.entry(self.id).or_default();
*attempt += 1;
*attempt
});
if attempt <= self.max_retries {
ModelTurnAction::retry_with_feedback("Return a complete answer.")
} else {
ModelTurnAction::stop("response retry limit exceeded")
}
}
}Structs§
- Completion
Call - Completion-call event.
- Completion
Response - Canonical non-streaming completion response event.
- Hook
Context - Run-scoped context supplied to hooks.
- Hook
Stack - Ordered composable hook stack.
- Invalid
Tool Call Context - Diagnostics for an invalid model-emitted tool call.
- Model
Turn Finished - Medium-neutral accepted model-turn event.
- Request
Patch - A non-sticky patch applied only to the current turn’s completion request.
- RunId
- Opaque process-scoped identifier for one agent run.
- Scratchpad
- Run-scoped typed storage shared by hooks.
- Stream
Response Finish - Canonical streaming response-finish event.
- Text
Delta - Streaming text delta.
- Tool
Call - Pre-execution tool event.
- Tool
Call Delta - Streaming tool-call delta.
- Tool
Result Event - Post-execution tool event.
Enums§
- Completion
Call Action - Action for completion-call hooks.
- Invalid
Tool Call Action - Action for invalid-tool-call hooks and manual invalid-call resolution.
- Model
Turn Action - Action for the medium-neutral
ModelTurnFinishedevent. - Observation
Action - Action for observe-only lifecycle events.
- Retry
Request - How an accepted, tool-free model turn should be retried.
- Step
Event Kind - Hook event kind used only as an observation performance hint.
- Tool
Call Action - Action for pre-tool hooks.
- Tool
Result Action - Action for post-tool hooks.
Traits§
- Agent
Hook - Per-run lifecycle observer and steerer.