Aex Brain
Customize and operate

Embed the runtime

Run sessions inside a Rust service you already own.

Use the server when you want a process to talk to. Use the crate when another Rust service already owns startup, configuration, and deployment, and you want sessions inside it.

Each Session represents one conversation. Your service can manage multiple sessions sharing one runtime. This Rust excerpt assumes you have configured the session directory, telemetry and the loop, model and tool executors described below:

use std::sync::Arc;

let limits = brain::Limits::default();
let writer = brain::Writer::spawn_with(&limits);
let feed = Arc::new(brain::Feed::with_limits(telemetry.clone(), &limits));

let runtime = Arc::new(brain::SessionRuntime {
    environment_control: None,
    tool_executions: Arc::default(),
    limits: limits.clone(),
    loop_executor,
    model_executor,
    tool_executor,
    live: feed.clone(),
    telemetry,
});

let store = brain::LocalSessionStore::create(
    &sessions_dir.join(session_id.as_str()),
    session_id,
    &serde_json::to_value(&config)?,
    writer.clone(),
    feed.clone(),
)?;
let creating = brain::Session::begin(store.clone(), runtime.clone(), &config, &opening_transcript)?;
let session = creating.complete(config)?;

session
    .message(brain_protocol::MessageRequest {
        input: "Explain the current changes.".into(),
    })
    .await?;

Open only the session needed, call interrupt_unfinished_turn, then Session::open when an explicit activation is required. LocalSessionStore::open alone permits transcript and Event reads without an actor. Call checkpoint() at a quiescent boundary before dropping execution to accelerate the next open; this projection is disposable. Keep one live store/sequencer per session and serialize mutations for that session. The stock server provides that coordination.

Hold a filesystem lock on the local data directory for the process lifetime before opening mutable stores. brain_server::data_layout::lock provides the stock server's lock when embedding that composition. One local writer is supported; cross-server ownership belongs to the host platform.

You supply the ports

Supply loop_executor, model_executor, and tool_executor implementations for your deployment. Set environment_control when your host supports resource operations; None leaves them unavailable. The loop executor receives the Agentloop, the Environment entry it is placed in, and the session's TurnServices, and runs the loop against them; the server's executor resolves the entry to its Environment adapter, and yours could run a trusted loop in-process. The model executor receives the session id and resolves the credential it sealed for it; the tool executor receives the Tool and its Environment entry. A custom SessionStore can construct asynchronous append completions with CommitHandle::from_completion; returning success must mean the canonical records committed.

What the runtime keeps

Synchronous journal commits still land before effects, and recovery still rebuilds every projection from the same canonical journal. Embedding does not make admission more permissive: Session::begin and complete hold configuration to the same contract as the server.

What stays yours

Which sessions exist, which are running, what to do with them after a restart, and when to forget them. Where environments live and how they are found. Credentials, and how HTTP retries are answered. Everything about product policy. The runtime has opinions about correctness, not about your architecture.

Telemetry delivery

The telemetry channel is bounded and never holds up a turn. Its worker drains queued records into ordered batches and retries a rejected batch for up to 30 seconds. A sink may therefore receive a batch more than once and must make duplicates harmless. Exhausted deliveries are counted and reported through telemetry_delivery_dropped records when the queue still has room.

Telemetry remains best effort. For resumable event forwarding, consume the session event endpoint, save its sequence cursor after the destination acknowledges a batch, and reconnect from that cursor. The session's canonical journal, rather than the telemetry queue, is the durable record.

On this page