Skip to main content

a2a/
message.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5/// The semantic category of a message.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum MessageKind {
9    /// A work assignment.
10    Task,
11    /// A reply to a previous message.
12    Reply,
13    /// A question requiring a response.
14    Question,
15    /// A status update.
16    Status,
17    /// A file or data artifact.
18    Artifact,
19}
20
21/// A single content item within a message.
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23#[serde(tag = "type", rename_all = "snake_case")]
24pub enum Part {
25    /// Plain text content.
26    Text {
27        /// The text payload.
28        text: String,
29    },
30    /// Structured JSON data.
31    Data {
32        /// The JSON payload.
33        data: serde_json::Value,
34    },
35    /// A file reference by URI.
36    File {
37        /// The file URI.
38        uri: String,
39    },
40}
41
42/// Message delivery state.
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(rename_all = "snake_case")]
45pub enum MsgState {
46    /// Not yet claimed by any worker.
47    Unread,
48    /// Claimed by exactly one worker (atomic).
49    Delivered,
50    /// Fully processed.
51    Consumed,
52}
53
54/// An agent-to-agent message in the team mailbox.
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct Message {
57    /// Unique message identifier.
58    pub id: Uuid,
59    /// Team this message belongs to.
60    pub team_id: String,
61    /// Optional associated task.
62    pub task_id: Option<Uuid>,
63    /// Sending agent name.
64    pub from: String,
65    /// Receiving agent name.
66    pub to: String,
67    /// Message category.
68    pub kind: MessageKind,
69    /// Message content parts.
70    pub parts: Vec<Part>,
71    /// Optional reference to the message being replied to.
72    pub in_reply_to: Option<Uuid>,
73    /// Delivery state.
74    pub state: MsgState,
75    /// When the message was created.
76    pub created_at: DateTime<Utc>,
77    /// When the message was consumed, if at all.
78    pub consumed_at: Option<DateTime<Utc>>,
79}
80
81impl Message {
82    /// Create a new unread message.
83    pub fn new(
84        team_id: impl Into<String>,
85        from: impl Into<String>,
86        to: impl Into<String>,
87        kind: MessageKind,
88        parts: Vec<Part>,
89    ) -> Self {
90        Message {
91            id: Uuid::new_v4(),
92            team_id: team_id.into(),
93            task_id: None,
94            from: from.into(),
95            to: to.into(),
96            kind,
97            parts,
98            in_reply_to: None,
99            state: MsgState::Unread,
100            created_at: Utc::now(),
101            consumed_at: None,
102        }
103    }
104}
105
106/// A file or data artifact produced by an agent.
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub struct Artifact {
109    /// The artifact category (e.g. "diff", "report").
110    pub kind: String,
111    /// The artifact content (text, base64, or URI).
112    pub content: String,
113    /// Optional human-readable name.
114    pub name: Option<String>,
115}