Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mofa-org/mofa/llms.txt
Use this file to discover all available pages before exploring further.
The AgentPlugin trait is the foundational interface for all plugins in the MoFA framework. It defines the complete plugin lifecycle from loading to execution and unloading.
Trait Definition
#[async_trait]
pub trait AgentPlugin: Send + Sync {
fn metadata(&self) -> &PluginMetadata;
fn plugin_id(&self) -> &str;
fn plugin_type(&self) -> PluginType;
fn state(&self) -> PluginState;
async fn load(&mut self, ctx: &PluginContext) -> PluginResult<()>;
async fn init_plugin(&mut self) -> PluginResult<()>;
async fn start(&mut self) -> PluginResult<()>;
async fn pause(&mut self) -> PluginResult<()>;
async fn resume(&mut self) -> PluginResult<()>;
async fn stop(&mut self) -> PluginResult<()>;
async fn unload(&mut self) -> PluginResult<()>;
async fn execute(&mut self, input: String) -> PluginResult<String>;
async fn health_check(&self) -> PluginResult<bool>;
fn stats(&self) -> HashMap<String, serde_json::Value>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
}
Lifecycle Methods
Plugins follow a strict lifecycle with the following states:
load
Allocate resources and prepare the plugin for initialization.
Plugin execution context containing configuration and shared state
async fn load(&mut self, ctx: &PluginContext) -> PluginResult<()> {
// Allocate resources, read configuration
self.config = ctx.config.clone();
self.state = PluginState::Loaded;
Ok(())
}
init_plugin
Initialize plugin-specific configuration and state.
async fn init_plugin(&mut self) -> PluginResult<()> {
// Initialize internal state
// Call any setup methods
self.state = PluginState::Running;
Ok(())
}
start
Start the plugin and make it ready for execution.
async fn start(&mut self) -> PluginResult<()> {
self.state = PluginState::Running;
Ok(())
}
pause
Temporarily suspend plugin execution (optional).
async fn pause(&mut self) -> PluginResult<()> {
self.state = PluginState::Paused;
Ok(())
}
resume
Resume a paused plugin (optional).
async fn resume(&mut self) -> PluginResult<()> {
self.state = PluginState::Running;
Ok(())
}
stop
Stop plugin execution.
async fn stop(&mut self) -> PluginResult<()> {
self.state = PluginState::Paused;
Ok(())
}
unload
Release all resources and clean up.
async fn unload(&mut self) -> PluginResult<()> {
// Release resources
self.state = PluginState::Unloaded;
Ok(())
}
Execution Methods
execute
Execute the plugin’s core functionality.
Input data as a string (typically JSON)
Execution result as a string (typically JSON)
async fn execute(&mut self, input: String) -> PluginResult<String> {
// Parse input
let data: InputType = serde_json::from_str(&input)?;
// Execute plugin logic
let result = self.process(data).await?;
// Return result as JSON
Ok(serde_json::to_string(&result)?)
}
health_check
Perform a health check on the plugin.
async fn health_check(&self) -> PluginResult<bool> {
Ok(self.state() == PluginState::Running)
}
stats
Return plugin runtime statistics.
fn stats(&self) -> HashMap<String, serde_json::Value> {
let mut stats = HashMap::new();
stats.insert("calls_total".to_string(), json!(self.call_count));
stats.insert("state".to_string(), json!(format!("{:?}", self.state)));
stats
}
Return plugin metadata.
fn metadata(&self) -> &PluginMetadata {
&self.metadata
}
plugin_id
Convenience method to get the plugin ID.
fn plugin_id(&self) -> &str {
&self.metadata().id
}
plugin_type
Return the plugin type.
fn plugin_type(&self) -> PluginType {
self.metadata().plugin_type.clone()
}
Type Casting Methods
These methods enable downcasting to concrete plugin types:
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
Plugin States
pub enum PluginState {
Unloaded, // Not initialized
Loading, // Currently loading
Loaded, // Loaded and ready
Running, // Active and executing
Paused, // Temporarily suspended
Error(String), // Error state with message
}
Plugin Types
pub enum PluginType {
LLM, // LLM capability plugin
Tool, // Tool calling plugin
Storage, // Storage plugin
Memory, // Memory management plugin
VectorDB, // Vector database plugin
Communication, // Communication plugin
Monitor, // Monitor plugin
Skill, // Agent Skills plugin
Custom(String),// Custom plugin type
}
Example Implementation
use mofa_kernel::plugin::{AgentPlugin, PluginMetadata, PluginState, PluginType};
use std::any::Any;
struct MyPlugin {
metadata: PluginMetadata,
state: PluginState,
call_count: u64,
}
impl MyPlugin {
pub fn new() -> Self {
let metadata = PluginMetadata::new(
"my-plugin",
"My Custom Plugin",
PluginType::Custom("example".to_string()),
)
.with_description("An example plugin implementation");
Self {
metadata,
state: PluginState::Unloaded,
call_count: 0,
}
}
}
#[async_trait]
impl AgentPlugin for MyPlugin {
fn metadata(&self) -> &PluginMetadata {
&self.metadata
}
fn state(&self) -> PluginState {
self.state.clone()
}
async fn load(&mut self, ctx: &PluginContext) -> PluginResult<()> {
self.state = PluginState::Loaded;
Ok(())
}
async fn init_plugin(&mut self) -> PluginResult<()> {
self.state = PluginState::Running;
Ok(())
}
async fn start(&mut self) -> PluginResult<()> {
self.state = PluginState::Running;
Ok(())
}
async fn stop(&mut self) -> PluginResult<()> {
self.state = PluginState::Paused;
Ok(())
}
async fn unload(&mut self) -> PluginResult<()> {
self.state = PluginState::Unloaded;
Ok(())
}
async fn execute(&mut self, input: String) -> PluginResult<String> {
self.call_count += 1;
Ok(format!("Processed: {}", input))
}
fn stats(&self) -> HashMap<String, serde_json::Value> {
let mut stats = HashMap::new();
stats.insert("calls_total".to_string(), json!(self.call_count));
stats
}
fn as_any(&self) -> &dyn Any { self }
fn as_any_mut(&mut self) -> &mut dyn Any { self }
fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
}