conversation_api/execution/event.rs
1//! Durable Agent events and their delivery boundary.
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::execution::{
8 EventId, ExternalError, InvocationContext, MessageId, PreparedAction, RuntimeSnapshot,
9 UsageSummary,
10};
11
12/// Event emitted by the Runtime.
13#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
14#[serde(tag = "type", rename_all = "snake_case")]
15pub enum AgentEvent {
16 /// A run has started or resumed.
17 Started,
18 /// The run requires user input before it can continue.
19 InteractionRequired {
20 /// Batch identifier answered by `SubmitInteraction`.
21 batch_id: MessageId,
22 /// Prepared actions awaiting one decision each.
23 actions: Vec<PreparedAction>,
24 /// Usage accumulated before Runtime suspended the run.
25 usage: UsageSummary,
26 },
27 /// The run completed successfully.
28 Completed {
29 /// Final structured result.
30 result: Value,
31 /// Aggregated usage for the completed run.
32 usage: UsageSummary,
33 },
34 /// The run failed definitively.
35 Failed {
36 /// Stable machine-readable failure code.
37 code: String,
38 /// Safe user-facing or diagnostic message.
39 message: String,
40 /// Usage settled before the failure, cancellation, or interruption.
41 usage: UsageSummary,
42 },
43}
44
45/// Best-effort, request-scoped observation that is not part of the durable outbox.
46#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
47#[serde(tag = "type", rename_all = "snake_case")]
48pub enum AgentObservation {
49 /// Coarse progress for live presentation.
50 Progress {
51 /// Stable progress label.
52 status: String,
53 },
54 /// Temporary assistant text emitted before a tool batch.
55 CompanionText {
56 /// Text shown while work continues.
57 content: String,
58 /// Whether a client should append rather than replace.
59 append: bool,
60 },
61 /// A tool attempt is starting.
62 ToolStarted {
63 /// Model tool-call identifier.
64 call_id: String,
65 /// Stable tool name.
66 tool_name: String,
67 },
68 /// A tool attempt produced a result.
69 ToolResult {
70 /// Model tool-call identifier.
71 call_id: String,
72 /// Stable tool name.
73 tool_name: String,
74 /// Structured result.
75 result: Value,
76 /// Whether execution failed.
77 is_error: bool,
78 },
79 /// A validated model tool-call batch has been checkpointed for execution.
80 ToolCallsScheduled {
81 /// Tool names in model order.
82 tool_names: Vec<String>,
83 },
84 /// A tool batch completed and its results are available to the next model step.
85 ToolCallsCompleted {
86 /// Number of completed tool calls.
87 count: u32,
88 },
89 /// Optional diagnostic payload requested by the caller.
90 DebugData {
91 /// Diagnostic namespace.
92 scope: String,
93 /// Structured diagnostic value.
94 payload: Value,
95 },
96}
97
98/// Sequenced event persisted as part of a thread transition.
99#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
100pub struct DurableEvent {
101 /// Globally unique event identifier used for deduplication.
102 pub id: EventId,
103 /// Monotonic sequence within a thread.
104 pub sequence: u64,
105 /// Frozen routing, ownership, and run identity for this event.
106 pub context: InvocationContext,
107 /// Event payload.
108 pub event: AgentEvent,
109}
110
111/// Delivery boundary for events that have already been durably committed.
112#[async_trait]
113pub trait EventPublisher: Send + Sync {
114 /// Publishes one committed stable-boundary event with at-least-once delivery semantics.
115 ///
116 /// `snapshot` is the exact Runtime generation committed with `event`. Implementations must
117 /// never reload a newer snapshot while encoding the event.
118 async fn publish(
119 &self,
120 snapshot: &RuntimeSnapshot,
121 event: &DurableEvent,
122 ) -> Result<(), ExternalError>;
123}
124
125/// Best-effort observer for non-durable UI progress.
126#[async_trait]
127pub trait Observer: Send + Sync {
128 /// Delivers one request-scoped observation.
129 async fn observe(&self, context: &InvocationContext, observation: &AgentObservation);
130}