Skip to main content

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

AgentInput

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

Text
String
Single text string input
let input = AgentInput::Text("Hello, agent!".to_string());
// Or using the builder
let input = AgentInput::text("Hello, agent!");
Texts
Vec<String>
Multiple text strings (multi-line text)
let input = AgentInput::Texts(vec![
    "Line 1".to_string(),
    "Line 2".to_string(),
]);
Json
serde_json::Value
Structured JSON data
let input = AgentInput::json(serde_json::json!({
    "action": "search",
    "query": "Rust programming"
}));
Map
HashMap<String, serde_json::Value>
Key-value pairs
let mut map = HashMap::new();
map.insert("key1".to_string(), json!("value1"));
let input = AgentInput::map(map);
Binary
Vec<u8>
Binary data (images, files, etc.)
let data = vec![0x89, 0x50, 0x4E, 0x47]; // PNG header
let input = AgentInput::Binary(data);
Multimodal
Vec<serde_json::Value>
Multimodal content parts (text, images, audio)
let input = AgentInput::Multimodal(vec![
    json!({"type": "text", "content": "Describe this image"}),
    json!({"type": "image_url", "url": "https://..."}),
]);
Empty
()
Empty input (default)

Methods

text
fn(s: impl Into<String>) -> Self
Creates a text input
let input = AgentInput::text("Query text");
json
fn(value: serde_json::Value) -> Self
Creates a JSON input
let input = AgentInput::json(json!({"key": "value"}));
as_text
fn(&self) -> Option<&str>
Gets text content if input is Text variant
if let Some(text) = input.as_text() {
    println!("Text: {}", text);
}
to_text
fn(&self) -> String
Converts any input variant to text representation
let 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
is_empty
fn(&self) -> bool
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

content
OutputContent
required
The main output content. See OutputContent below.
metadata
HashMap<String, serde_json::Value>
Arbitrary metadata key-value pairs
tools_used
Vec<ToolUsage>
List of tools used during execution. See ToolUsage.
reasoning_steps
Vec<ReasoningStep>
Step-by-step reasoning process (for ReAct agents, etc.)
duration_ms
u64
Execution time in milliseconds
token_usage
Option<TokenUsage>
LLM token usage statistics. See TokenUsage.

Constructor Methods

text
fn(s: impl Into<String>) -> Self
Creates a text output
let output = AgentOutput::text("Task completed successfully");
json
fn(value: serde_json::Value) -> Self
Creates a JSON output
let output = AgentOutput::json(json!({
    "status": "success",
    "result": 42
}));
error
fn(message: impl Into<String>) -> Self
Creates an error output
let output = AgentOutput::error("Invalid input format");

Builder Methods

with_duration
fn(self, duration_ms: u64) -> Self
Sets execution duration
let output = AgentOutput::text("Done")
    .with_duration(150);
with_metadata
fn(self, key: impl Into<String>, value: serde_json::Value) -> Self
Adds a metadata entry
let 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
to_text
fn(&self) -> String
Converts output to text representation
is_error
fn(&self) -> bool
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,
}
Text
String
Single text string output
Texts
Vec<String>
Multiple text strings
Json
serde_json::Value
Structured JSON output
Binary
Vec<u8>
Binary data output
Stream
()
Marker for streaming output (actual stream handled separately)
Error
String
Error message
Empty
()
Empty output

ToolUsage

#[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
String
required
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)
success
bool
required
Whether the tool execution succeeded
error
Option<String>
Error message (if failed)
duration_ms
u64
required
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
String
required
Content of the reasoning step
step_number
usize
required
Sequential step number
timestamp_ms
u64
required
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

Build docs developers (and LLMs) love