Skip to main content

autoagents_protocol/
protocol.rs

1use crate::StreamChunk;
2use crate::task::Task;
3use crate::tool::ToolCallResult;
4use serde::{Deserialize, Serialize};
5use std::any::{Any, TypeId};
6use std::fmt::Debug;
7use std::sync::Arc;
8use uuid::Uuid;
9
10/// Submission IDs are used to track actor tasks
11pub type SubmissionId = Uuid;
12
13/// Agent IDs are used to identify actors
14pub type ActorID = Uuid;
15
16/// Session IDs are used to identify sessions
17pub type RuntimeID = Uuid;
18
19/// Event IDs are used to correlate events with their responses
20pub type EventId = Uuid;
21
22/// Protocol events represent the various events that can occur during actor execution
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub enum Event {
25    // /// A new task has been submitted to an agent
26    NewTask {
27        actor_id: ActorID,
28        task: Task,
29    },
30
31    /// A task has started execution
32    TaskStarted {
33        sub_id: SubmissionId,
34        actor_id: ActorID,
35        actor_name: String,
36        task_description: String,
37    },
38
39    /// A task has been completed
40    TaskComplete {
41        sub_id: SubmissionId,
42        actor_id: ActorID,
43        actor_name: String,
44        result: String,
45    },
46
47    /// A task encountered an error
48    TaskError {
49        sub_id: SubmissionId,
50        actor_id: ActorID,
51        error: String,
52    },
53
54    #[serde(skip)]
55    PublishMessage {
56        topic_name: String,
57        topic_type: TypeId,
58        message: Arc<dyn Any + Send + Sync>,
59    },
60
61    SendMessage {
62        message: String,
63        actor_id: ActorID,
64    },
65
66    /// Tool call requested (with ID)
67    ToolCallRequested {
68        sub_id: SubmissionId,
69        actor_id: ActorID,
70        id: String,
71        tool_name: String,
72        arguments: String,
73    },
74
75    /// Tool call completed (with ID and result)
76    ToolCallCompleted {
77        sub_id: SubmissionId,
78        actor_id: ActorID,
79        id: String,
80        tool_name: String,
81        result: serde_json::Value,
82    },
83
84    /// Tool call has failed
85    ToolCallFailed {
86        sub_id: SubmissionId,
87        actor_id: ActorID,
88        id: String,
89        tool_name: String,
90        error: String,
91    },
92
93    /// A turn has started
94    TurnStarted {
95        sub_id: SubmissionId,
96        actor_id: ActorID,
97        turn_number: usize,
98        max_turns: usize,
99    },
100
101    /// A turn has completed
102    TurnCompleted {
103        sub_id: SubmissionId,
104        actor_id: ActorID,
105        turn_number: usize,
106        final_turn: bool,
107    },
108
109    /// Streaming chunk from agent
110    StreamChunk {
111        sub_id: SubmissionId,
112        chunk: StreamChunk,
113    },
114
115    /// Streaming tool call chunk
116    StreamToolCall {
117        sub_id: SubmissionId,
118        tool_call: serde_json::Value,
119    },
120
121    /// Streaming completed
122    StreamComplete {
123        sub_id: SubmissionId,
124    },
125}
126
127/// Internal events that are processed within the runtime
128#[derive(Debug)]
129pub enum InternalEvent {
130    /// Process a protocol event
131    ProtocolEvent(Event),
132    /// Shutdown signal
133    Shutdown,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub enum StreamingTurnResult {
138    Complete(String),
139    ToolCallsProcessed(Vec<ToolCallResult>),
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145    use serde_json::json;
146
147    #[test]
148    fn test_event_serialization_new_task() {
149        let _ = Uuid::new_v4();
150        let event = Event::NewTask {
151            actor_id: Default::default(),
152            task: Task::new(String::from("test")),
153        };
154
155        //Check if serialization and deserilization works properly
156        let serialized = serde_json::to_string(&event).unwrap();
157        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
158
159        match deserialized {
160            Event::NewTask { task, .. } => {
161                assert_eq!(task.prompt, "test");
162            }
163            _ => panic!("Expected NewTask variant"),
164        }
165    }
166
167    #[test]
168    fn test_event_serialization_task_started() {
169        let event = Event::TaskStarted {
170            sub_id: Uuid::new_v4(),
171            actor_id: Default::default(),
172            actor_name: String::from("test"),
173            task_description: "Started task".to_string(),
174        };
175
176        let serialized = serde_json::to_string(&event).unwrap();
177        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
178
179        match deserialized {
180            Event::TaskStarted {
181                task_description, ..
182            } => {
183                assert_eq!(task_description, "Started task");
184            }
185            _ => panic!("Expected TaskStarted variant"),
186        }
187    }
188
189    #[test]
190    fn test_event_serialization_tool_calls() {
191        let tool_call_requested = Event::ToolCallRequested {
192            sub_id: Uuid::new_v4(),
193            actor_id: Uuid::new_v4(),
194            id: "call_123".to_string(),
195            tool_name: "test_tool".to_string(),
196            arguments: "{\"param\": \"value\"}".to_string(),
197        };
198
199        let serialized = serde_json::to_string(&tool_call_requested).unwrap();
200        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
201
202        match deserialized {
203            Event::ToolCallRequested {
204                id,
205                tool_name,
206                arguments,
207                ..
208            } => {
209                assert_eq!(id, "call_123");
210                assert_eq!(tool_name, "test_tool");
211                assert_eq!(arguments, "{\"param\": \"value\"}");
212            }
213            _ => panic!("Expected ToolCallRequested variant"),
214        }
215    }
216
217    #[test]
218    fn test_event_serialization_tool_call_completed() {
219        let result = json!({"output": "tool result"});
220        let event = Event::ToolCallCompleted {
221            sub_id: Uuid::new_v4(),
222            actor_id: Uuid::new_v4(),
223            id: "call_456".to_string(),
224            tool_name: "completed_tool".to_string(),
225            result: result.clone(),
226        };
227
228        let serialized = serde_json::to_string(&event).unwrap();
229        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
230
231        match deserialized {
232            Event::ToolCallCompleted {
233                id,
234                tool_name,
235                result: res,
236                ..
237            } => {
238                assert_eq!(id, "call_456");
239                assert_eq!(tool_name, "completed_tool");
240                assert_eq!(res, result);
241            }
242            _ => panic!("Expected ToolCallCompleted variant"),
243        }
244    }
245
246    #[test]
247    fn test_event_serialization_tool_call_failed() {
248        let event = Event::ToolCallFailed {
249            sub_id: Uuid::new_v4(),
250            actor_id: Uuid::new_v4(),
251            id: "call_789".to_string(),
252            tool_name: "failed_tool".to_string(),
253            error: "Tool execution failed".to_string(),
254        };
255
256        let serialized = serde_json::to_string(&event).unwrap();
257        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
258
259        match deserialized {
260            Event::ToolCallFailed {
261                id,
262                tool_name,
263                error,
264                ..
265            } => {
266                assert_eq!(id, "call_789");
267                assert_eq!(tool_name, "failed_tool");
268                assert_eq!(error, "Tool execution failed");
269            }
270            _ => panic!("Expected ToolCallFailed variant"),
271        }
272    }
273
274    #[test]
275    fn test_event_serialization_turn_events() {
276        let turn_started = Event::TurnStarted {
277            sub_id: Uuid::new_v4(),
278            actor_id: Uuid::new_v4(),
279            turn_number: 1,
280            max_turns: 10,
281        };
282
283        let serialized = serde_json::to_string(&turn_started).unwrap();
284        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
285
286        match deserialized {
287            Event::TurnStarted {
288                turn_number,
289                max_turns,
290                ..
291            } => {
292                assert_eq!(turn_number, 1);
293                assert_eq!(max_turns, 10);
294            }
295            _ => panic!("Expected TurnStarted variant"),
296        }
297
298        let turn_completed = Event::TurnCompleted {
299            sub_id: Uuid::new_v4(),
300            actor_id: Uuid::new_v4(),
301            turn_number: 1,
302            final_turn: false,
303        };
304
305        let serialized = serde_json::to_string(&turn_completed).unwrap();
306        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
307
308        match deserialized {
309            Event::TurnCompleted {
310                turn_number,
311                final_turn,
312                ..
313            } => {
314                assert_eq!(turn_number, 1);
315                assert!(!final_turn);
316            }
317            _ => panic!("Expected TurnCompleted variant"),
318        }
319    }
320
321    #[test]
322    fn test_uuid_types() {
323        let submission_id: SubmissionId = Uuid::new_v4();
324        let agent_id: ActorID = Uuid::new_v4();
325        let runtime_id: RuntimeID = Uuid::new_v4();
326        let event_id: EventId = Uuid::new_v4();
327
328        // Test that all UUID types can be used interchangeably
329        assert_ne!(submission_id, agent_id);
330        assert_ne!(runtime_id, event_id);
331    }
332}