Documentation Index Fetch the complete documentation index at: https://mintlify.com/dallay/corvus/llms.txt
Use this file to discover all available pages before exploring further.
Extension Overview
Corvus is designed for extreme extensibility. Every core subsystem is a trait — you can swap implementations with zero changes to the agent runtime.
Extension Points
From README.md:
Subsystem Trait What You Can Build AI Models ProviderCustom LLM backends, local models, API wrappers Channels ChannelMessaging platforms, custom protocols Tools ToolNew capabilities, integrations, hardware drivers Memory MemoryStorage backends, vector DBs, knowledge graphs Runtime RuntimeAdapterExecution environments (WASM, edge, embedded) Observability ObserverMetrics, tracing, monitoring
Architecture
All extensions follow the same pattern:
Implement the Trait
Create a struct that implements the trait (e.g., Provider, Tool)
Register in Factory
Add your implementation to the factory module (e.g., src/providers/mod.rs)
Configure
Add config options to config.toml
Use
Agent automatically discovers and uses your extension
Quick Examples
Custom Provider (~30 lines)
use corvus :: providers :: traits :: Provider ;
use async_trait :: async_trait;
pub struct MyProvider {
api_key : String ,
client : reqwest :: Client ,
}
#[async_trait]
impl Provider for MyProvider {
async fn chat_with_system (
& self ,
system : Option < & str >,
message : & str ,
model : & str ,
temperature : f64 ,
) -> anyhow :: Result < String > {
// Your API call here
Ok ( "response" . into ())
}
}
use corvus :: tools :: traits :: { Tool , ToolResult };
use async_trait :: async_trait;
pub struct MyTool ;
#[async_trait]
impl Tool for MyTool {
fn name ( & self ) -> & str { "my_tool" }
fn description ( & self ) -> & str {
"Does something useful"
}
fn parameters_schema ( & self ) -> serde_json :: Value {
serde_json :: json! ({
"type" : "object" ,
"properties" : {
"input" : { "type" : "string" }
},
"required" : [ "input" ]
})
}
async fn execute ( & self , args : serde_json :: Value )
-> anyhow :: Result < ToolResult >
{
let input = args [ "input" ] . as_str () . unwrap ();
Ok ( ToolResult {
success : true ,
output : format! ( "Processed: {}" , input ),
error : None ,
})
}
}
Custom Channel (~100 lines)
use corvus :: channels :: traits :: { Channel , ChannelMessage , SendMessage };
use async_trait :: async_trait;
pub struct MyChannel {
api_url : String ,
client : reqwest :: Client ,
}
#[async_trait]
impl Channel for MyChannel {
fn name ( & self ) -> & str { "my_channel" }
async fn send ( & self , message : & SendMessage ) -> anyhow :: Result <()> {
// Send message via API
Ok (())
}
async fn listen ( & self , tx : tokio :: sync :: mpsc :: Sender < ChannelMessage >)
-> anyhow :: Result <()>
{
// Poll for incoming messages, send to tx
Ok (())
}
}
Extension Guidelines
1. Security First
Always validate inputs before executing. Don’t trust LLM-provided parameters.
Validate and sanitize all inputs
Use parameterized queries (SQL, etc.)
Never log secrets or API keys
Implement rate limiting where applicable
2. Error Handling
Return errors via Result or structured error types. Never panic in production code.
// Good
let value = args [ "param" ]
. as_str ()
. ok_or_else ( || anyhow :: anyhow! ( "Missing 'param'" )) ? ;
// Bad
let value = args [ "param" ] . as_str () . unwrap (); // can panic
3. Async Operations
Use async/await for I/O operations. Never block the agent loop.
#[async_trait]
impl Tool for HttpTool {
async fn execute ( & self , args : Value ) -> Result < ToolResult > {
let resp = reqwest :: get ( url ) . await ? ; // non-blocking
Ok ( ToolResult :: success ( resp . text () . await ? ))
}
}
4. Testing
Write tests for every extension. Use #[tokio::test] for async tests.
#[tokio :: test]
async fn test_my_tool () {
let tool = MyTool :: new ();
let result = tool . execute ( json! ({ "input" : "test" })) . await . unwrap ();
assert! ( result . success);
}
Example Extensions
Corvus ships with working examples:
Custom Provider Ollama local LLM integration
Custom Channel Telegram bot integration
Custom Memory In-memory backend
Development Workflow
Clone the repository
git clone https://github.com/dallay/corvus.git
cd corvus/clients/agent-runtime
Create your extension
# Providers
touch src/providers/my_provider.rs
# Tools
touch src/tools/my_tool.rs
# Channels
touch src/channels/my_channel.rs
Register in module
// src/providers/mod.rs
pub mod my_provider ;
pub fn create_provider ( name : & str , config : & Config )
-> Result < Box < dyn Provider >>
{
match name {
"my_provider" => Ok ( Box :: new ( my_provider :: MyProvider :: new ( config ))),
// ...
}
}
Test
Use
# ~/.corvus/config.toml
default_provider = "my_provider"
Contributing extensions:
Follow Contributing Guidelines
Add tests and documentation
Submit a pull request
Add to the Extensions Registry
Next Steps
Custom Provider Build a custom LLM provider
Custom Channel Build a custom messaging channel
Custom Tool Build a custom tool
Custom Memory Build a custom memory backend