mecha-core 0.1.15

Provider-agnostic agent harness: loop, tools, MCP client, sessions.
Documentation

mecha-core — an agent harness for local models.

The library knows nothing about any particular CLI, UI, or project. It gives you four things and lets you wire them together:

  • [provider] — talk to a model (Anthropic, or anything OpenAI-shaped)
  • [tool] — things the agent can do, native or [mcp]-backed
  • [agent] — the loop that puts those together
  • [session] / [batch] — persistence and fan-out around the loop
# async fn example() -> anyhow::Result<()> {
use mecha_core::{agent::Agent, agent::Conversation, config::Config};
use mecha_core::sandbox::Sandbox;
use mecha_core::tool::{ModeApprover, Registry, ToolCtx};
use std::sync::Arc;

let cfg = Config::load(&std::env::current_dir()?)?;
let (_, provider_cfg) = cfg.provider(None)?;

// How `shell` is confined. It decides that tool's declared capabilities,
// so it is built before the registry rather than consulted at call time.
let sandbox = Arc::new(Sandbox::new(cfg.sandbox.clone()));

let agent = Agent::new(
    mecha_core::provider::build(provider_cfg)?,
    Registry::new().with_builtins(&cfg.tools, sandbox),
    Arc::new(ModeApprover { mode: cfg.tools.permission_mode }),
    ToolCtx {
        workspace: std::env::current_dir()?,
        shell_timeout: std::time::Duration::from_secs(cfg.tools.shell_timeout_secs),
        security: cfg.security.clone(),
        ..ToolCtx::default()
    },
    cfg.agent.clone(),
    None,
)?;

// A conversation carries its own taint, so keeping it across turns keeps
// the trifecta interlock honest — see `agent::Conversation`.
let mut convo = Conversation::user("What changed in this repo today?");
let outcome = agent.run(&mut convo, None).await?;
println!("{}", outcome.text);
# Ok(())
# }