atomr_agents_core/
event.rs1use serde::{Deserialize, Serialize};
2
3use crate::ids::{AgentId, HarnessId, RunId, ToolId, WorkflowId};
4use crate::inference::FinishReason;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(tag = "kind", rename_all = "snake_case")]
11pub enum Event {
12 StrategyResolved {
13 strategy: String,
14 agent_id: Option<AgentId>,
15 elapsed_ms: u64,
16 tokens_used: u32,
17 },
18 ToolInvoked {
19 tool_id: ToolId,
20 args_hash: u64,
21 elapsed_ms: u64,
22 ok: bool,
23 },
24 AgentTurn {
25 agent_id: AgentId,
26 input_tokens: u32,
27 output_tokens: u32,
28 finish_reason: Option<FinishReason>,
29 elapsed_ms: u64,
30 },
31 WorkflowStep {
32 workflow_id: WorkflowId,
33 step_id: String,
34 step_kind: String,
35 elapsed_ms: u64,
36 ok: bool,
37 },
38 HarnessIteration {
39 harness_id: HarnessId,
40 iteration: u64,
41 outcome: String,
42 budget_remaining_tokens: u32,
43 },
44 Backpressure {
45 actor_path: String,
46 queued: u32,
47 dropped: u32,
48 },
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct EventEnvelope {
54 pub timestamp_ms: i64,
55 pub correlation_id: Option<String>,
56 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub run_id: Option<RunId>,
61 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub parent_run_id: Option<RunId>,
63 #[serde(default, skip_serializing_if = "Vec::is_empty")]
64 pub tags: Vec<String>,
65 pub event: Event,
66}
67
68impl EventEnvelope {
69 pub fn now(event: Event) -> Self {
70 Self {
71 timestamp_ms: chrono::Utc::now().timestamp_millis(),
72 correlation_id: None,
73 run_id: None,
74 parent_run_id: None,
75 tags: Vec::new(),
76 event,
77 }
78 }
79
80 pub fn with_run(mut self, run_id: RunId, parent: Option<RunId>) -> Self {
81 self.run_id = Some(run_id);
82 self.parent_run_id = parent;
83 self
84 }
85
86 pub fn with_tags(mut self, tags: Vec<String>) -> Self {
87 self.tags = tags;
88 self
89 }
90}