Skip to main content

Lifecycle & Events

Distri emits structured events for every agent run. Use them to drive UI updates, telemetry, and workflow automation.

Threads Interface


Run Lifecycle

EventPayloadNotes
run_started{ thread_id, run_id, agent_id }Fired when a new run begins.
plan_started{ initial_plan }Indicates the planner kicked off.
plan_finished{ total_steps }Planner produced a plan.
plan_pruned{ removed_steps }Planner removed branches.
run_finished{ success, total_steps, failed_steps }Run completed successfully.
run_error{ message, code? }Terminal failure.

Step Execution

EventPayloadNotes
step_started{ step_id, step_index }Planner step begins executing.
step_completed{ step_id, success }Step finished, identify retries/flaky tools.

Tool Execution

EventPayloadNotes
tool_execution_start{ step_id, tool_call_id, tool_call_name, input }Tool call dispatched.
tool_execution_end{ step_id, tool_call_id, tool_call_name, success }Tool finished; check success.
tool_calls{ step_id, parent_message_id?, tool_calls: ToolCall[] }Batched tool call metadata.
tool_results{ step_id, parent_message_id?, results: ToolResponse[] }Batched tool outputs.

Streaming Messages

EventPayloadNotes
text_message_start{ message_id, step_id, role, is_final? }Begin streaming content for a message.
text_message_content{ message_id, step_id, delta, stripped_content? }Token-level updates.
text_message_end{ message_id, step_id }Message finished streaming.

Agent Handover

EventPayloadNotes
agent_handover{ from_agent, to_agent, reason? }Control transferred to another agent.

Workflow Orchestration

EventPayloadNotes
workflow_started{ workflow_name, total_steps }Workflow initiated.
node_started{ node_id, node_name, step_type }Workflow node began execution.
node_completed{ node_id, node_name, success, error? }Node finished with status.
run_completed{ workflow_name, success, total_steps }Workflow run succeeded.
run_failed{ workflow_name, error, failed_at_step? }Workflow run failed.

Todos

EventPayloadNotes
todos_updated{ formatted_todos, action, todo_count }Planner-generated tasks changed.

Listening to Events

React

import { useAgent, useAgentEvents } from '@distri/react';

function AgentUI() {
const { agent } = useAgent({ agentIdOrDef: 'my_agent' });

useAgentEvents({
onRunStarted: (event) => {
console.log('Run started:', event.run_id);
},
onToolExecutionStart: (event) => {
console.log('Tool called:', event.tool_call_name);
},
onTextMessageContent: (event) => {
console.log('Streaming:', event.delta);
},
onRunFinished: (event) => {
console.log('Run finished:', event.success);
},
});

return <Chat agent={agent} />;
}

SSE (Server-Sent Events)

const eventSource = new EventSource(
'https://api.distri.dev/v1/agents/my_agent/stream'
);

eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'run_started':
console.log('Run started:', data.payload);
break;
case 'tool_execution_start':
console.log('Tool called:', data.payload.tool_call_name);
break;
case 'text_message_content':
console.log('Content:', data.payload.delta);
break;
}
};

Creating Custom Events

use distri_types::events::{AgentEvent, AgentEventType};

let event = AgentEvent::with_context(
AgentEventType::RunError {
message: "verification failed".into(),
code: Some("INVALID_STATE".into()),
},
thread_id.to_string(),
run_id.to_string(),
task_id.to_string(),
agent_id.to_string(),
);
log::info!("event={:?}", event);