API Reference

This is the embedding API surface. The core lives in the orchard facade crate, and the C-FFI, PyO3, and WASM bindings are thin adapters over it. The Rust types below are illustrative; the contract is the capability set. For the language itself, see the Embedding Orchard guide.

Load, check, compile

Every load, check, and compile entry point returns structured diagnostics and never panics. You can run an agent directly from source, analyze it without running, or compile it to a stable JSON IR and run that.

use orchard::{Agent, Diagnostic};

// Parse + check; structured diagnostics, never a panic.
let agent: Agent = Agent::load(source, "ivy.orch")?;     // Err = Vec<Diagnostic>
let diags: Vec<Diagnostic> = Agent::check(source, "ivy.orch");   // analysis only
let ir_json: String = Agent::compile(source, "ivy.orch")?;       // stable JSON IR
let agent = Agent::from_ir(&ir_json)?;                           // run precompiled IR
Agent::load(source, name)
parses, checks, and lowers the source. Returns an Agent on success or a Vec of Diagnostic on failure.
Agent::check(source, name)
runs analysis only and returns a Vec of Diagnostic without building an agent.
Agent::compile(source, name)
lowers the source to the stable, diffable JSON IR string.
Agent::from_ir(ir)
builds an Agent from precompiled IR and runs it.
Diagnostic
a structured record of severity, message, span, and hint. It never panics.
Diagnostic::render(source)
reproduces the caret format byte-for-byte against the source.

Build a session

A session is built with Runtime::builder(agent). Every boundary has a pure-Rust default, so a session builds with zero config: the default provider resolves from the manifest, the default store is redb or in-memory, and the default HTTP client is the egress-guarded rustls client. Hosts override any subset.

use orchard::{Runtime, Provider, Store, HttpClient, Embedder, Event};
use std::sync::Arc;

let session = Runtime::builder(agent)
    .provider(Arc::new(my_provider))        // dyn Provider  (route model calls)
    .store(Arc::new(my_store))              // dyn Store     (share host DB / in-mem)
    .http_client(Arc::new(my_http))         // dyn HttpClient (egress-guarded)
    .embedder(Arc::new(my_embedder))        // dyn Embedder  (optional)
    .register_tool(native_tool)             // a host Rust tool the loop can call
    .policy_overrides(p)                    // budgets, allowed_domains, secrets
    .on_event(|e: &Event| { /* steps, tool calls, usage, spend, traces */ })
    .build()?;
.provider(Arc<dyn Provider>)
routes model calls through a host gateway or a fake.
.store(Arc<dyn Store>)
shares a host database, or uses the in-memory default.
.http_client(Arc<dyn HttpClient>)
replaces the egress-guarded default client.
.embedder(Arc<dyn Embedder>)
supplies embeddings for semantic memory. Optional.
.register_tool(native_tool)
adds a native Rust host tool the loop can call.
.policy_overrides(p)
tightens budgets, allowed_domains, and secrets from the host.
.on_event(handler)
receives the event stream for steps, tool calls, usage, spend, and traces.
.build()
finalizes the session.

Drive turns (async)

All driving methods are async. The same session is reused across turns, so memory persists between them.

let reply: String  = session.message("Summarize my inbox").await?;   // on message
let out:   String  = session.task("Draft the standup").await?;       // one-shot
let val:   Value   = session.skill("triage", args).await?;           // named skill
session.serve().await?;                                              // schedule/file
session.message(text)
drives the agent on an incoming message.
session.task(text)
runs a one-shot task and returns its output.
session.skill(name, args)
invokes a named skill with arguments and returns its value.
session.serve()
runs the agent's schedule and file handlers.

Native host tools

A host registers an async Rust function the agent's delegateloop and behavior code can call. This is the v3 analogue of v2's pure-computation tools, generalized.

let native_tool = NativeTool::builder("lookup_user")
    .description("Look up a user by id in the host database.")
    .param("id", JsonType::Integer, /*required*/ true)
    .returns(JsonType::Object)
    .handler(|args, ctx| async move {
        let id = args.get_i64("id")?;
        Ok(ctx.host_db().fetch_user(id).await?.into())   // -> Value / JSON
    })
    .build();
NativeTool::builder(name)
starts a native tool definition.
.description(text)
the description advertised to the model.
.param(name, type, required)
declares a JSON-schema parameter.
.returns(type)
declares the JSON type of the result.
.handler(closure)
the async body. Errors returned here become a structured tool error to the model and never crash the loop.
.build()
finalizes the tool.
#[orchard::tool]
an attribute macro that generates the schema and binding from a typed Rust function signature, where practical.

Registered tools are advertised to the model with their JSON-schema params and description, and dispatched exactly like built-in pack tools, with the same validation, redaction, and sentinel-wrapping rules. Mark a tool external: true to sentinel-wrap its output.

Custom providers and stores

A host can route all model calls through its own gateway and share its own database, or use the in-memory store and the mock provider for offline tests.

Provider::chat(request)
takes a request of system, messages, tools, temperature, max_tokens, and an optional schema, and returns a ChatResponse.
Provider::supports_schema
reports whether the provider can constrain output to a schema.
Store
mirrors the logical operations for conversation, facts, state, semantic, and trace. A host shares its own database, or uses the in-memory store (for example IndexedDB-backed on WASM).

Observability

The on_event handler receives a stream of events. This is what host UIs render. Every payload is redacted.

turn start / end
the boundaries of a turn.
model step
a model call, with token usage and spend.
tool call
name, args, result, duration, and success or breaker state.
emit output
intermediate output emitted by the agent.
gen / delegate span boundaries
the start and end of generation and delegate spans.
policy violations
events raised when the agent hits a policy limit.
traces
trace records for the run.

Policy and secrets from the host

The host supplies budgets (spend, steps, and tool-call caps), allowed_domains, the allow_shell and allow_mcp gates, the i_understand_injection_riskflag, and secret values to taint-track. These compose with the agent's own policy block by min, which is tighten-only: the host can only tighten, never loosen, the agent's declared policy.

Binding parity

Each binding exposes the same capabilities as a thin adapter: load, check, and compile, build a session, drive turns, inject a provider, store, or tool, observe events, and set policy. Each ships with a runnable example that runs an agent offline through the mock provider.

C FFI
a C ABI generated with cbindgen.
Python
a pip-installable PyO3 module.
WebAssembly
a wasm-bindgen build for the browser and Node.