actflow_agent_sdk/agent.rs
1//! Agent trait definition.
2
3use crate::types::{AgentOutput, Context, Inputs};
4use std::future::Future;
5use tokio::sync::mpsc;
6
7/// A sender for streaming log messages during agent execution.
8#[derive(Clone)]
9pub struct LogSender {
10 tx: mpsc::Sender<String>,
11}
12
13impl LogSender {
14 pub(crate) fn new(tx: mpsc::Sender<String>) -> Self {
15 Self { tx }
16 }
17
18 /// Send a log message.
19 pub async fn send(&self, msg: impl Into<String>) {
20 let _ = self.tx.send(msg.into()).await;
21 }
22
23 /// Send a log message (non-async, best-effort).
24 pub fn try_send(&self, msg: impl Into<String>) {
25 let _ = self.tx.try_send(msg.into());
26 }
27}
28
29/// Trait for implementing an Actflow agent.
30///
31/// Implement this trait to create your own agent that can be executed
32/// by the Actflow workflow engine.
33///
34/// # Example
35///
36/// ```rust,ignore
37/// use actflow_agent_sdk::{Agent, AgentOutput, Context, Inputs, LogSender};
38///
39/// struct MyAgent;
40///
41/// impl Agent for MyAgent {
42/// async fn run(
43/// &self,
44/// nid: String,
45/// ctx: Context,
46/// inputs: Inputs,
47/// log: LogSender,
48/// ) -> AgentOutput {
49/// log.send("Processing...").await;
50/// AgentOutput::success(serde_json::json!({"result": "done"}))
51/// }
52/// }
53/// ```
54pub trait Agent: Send + Sync + 'static {
55 /// Execute the agent logic.
56 ///
57 /// # Arguments
58 ///
59 /// * `nid` - Node ID in the workflow
60 /// * `ctx` - Execution context containing process ID, environment variables, and workflow variables
61 /// * `inputs` - Input data for this agent
62 /// * `log` - Log sender for streaming log messages
63 ///
64 /// # Returns
65 ///
66 /// Returns an `AgentOutput` containing the execution status and output data.
67 fn run(
68 &self,
69 nid: String,
70 ctx: Context,
71 inputs: Inputs,
72 log: LogSender,
73 ) -> impl Future<Output = AgentOutput> + Send;
74
75 /// Called when the agent should shut down.
76 ///
77 /// Override this method to perform cleanup operations.
78 /// Default implementation does nothing.
79 fn shutdown(&self) -> impl Future<Output = ()> + Send {
80 async {}
81 }
82}
83