# Nanocode

The runtime that owns the harnesses, tools, durability store, and subagents, and spawns agents that share them.

`Nanocode::builder()` returns a `NanocodeBuilder`. Each builder method returns the builder, and `build` or `build_async` validates the configuration and returns the runtime. A `Nanocode` value is cheap to clone, and every clone shares one runtime.

```rust title="main.rs"
use nanocode::{Nanocode, OpenAi, Tools};

type Result<T> =
    std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

#[tokio::main]
async fn main() -> Result<()> {
    // 1. Configure the runtime, then build it on the Tokio runtime
    let runtime = Nanocode::builder()
        .openai(OpenAi::default())
        .tools(Tools::builder().without_defaults().build()?)
        .build_async()
        .await?;

    // 2. Spawn an agent on the default harness and run a turn
    let (agent, _events) = runtime.spawn().build().await?;
    println!(
        "{}",
        agent.prompt("Say hello.").await?.await?.final_message()
    );

    // 3. Stop every agent and flush the store
    runtime.shutdown().await?;
    Ok(())
}
```

## Signature

```rust
// The runtime with the built-in Codex and Claude harnesses
pub type Nanocode = nanocode_agent::Runtime<Defaults>;
pub type NanocodeBuilder<B = Unselected> =
    nanocode_agent::RuntimeBuilder<B, Defaults>;

impl Nanocode {
    pub fn builder() -> NanocodeBuilder;
}
```

## Builder Defaults

On native targets, `build` adds a default `OpenAi` and a default `ClaudeClient` harness for each family that the builder does not configure. If no harness is selected, the runtime uses Codex, then Claude.

| Setting    | Default                                                                                                                    |
| ---------- | -------------------------------------------------------------------------------------------------------------------------- |
| Harness    | Codex, or the first configured harness                                                                                     |
| Model      | `Model::Sol` on Codex, `ClaudeModel::Opus55` on Claude                                                                     |
| Thinking   | The default of the model, such as `Thinking::Medium` for `Model::Sol`                                                      |
| Durability | `JsonlStore` at `$NANOCODE_HOME/sessions.jsonl`, or `~/.nanocode/sessions.jsonl` on native targets. `MemoryStore` on WASM. |
| Workspace  | The current directory on native targets                                                                                    |
| Subagents  | Enabled, with no limit                                                                                                     |

## Builder Methods

### builder.openai

```rust
// Installs the Codex harness, replacing an earlier one
pub fn openai(self, harness: impl Into<CodexHarness>) -> Self
```

Installs the Codex harness from an `OpenAi` client or a `CodexHarness`. See [`OpenAi`](/docs/api/rust/OpenAi).

```rust
// Signs in with the ChatGPT login in the nanocode home
let builder = Nanocode::builder().openai(OpenAi::default());
```

### builder.claude

```rust
// Installs the Claude harness, replacing an earlier one
pub fn claude(self, harness: impl Into<ClaudeHarness>) -> Self
```

Installs the Claude harness from a `ClaudeClient` or a `ClaudeHarness`. See [`ClaudeClient`](/docs/api/rust/ClaudeClient).

```rust
// Uses an Anthropic API key
let client = ClaudeClient::with_api_key(
    "https://api.anthropic.com/v1/messages",
    key,
);
let builder = Nanocode::builder().claude(client);
```

### builder.tools

```rust
// One tool catalog for every agent of the runtime
pub fn tools(self, tools: Tools) -> Self
```

Sets the tools that every agent receives. See [`Tools`](/docs/api/rust/Tools).

```rust
// Registers one #[tool] function and no built-in tools
let tools = Tools::builder()
    .without_defaults()
    .tool(checked_sum)
    .build()?;
let builder = Nanocode::builder().tools(tools);
```

### builder.tools_factory

```rust
// Builds a catalog per agent from its handle
pub fn tools_factory<T>(self, factory: T) -> Self
where
    T: Fn(AgentHandle) -> Result<Tools, ToolsBuildError>
        + Send
        + Sync
        + 'static
```

Builds the tools of each agent when the agent starts. The factory receives the `AgentHandle`, which carries the session ID. This method replaces `tools`, and `tools` replaces it.

```rust
// Gives each agent a catalog that reads its own session ID
let builder = Nanocode::builder().tools_factory(|handle| {
    println!("tools for {}", handle.session_id());
    Tools::builder().without_defaults().build()
});
```

### builder.code_mode_host

```rust
// Runs Code Mode cells in a host instead of the embedded engine
pub fn code_mode_host(
    self,
    host: impl CodeModeHost,
) -> Result<Self, ToolsBuildError>
```

Moves Code Mode execution to `host`, such as a remote transport. The catalog drops the default tools, and on native targets the runtime also turns off computer use and runner management.

```rust
// Sends every Code Mode cell over a remote socket transport
let builder =
    Nanocode::builder().code_mode_host(transport.into_host())?;
```

### builder.backend

```rust
// Registers a third-party harness
pub fn backend(
    self,
    backend: impl DurableBackendRegistration + 'static,
) -> Self
```

Registers a backend that implements the `nanocode::backend` contract. Each backend identity can be registered once, and `build` rejects a duplicate.

```rust
// Adds a custom harness next to the built-in ones
let builder = Nanocode::builder().backend(MyBackend::new());
```

### builder.for_backend

```rust
// Selects the default harness by its backend kind
pub fn for_backend<B: BackendKind>(self) -> NanocodeBuilder<B>
```

Selects the harness that `spawn` uses when it does not name one, and unlocks `builder.model` for that harness.

```rust
// Defaults every agent to Codex on Model::Luna
let builder = Nanocode::builder()
    .for_backend::<Codex>()
    .model(Model::Luna);
```

### builder.model

```rust
// Available after for_backend
pub fn model(self, model: B::Model) -> Self
```

Sets the default model of the selected harness. The model type follows the backend kind: `Model` for `Codex` and `ClaudeModel` for `Claude`.

```rust
// Defaults every agent to Claude Sonnet
let builder = Nanocode::builder()
    .for_backend::<Claude>()
    .model(ClaudeModel::Sonnet55);
```

### builder.durability

```rust
// Accepts a SessionStore or any StateStore
pub fn durability(self, store: impl IntoSessionStore) -> Self
```

Sets the store that journals every root agent and its subagents. The runtime registers the checkpoint format of each harness on the store. See [`session_store`](/docs/api/rust/session_store).

```rust
// Journals sessions to a JSONL file
let store = nanocode::session_store(
    JsonlStore::open_async("sessions.jsonl").await?,
)?;
let builder = Nanocode::builder().durability(store);
```

### builder.max_subagents

```rust
// Limits the subagents of the runtime
pub const fn max_subagents(self, limit: usize) -> Self
```

Sets the subagent limit and turns subagents on again after `without_subagents`. The default limit is `usize::MAX`.

```rust
// Allows at most four subagents
let builder = Nanocode::builder().max_subagents(4);
```

### builder.without_subagents

```rust
// Removes subagent orchestration
pub const fn without_subagents(self) -> Self
```

Turns subagents off. `subagents` and `take_subagent_updates` then return `None`.

```rust
// Builds a runtime whose agents cannot spawn subagents
let builder = Nanocode::builder().without_subagents();
```

### builder.without_subagent_continuation

```rust
// Keeps subagents, but not their link back to a live parent
pub const fn without_subagent_continuation(self) -> Self
```

Keeps subagents on, but does not give the subagent registry a way to look up a live parent agent by its session ID.

```rust
// Keeps subagents without parent lookup
let builder = Nanocode::builder().without_subagent_continuation();
```

### builder.thinking

```rust
// The default reasoning effort
pub const fn thinking(self, thinking: Thinking) -> Self
```

Sets the default reasoning effort. `build` rejects a level that the default model does not support.

```rust
// Uses low effort unless an agent overrides it
let builder = Nanocode::builder().thinking(Thinking::Low);
```

### builder.instructions

```rust
// Extra instructions for every agent
pub fn instructions(self, instructions: impl Into<Arc<str>>) -> Self
```

Sets instructions that every agent of the runtime receives.

```rust
// Adds a project rule to every agent
let builder =
    Nanocode::builder().instructions("Answer in British English.");
```

### builder.workspace

```rust
// The directory that tools run in
pub fn workspace(self, workspace: impl Into<PathBuf>) -> Self
```

Sets the workspace directory. On native targets, a relative path resolves against the current directory. WASM builds require an absolute path.

```rust
// Runs tools in a checkout
let builder = Nanocode::builder().workspace("/srv/checkouts/app");
```

### builder.build

```rust
// Builds on the current thread
pub fn build(self) -> Result<Nanocode, NanocodeError>
```

Validates the configuration and returns the runtime. It opens the default store synchronously when no store is set.

```rust
// Builds without an async context
let runtime = Nanocode::builder().openai(OpenAi::default()).build()?;
```

### builder.build_async

```rust
// Builds without blocking the async executor
pub async fn build_async(self) -> Result<Nanocode, NanocodeError>
```

Opens the default store asynchronously, then runs `build` on a separate thread. On native targets it requires an active Tokio runtime.

```rust
// Builds inside #[tokio::main]
let runtime = Nanocode::builder()
    .openai(OpenAi::default())
    .build_async()
    .await?;
```

### builder.runner

> [!NOTE]
> `runner`, `runner_server`, `runner_management`, `cua`, `without_cua`, `tool_environment`, and `tool_provider` exist only on native targets.

```rust
// Dials a hand when the runtime starts
pub fn runner(self, runner: Runner) -> Self
```

Adds a hand that the runtime connects to. See [`hand`](/docs/api/rust/hand).

```rust
// Connects to a listening hand with a shared token
let builder = Nanocode::builder()
    .runner(Runner::connect("ws://127.0.0.1:9000").token(token));
```

### builder.runner_server

```rust
// Accepts hands at an address
pub fn runner_server(self, config: RunnerServerConfig) -> Self
```

Listens for hands that dial the runtime.

```rust
// Accepts hands on a loopback port
let builder = Nanocode::builder().runner_server(
    RunnerServerConfig::listen("127.0.0.1:9000").token(token),
);
```

### builder.runner_management

```rust
// Model-visible runner management
pub fn runner_management(self, enabled: bool) -> Self
```

Turns the runner management tools on or off. They are on by default.

```rust
// Keeps runner management out of the catalog
let builder = Nanocode::builder().runner_management(false);
```

### builder.cua

```rust
// Computer-use tools with a configuration
pub fn cua(self, tools: ComputerTools) -> Self
```

Installs computer-use tools from a `ComputerTools` connection. Native runtimes install the default computer-use tools when neither `cua` nor `without_cua` is called. `without_cua` turns computer use off.

```rust
// Connects the computer-use tools, then installs them
let computer = ComputerTools::connect(config).await?;
let builder = Nanocode::builder().cua(computer);
```

### builder.tool_environment

```rust
// Environment variables for tool processes
pub fn tool_environment<K, V>(
    self,
    variables: impl IntoIterator<Item = (K, V)>,
) -> Self
where
    K: Into<OsString>,
    V: Into<OsString>
```

Sets environment variables for the processes that tools start.

```rust
// Gives shell tools a fixed locale
let builder =
    Nanocode::builder().tool_environment([("LANG", "C.UTF-8")]);
```

### builder.tool_provider

```rust
// Adds tools that a provider discovers at runtime
pub fn tool_provider(
    self,
    provider: impl DynamicToolProvider + 'static,
) -> Self
```

Adds a dynamic tool provider, such as an MCP client, to every agent.

```rust
// Adds a provider next to the static catalog
let builder = Nanocode::builder().tool_provider(provider);
```

## Methods

### runtime.spawn

```rust
// Starts a SpawnBuilder for a new root agent
pub fn spawn(&self) -> SpawnBuilder<'_>
```

Returns a [`SpawnBuilder`](/docs/api/rust/SpawnBuilder). Its `build` returns the agent and its event stream.

```rust
// Spawns an agent with the runtime defaults
let (agent, mut events) = runtime.spawn().build().await?;
```

### runtime.open_session

```rust
// Reopens a session from the runtime's store
pub fn open_session<'a>(&'a self, session_id: &'a str)
    -> HostFuture<'a, Result<(Agent, AgentEvents), NanocodeError>>
```

Reopens a stored session and resumes its pending turns. If the session is already live in this runtime, it returns the live agent with a new event stream. It fails when durability is off.

```rust
// Continues a session by its ID
let (agent, events) = runtime.open_session(&session_id).await?;
```

### runtime.open

```rust
// Reopens a session from an explicit store
pub fn open<'a>(&'a self, store: &'a SessionStore, session_id: &'a str)
    -> HostFuture<'a, Result<(Agent, AgentEvents), NanocodeError>>
```

Works like `open_session`, but takes the store. The store must be the store of the runtime.

```rust
// Uses the same store value that was passed to durability
let (agent, events) = runtime.open(&store, &session_id).await?;
```

### runtime.resume

```rust
// Rebuilds an agent from a portable checkpoint
pub fn resume(&self, checkpoint: SessionCheckpoint)
    -> HostFuture<'_, Result<(Agent, AgentEvents), NanocodeError>>
```

Validates the checkpoint and builds an agent with its model and thinking. See [`SessionCheckpoint`](/docs/api/rust/types#sessioncheckpoint).

```rust
// Resumes from a checkpoint saved as JSON
let checkpoint = SessionCheckpoint::from_json(&saved)?;
let (agent, events) = runtime.resume(checkpoint).await?;
```

### runtime.switch

```rust
// Moves a conversation to another model or harness
pub fn switch<'a>(
    &'a self, agent: &'a Agent,
    model: ModelSelection,
    thinking: Option<Thinking>,
)
    -> HostFuture<'a, Result<(Agent, AgentEvents), NanocodeError>>
```

Returns a new agent that continues the conversation of `agent` on `model`. If the model is the agent's current model, `switch` forks the session with the new thinking level. Otherwise it starts a new session seeded with the transcript. `thinking` defaults to the model's default.

```rust
// Continues the conversation on Claude
let model = ModelSelection::Claude(ClaudeModel::Sonnet55);
let (switched, events) = runtime.switch(&agent, model, None).await?;
```

### runtime.shutdown

```rust
// Stops hosts and agents, then flushes the store
pub fn shutdown(&self) -> HostFuture<'_, Result<(), NanocodeError>>
```

Shuts down the host services and every agent the runtime owns, then flushes the store. It returns the first error after all three steps run.

```rust
// Shuts down before the process exits
runtime.shutdown().await?;
```

### runtime.subagents

```rust
// The subagent control, if subagents are on
pub fn subagents(&self) -> Option<&SubagentControl>
```

Returns the control for the runtime's subagents, or `None` after `without_subagents`.

```rust
// Checks whether this runtime orchestrates subagents
let enabled = runtime.subagents().is_some();
```

### runtime.take_subagent_updates

```rust
// Takes the subagent update receiver once
pub fn take_subagent_updates(&self) -> Option<SubagentUpdates>
```

Returns the receiver of subagent updates. The first call takes it, and later calls return `None`.

```rust
// Prints each subagent as it starts
let mut updates = runtime
    .take_subagent_updates()
    .ok_or("updates already taken")?;
tokio::spawn(async move {
    while let Some(scoped) = updates.recv().await {
        if let AgentUpdate::Added(agent) = scoped.update {
            eprintln!("+ {} {}", agent.role, agent.task);
        }
    }
});
```

### runtime.harness

```rust
// The default harness family
pub fn harness(&self) -> HarnessFamily
```

Returns the family of the default model.

```rust
// Prints "codex" for a runtime with the defaults
println!("{}", runtime.harness());
```

### runtime.model

```rust
// The default model
pub fn model(&self) -> ModelSelection
```

Returns the model that `spawn` uses when the builder does not select one.

```rust
// Prints the model identifier, such as gpt-6.1-sol
println!("{}", runtime.model().as_str());
```

### runtime.thinking

```rust
// The default reasoning effort
pub fn thinking(&self) -> Thinking
```

Returns the reasoning effort that `spawn` uses by default.

```rust
// Prints "low" after builder.thinking(Thinking::Low)
println!("{}", runtime.thinking());
```

### runtime.is_configured

```rust
// Whether a harness family can spawn agents
pub fn is_configured(&self, family: HarnessFamily) -> bool
```

Returns `true` when the runtime has a harness for `family`.

```rust
// Checks for Claude before a switch
if runtime.is_configured(HarnessFamily::Claude) {
    println!("Claude is available");
}
```

## Errors

### NanocodeError

`build`, `build_async`, and the open methods return [`NanocodeError`](/docs/api/rust/types#nanocodeerror). Configuration errors use `NanocodeError::InvalidRequest`, for example a duplicate backend, an unsupported thinking level, or `open_session` without durability. `build_async` returns `NanocodeError::TokioRuntimeUnavailable` outside Tokio.

```rust
// Rejects a thinking level that Model::Sol does not support
match Nanocode::builder()
    .for_backend::<Codex>()
    .thinking(Thinking::None)
    .build()
{
    Err(NanocodeError::InvalidRequest(message)) => {
        eprintln!("{message}")
    }
    other => drop(other),
}
```
