AgentInput & AgentOutput
The AgentInput and AgentOutput types define the data structures for agent task execution. They support multiple formats including text, JSON, binary, and multimodal content.
Location: mofa-kernel/src/agent/types.rs
Type Definition
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub enum AgentInput {
Text(String),
Texts(Vec<String>),
Json(serde_json::Value),
Map(HashMap<String, serde_json::Value>),
Binary(Vec<u8>),
Multimodal(Vec<serde_json::Value>),
#[default]
Empty,
}
Variants
Single text string inputlet input = AgentInput::Text("Hello, agent!".to_string());
// Or using the builder
let input = AgentInput::text("Hello, agent!");
Multiple text strings (multi-line text)let input = AgentInput::Texts(vec![
"Line 1".to_string(),
"Line 2".to_string(),
]);
Structured JSON datalet input = AgentInput::json(serde_json::json!({
"action": "search",
"query": "Rust programming"
}));
Map
HashMap<String, serde_json::Value>
Key-value pairslet mut map = HashMap::new();
map.insert("key1".to_string(), json!("value1"));
let input = AgentInput::map(map);
Binary data (images, files, etc.)let data = vec![0x89, 0x50, 0x4E, 0x47]; // PNG header
let input = AgentInput::Binary(data);
Multimodal content parts (text, images, audio)let input = AgentInput::Multimodal(vec![
json!({"type": "text", "content": "Describe this image"}),
json!({"type": "image_url", "url": "https://..."}),
]);
Methods
text
fn(s: impl Into<String>) -> Self
Creates a text inputlet input = AgentInput::text("Query text");
json
fn(value: serde_json::Value) -> Self
Creates a JSON inputlet input = AgentInput::json(json!({"key": "value"}));
as_text
fn(&self) -> Option<&str>
Gets text content if input is Text variantif let Some(text) = input.as_text() {
println!("Text: {}", text);
}
Converts any input variant to text representationlet text = input.to_text();
as_json
fn(&self) -> Option<&serde_json::Value>
Gets JSON content if input is Json variant
to_json
fn(&self) -> serde_json::Value
Converts any input variant to JSON
Checks if input is the Empty variant
AgentOutput
Type Definition
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentOutput {
pub content: OutputContent,
pub metadata: HashMap<String, serde_json::Value>,
pub tools_used: Vec<ToolUsage>,
pub reasoning_steps: Vec<ReasoningStep>,
pub duration_ms: u64,
pub token_usage: Option<TokenUsage>,
}
Fields
metadata
HashMap<String, serde_json::Value>
Arbitrary metadata key-value pairs
List of tools used during execution. See ToolUsage.
Step-by-step reasoning process (for ReAct agents, etc.)
Execution time in milliseconds
Constructor Methods
text
fn(s: impl Into<String>) -> Self
Creates a text outputlet output = AgentOutput::text("Task completed successfully");
json
fn(value: serde_json::Value) -> Self
Creates a JSON outputlet output = AgentOutput::json(json!({
"status": "success",
"result": 42
}));
error
fn(message: impl Into<String>) -> Self
Creates an error outputlet output = AgentOutput::error("Invalid input format");
Builder Methods
with_duration
fn(self, duration_ms: u64) -> Self
Sets execution durationlet output = AgentOutput::text("Done")
.with_duration(150);
with_metadata
fn(self, key: impl Into<String>, value: serde_json::Value) -> Self
Adds a metadata entrylet output = AgentOutput::text("Result")
.with_metadata("source", json!("database"))
.with_metadata("confidence", json!(0.95));
with_tool_usage
fn(self, usage: ToolUsage) -> Self
Adds a tool usage record
with_tools_used
fn(self, usages: Vec<ToolUsage>) -> Self
Sets all tool usage records at once
with_reasoning_step
fn(self, step: ReasoningStep) -> Self
Adds a reasoning step
with_reasoning_steps
fn(self, steps: Vec<ReasoningStep>) -> Self
Sets all reasoning steps at once
with_token_usage
fn(self, usage: TokenUsage) -> Self
Sets token usage statistics
Query Methods
as_text
fn(&self) -> Option<&str>
Gets text content if output is text
Converts output to text representation
Checks if output is an error
OutputContent
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub enum OutputContent {
Text(String),
Texts(Vec<String>),
Json(serde_json::Value),
Binary(Vec<u8>),
Stream,
Error(String),
Empty,
}
Single text string output
Marker for streaming output (actual stream handled separately)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolUsage {
pub name: String,
pub input: serde_json::Value,
pub output: Option<serde_json::Value>,
pub success: bool,
pub error: Option<String>,
pub duration_ms: u64,
}
Fields
Name of the tool that was used
input
serde_json::Value
required
Input parameters passed to the tool
output
Option<serde_json::Value>
Tool output (if successful)
Whether the tool execution succeeded
Error message (if failed)
Tool execution duration in milliseconds
Constructor Methods
impl ToolUsage {
pub fn success(
name: impl Into<String>,
input: serde_json::Value,
output: serde_json::Value,
duration_ms: u64,
) -> Self;
pub fn failure(
name: impl Into<String>,
input: serde_json::Value,
error: impl Into<String>,
duration_ms: u64,
) -> Self;
}
ReasoningStep
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReasoningStep {
pub step_type: ReasoningStepType,
pub content: String,
pub step_number: usize,
pub timestamp_ms: u64,
}
Fields
step_type
ReasoningStepType
required
Type of reasoning step (Thought, Action, Observation, etc.)
Content of the reasoning step
Timestamp in milliseconds
ReasoningStepType
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ReasoningStepType {
Thought,
Action,
Observation,
Reflection,
Decision,
FinalAnswer,
Custom(String),
}
TokenUsage
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TokenUsage {
pub prompt_tokens: u32,
pub completion_tokens: u32,
pub total_tokens: u32,
}
Constructor
impl TokenUsage {
pub fn new(prompt_tokens: u32, completion_tokens: u32) -> Self {
let total_tokens = prompt_tokens + completion_tokens;
Self { prompt_tokens, completion_tokens, total_tokens }
}
}
AgentState
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub enum AgentState {
#[default]
Created,
Initializing,
Ready,
Running,
Executing,
Paused,
Interrupted,
ShuttingDown,
Shutdown,
Failed,
Destroyed,
Error(String),
}
State Transitions
impl AgentState {
pub fn can_transition_to(&self, target: &AgentState) -> bool;
pub fn transition_to(&self, target: AgentState) -> Result<AgentState, AgentError>;
pub fn is_active(&self) -> bool;
pub fn is_terminal(&self) -> bool;
}
Valid state transitions:
Created → Initializing
Initializing → Ready | Error | Failed
Ready → Executing | Running | ShuttingDown
Running → Paused | Executing | ShuttingDown | Error | Failed
Executing → Ready | Paused | Interrupted | Error | Failed
Paused → Ready | Executing | ShuttingDown
Interrupted → Ready | ShuttingDown
ShuttingDown → Shutdown
Example Usage
use mofa_sdk::kernel::{AgentInput, AgentOutput, AgentState, ToolUsage, ReasoningStep, ReasoningStepType, TokenUsage};
// Create input
let input = AgentInput::text("Analyze the data");
// Create output with full details
let output = AgentOutput::text("Analysis complete")
.with_duration(250)
.with_metadata("model", json!("gpt-4o"))
.with_tool_usage(ToolUsage::success(
"database_query",
json!({"query": "SELECT * FROM data"}),
json!({"rows": 42}),
100,
))
.with_reasoning_step(ReasoningStep::new(
ReasoningStepType::Thought,
"Need to query the database",
1,
))
.with_token_usage(TokenUsage::new(150, 75));
println!("Result: {}", output.to_text());
println!("Duration: {}ms", output.duration_ms);
println!("Tools used: {}", output.tools_used.len());
See Also