Skip to main content

Crate aether_core

Crate aether_core 

Source
Expand description

§Aether Core

Aether Core is a Rust library for building AI agents (LLM + prompt + tools, running in a loop).

By default, agents have no system prompt and no tools — every token in the context window is yours to control. Tools come exclusively from MCP servers, so you can extend agents in any language.

Agents run in dedicated tokio tasks and communicate via async message passing. Hardware permitting, you can run hundreds of agents in a single process.

§Table of Contents

§Installation

Add Aether to your Cargo.toml:

[dependencies]
aether-agent-core = "0.1"

§Examples

§Minimal Agent (No Tools)

use aether_core::core::{AgentMessage, Prompt, UserMessage, agent};
use llm::providers::openrouter::OpenRouterProvider;
use std::io::{self, Write};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Choose your LLM. Alternatively use AnthropicProvider, LlamaCppProvider..etc
    // For this example, OPENROUTER_API_KEY needs to be set in your environment
    let llm = OpenRouterProvider::default("z-ai/glm-4.6")?;

   // 2. Create an Agent
    let (tx, mut rx, _handle) = agent(llm) // <-- Give it an LLM
        .system_prompt(Prompt::text("You are a helpful assistant.")) // <-- Give it a system prompt
        .spawn() // <-- Spawn it into a tokio task
        .await?;

    // 3. Send the agent a message
    tx.send(UserMessage::text("Explain async Rust in one paragraph"))
        .await?;

    // 4. Stream the agent's response back
    loop {
        match rx.recv().await {
            Some(AgentMessage::Text { chunk, is_complete, .. }) => {
                if !is_complete { print!("{chunk}"); io::stdout().flush()?; }
            }
            Some(AgentMessage::Done) => break,
            Some(AgentMessage::Error { message }) => { eprintln!("Error: {message}"); break; }
            _ => {}
        }
    }

    Ok(())
}

§Agent with Tools and AGENTS.md system prompt

Create a mcp.json file in the current working directory:

{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/directory"]
    },
    "playwright": {
      "command": "npx",
      "args": ["-y", "@executeautomation/playwright-mcp-server"]
    }
  }
}

And create an AGENTS.md file with a system prompt:

# BotBot

You are Mr. BotBot, a kickass coding agent equipped with SOTA filesystem and web browsing tools...

And bring Mr. BotBot to life!

use aether_core::core::{AgentMessage, UserMessage, Prompt, agent};
use aether_core::mcp::{mcp, McpSpawnResult};
use llm::providers::openrouter::OpenRouterProvider;
use std::io::{self, Write};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let llm = OpenRouterProvider::default("z-ai/glm-4.6")?;

    // 1. Connect to MCP servers
    let McpSpawnResult {
        tool_definitions: tools,
        instructions: _,
        command_tx: mcp_tx,
        event_rx: _,
        handle: _mcp_handle,
        ..
    } = mcp()
        .from_json_files(&["mcp.json"]) // <-- Load MCP servers from one or more JSON files
        .await?
        .spawn() // <-- Spawn the MCP client into a tokio task (multiple agents can use it)
        .await?;

    // 2. Create Agent
    let (tx, mut rx, _handle) = agent(llm)
        .system_prompt(Prompt::from_globs(vec!["AGENTS.md".into()], ".".into())) // <-- Load system prompt from AGENTS.md
        .tools(mcp_tx, tools) // <-- Give the agent MCP tools
        .spawn()
        .await?;

   // Send your agent a message and stream the results back
    tx.send(UserMessage::text(
        "Read the README.md file and summarize it",
    ))
    .await?;

    loop {
        use AgentMessage::*;
        match rx.recv().await {
            Some(Text { chunk, is_complete, .. }) => {
                if !is_complete {
                    print!("{chunk}");
                    io::stdout().flush().unwrap();
                } else {
                    println!();
                }
            }
            Some(ToolCall { request, .. }) => {
                println!("\nCalling tool: {}", request.name);
            }
            Some(ToolResult { result, .. }) => {
                println!("Tool '{}' completed", result.name);
            }
            Some(ToolError { error, .. }) => {
                eprintln!("Tool '{}' failed: {}", error.name, error.error);
            }
            Some(ToolProgress { .. }) => {
                // Tool progress updates (can be used to show progress bars, etc.)
            }
            Some(Done) => {
                println!("\nAgent finished");
                break;
            }
            Some(Error { message }) => {
                eprintln!("Error: {message}");
                break;
            }
            Some(Cancelled { .. }) => {
                eprintln!("Agent cancelled");
                break;
            }
            _ => {}
            None => break,
        }
    }

    Ok(())
}

§License

MIT

Re-exports§

pub use agent_spec::AgentSpec;
pub use agent_spec::AgentSpecExposure;

Modules§

agent_spec
Agent specification types for authored agent definitions.
context
core
events
Shared types for agent events.
mcp
testing