pub trait Agent: Send + Sync {
Show 15 methods
// Required methods
fn name(&self) -> &str;
fn system_prompt(&self) -> Result<String>;
fn available_tools(&self) -> Result<Vec<ToolSpec>>;
// Provided methods
fn provider(&self) -> Option<LlmProvider> { ... }
fn apply_config_overrides(&self, _cfg: &mut AppConfig) { ... }
fn required_completion_tools(&self) -> Option<&Vec<String>> { ... }
fn max_continuations(&self) -> usize { ... }
fn continuation_message(&self) -> Option<&str> { ... }
fn execute_tool(&self, name: &str, _args: Value) -> Result<Value> { ... }
fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn run_streaming<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn run_with_consumers<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumers: Vec<Box<dyn StreamConsumer>>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn initial_messages(&self, user_prompt: &str) -> Result<Vec<ChatMessage>> { ... }
fn continue_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn continue_session_streaming<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
}Expand description
Core trait for AI agents.
An agent defines:
- A system prompt that establishes behavior and capabilities
- A set of available tools that the LLM can invoke
- A runtime that orchestrates the conversation loop
§Examples
use appam::agent::{Agent, toml_agent::TomlAgent};
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let agent = TomlAgent::from_file("agents/assistant.toml")?;
agent.run("Hello, how can you help me?").await?;
Ok(())
}Required Methods§
Sourcefn system_prompt(&self) -> Result<String>
fn system_prompt(&self) -> Result<String>
Return the full system prompt for this agent.
The system prompt defines the agent’s personality, capabilities, instructions, and constraints. It is sent as the first message in every conversation.
§Errors
Returns an error if the prompt cannot be loaded (e.g., file not found).
Sourcefn available_tools(&self) -> Result<Vec<ToolSpec>>
fn available_tools(&self) -> Result<Vec<ToolSpec>>
Return the set of tool specifications available to this agent.
Tools are exposed to the LLM via their JSON schemas. The LLM can decide to invoke tools based on user queries and the system prompt.
§Errors
Returns an error if tool specifications cannot be loaded.
Provided Methods§
Sourcefn provider(&self) -> Option<LlmProvider>
fn provider(&self) -> Option<LlmProvider>
Return the provider override for this agent.
If Some(provider), this agent will use the specified provider regardless
of the global configuration. If None, the global provider config is used.
§Examples
fn provider(&self) -> Option<LlmProvider> {
Some(LlmProvider::Anthropic) // Force Anthropic for this agent
}Sourcefn apply_config_overrides(&self, _cfg: &mut AppConfig)
fn apply_config_overrides(&self, _cfg: &mut AppConfig)
Apply agent-specific configuration overrides to global config.
Allows agents to override global settings (provider, model, Anthropic features, etc.) Default implementation does nothing.
Sourcefn required_completion_tools(&self) -> Option<&Vec<String>>
fn required_completion_tools(&self) -> Option<&Vec<String>>
Return the list of tools required for session completion.
If Some, the runtime will automatically inject a continuation message
when the session ends without calling any of these tools.
Default implementation returns None (no continuation).
Sourcefn max_continuations(&self) -> usize
fn max_continuations(&self) -> usize
Return the maximum number of continuation attempts.
Limits how many times the runtime will inject continuation messages before giving up. Default is 2.
Sourcefn continuation_message(&self) -> Option<&str>
fn continuation_message(&self) -> Option<&str>
Return the custom continuation message, if any.
If Some, this message will be injected when the session ends without
calling required tools. If None, a default message is used.
Default implementation returns None.
Sourcefn execute_tool(&self, name: &str, _args: Value) -> Result<Value>
fn execute_tool(&self, name: &str, _args: Value) -> Result<Value>
Resolve a tool by name and execute it.
Default implementation returns an error. Agents should override this to provide tool resolution logic.
Sourcefn run<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run the agent with a user prompt.
Orchestrates the full conversation loop:
- Builds initial messages (system + user)
- Streams LLM response with tool calling
- Executes requested tools
- Continues until LLM stops requesting tools
- Returns session metadata
Output is streamed to console with default formatting.
The default implementation is provided by runtime::default_run.
Agents can override this for custom orchestration.
§Errors
Returns an error if the LLM request fails, tool execution fails, or session logging fails.
Sourcefn run_streaming<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn run_streaming<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run the agent with a custom stream consumer.
Like run(), but streams events to the provided consumer instead of
the console. Use this for web streaming, logging, metrics, or custom
output handling.
§Examples
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let consumer = ChannelConsumer::new(tx);
agent.run_streaming("Hello!", Box::new(consumer)).await?;Sourcefn run_with_consumers<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumers: Vec<Box<dyn StreamConsumer>>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn run_with_consumers<'life0, 'life1, 'async_trait>(
&'life0 self,
user_prompt: &'life1 str,
consumers: Vec<Box<dyn StreamConsumer>>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run the agent with multiple stream consumers.
Events are broadcast to all consumers. If any consumer returns an error, execution stops and the error is returned.
§Examples
agent.run_with_consumers("Hello!", vec![
Box::new(ConsoleConsumer::new()),
Box::new(ChannelConsumer::new(tx)),
]).await?;Sourcefn initial_messages(&self, user_prompt: &str) -> Result<Vec<ChatMessage>>
fn initial_messages(&self, user_prompt: &str) -> Result<Vec<ChatMessage>>
Build the initial message list for a conversation.
By default, creates a system message and a user message. Override for custom message initialization (e.g., few-shot examples, context).
Sourcefn continue_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn continue_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Continue an existing session with a new user prompt.
Loads the session from history and continues the conversation, preserving all previous messages and context. Streams output to console with default formatting.
§Requirements
- Session history must be enabled in configuration
- The session ID must exist in the database
§Examples
// First conversation
let session = agent.run("Hello!").await?;
// Continue later
agent.continue_session(&session.session_id, "How are you?").await?;§Errors
Returns an error if:
- Session history is not enabled
- Session ID does not exist
- LLM request fails
- Tool execution fails
Sourcefn continue_session_streaming<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn continue_session_streaming<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
user_prompt: &'life2 str,
consumer: Box<dyn StreamConsumer>,
) -> Pin<Box<dyn Future<Output = Result<Session>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Continue an existing session with custom streaming.
Like continue_session(), but streams events to the provided consumer
instead of the console.
§Examples
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let consumer = ChannelConsumer::new(tx);
agent.continue_session_streaming("session-123", "Continue...", Box::new(consumer)).await?;§Errors
Returns an error if:
- Session history is not enabled
- Session ID does not exist
- LLM request fails
- Tool execution fails
- Consumer returns an error