Skip to main content

Crate mobius

Crate mobius 

Source
Expand description

A small, modular Rust framework for one linear agent session.

Applications compose an agent::Agent from explicit model, sandbox, checkpoint, and middleware adapters. Frontends remain separate: they submit protocol::Op values and render the frontend-neutral protocol::Event stream.

§Embedded composition

The caller owns every runtime dependency. Include exactly one message-handling middleware, give new sessions a non-empty protocol::SessionContext::owner_id, and keep draining events while commands are active.

use std::path::Path;
use std::sync::Arc;

use mobius::Result;
use mobius::agent::{Agent, AgentConfig, create_agent};
use mobius::backend::checkpoint::{CheckpointStore, sqlite::SqliteCheckpoint};
use mobius::backend::model::{Model, ModelRouter, openai::OpenAi};
use mobius::backend::sandbox::{ApprovalPolicy, Sandbox, local::LocalSandbox};
use mobius::middleware::{Middleware, MiddlewareStack};
use mobius::middleware::{messages::Messages, tools::Tools};
use mobius::protocol::SessionContext;

async fn build_agent(
    workspace: &Path,
    state_dir: &Path,
    api_key: String,
    model_id: &str,
) -> Result<Agent> {
    let model: Arc<dyn Model> = Arc::new(OpenAi::new(
        api_key,
        "https://api.openai.com/v1",
        model_id,
    )?);
    let files = mobius::backend::session_files::SessionFileStore::new(state_dir, None);
    let models = Arc::new(ModelRouter::new("default", model).session_files(files.clone()));
    let sandbox = Arc::new(Sandbox::new(
        Arc::new(LocalSandbox::new(workspace)?),
        ApprovalPolicy::Ask,
    ));
    let checkpoints: Arc<dyn CheckpointStore> =
        Arc::new(SqliteCheckpoint::new(state_dir.join("mobius.sqlite3"))?);
    let middleware: Vec<Arc<dyn Middleware>> = vec![
        Arc::new(Messages::default()),
        Arc::new(Tools::coding(files)),
    ];

    create_agent(
        AgentConfig::new(
            models,
            sandbox,
            checkpoints,
            MiddlewareStack::new(middleware)?,
            "You are a concise coding agent.",
        )
        .session_context(SessionContext {
            owner_id: "embedded".into(),
            ..SessionContext::default()
        }),
    )
    .await
}

A custom provider implements backend::model::Model and must return normalized output. backend::model::ModelEventSink is synchronous and fallible; propagate its error rather than silently losing a streamed event. This example also uses serde_json.

use serde_json::json;

use mobius::{BoxFuture, Result};
use mobius::backend::model::{Model, ModelEventSink, ModelOutput, ModelRequest};
use mobius::protocol::{ModelEvent, ModelInfo, TokenUsage};

struct EchoModel;

impl Model for EchoModel {
    fn info(&self) -> ModelInfo {
        ModelInfo {
            model: "echo".into(),
            reasoning_effort: None,
        }
    }

    fn respond<'a>(
        &'a self,
        _request: ModelRequest<'a>,
        events: ModelEventSink,
    ) -> BoxFuture<'a, Result<ModelOutput>> {
        Box::pin(async move {
            events(ModelEvent::TextDelta("done".into())).await?;
            ModelOutput::from_output(
                vec![json!({
                    "type": "message",
                    "role": "assistant",
                    "content": [{"type": "output_text", "text": "done"}]
                })],
                true,
                TokenUsage::default(),
            )
        })
    }
}

A capability implements middleware::Middleware and joins the declaration-ordered middleware::MiddlewareStack. Static prompt sections are composed once at agent creation.

use std::sync::Arc;

use mobius::Result;
use mobius::middleware::{Middleware, MiddlewareStack, PromptSection, RuntimeContext};
use mobius::middleware::messages::Messages;

struct Policy;

impl Middleware for Policy {
    fn name(&self) -> &'static str {
        "policy"
    }

    fn prompt_section(&self, _runtime: &RuntimeContext) -> Result<Option<PromptSection>> {
        Ok(Some(PromptSection::new("Follow the repository policy.")))
    }
}

fn middleware_stack() -> Result<MiddlewareStack> {
    MiddlewareStack::new(vec![Arc::new(Messages::default()), Arc::new(Policy)])
}

§Runtime contracts

  • Error and ProviderError preserve actionable failure classes and retry metadata; callers should not infer policy by matching display strings.
  • agent::create_agent validates composition and unwinds started middleware on startup failure. agent::AgentSender documents bounded submission and sender-drop shutdown; drain agent::AgentEvents::recv until the stream closes.
  • backend::checkpoint::CheckpointStore::save_with_events is the atomic logical boundary for checkpoint, transcript, execution, and event state. Backend contracts specify durability and which optional history operations are supported.
  • backend::sandbox::Sandbox owns approval and background-process cleanup around an injected backend::sandbox::SandboxBackend. Backends must keep cancellation cleanup for resources they launch; the default authorized path fails closed.
  • In mobius-gateway, signal shutdown through GatewayServer::serve_until and await it; dropping the serving future does not perform graceful shutdown.

Modules§

agent
Agent handles and the single linear command dispatch loop.
backend
Runtime adapters used by the agent loop.
config
Typed loading of owner-local configuration embedded in the binary.
identifier
Shared ASCII identifier grammar; domain owners retain their prefix and reserved-name rules.
middleware
Ordered middleware and capability registration.
owner_only
Unix owner-only permission values for native path or descriptor operations.
protocol
The small event protocol shared by agent frontends.
sync
Explicit recovery of poisoned standard-library mutexes.

Macros§

embedded_config
Declares defaulted settings backed by a complete owner-local TOML document.

Structs§

ProviderError
A model-provider failure with retry metadata preserved for callers.

Enums§

Error
Errors returned by möbius modules.

Type Aliases§

BoxFuture
A boxed asynchronous operation used by runtime-pluggable interfaces.
Result
Result type shared by möbius modules.