Agents/Overview

Agents

anybao is an AI agent that lives in an any space. Its conversation loop is a Python program, its memory is a dataset, its tools are programs, and every run is a trace you can replay bit-exact. The runtime that hosts it — anyrt — is a Rust library or process that cages a CPython guest and lets nothing out except through a recorded effect boundary.

What "space-resident" means

any space "bao"  (derived per account, encrypted, synced)
 ├── general chat           the conversation — humans and the agent post here
 │    └── bao/log/v1        agent_turns + agent_chunks (history)
 ├── bao/brain/v1           agent_memory_items (long-term memory)
 ├── bao/config/v1          agent_config  (llm tiers, search providers)
 ├── bao/secrets/v1         agent_secrets (API keys, never guest-readable)
 ├── bao/triggers/v1        agent_triggers (cron/once/event)
 └── bao/runs/v1            agent_runs (one summary per run)

overlay space "agent"       the agent's code: programs/ + skills/ (joined read-only)
overlay space "connectors"  linear, github, gmail, … (programs)

each device                 trace bodies in its any server's local store, never synced

Everything the agent knows or does is ordinary data that you can query, subscribe to, export and delete with the same HTTP surface as the rest of your space. The agent has no server of its own.

How a conversation works

  1. A human posts to the space's general chat. anyrt serve watches the chat over a subscription.
  2. The runtime invokes the guest program toolcaller@v1 with {space, chatId, userText}.
  3. The program composes the system prompt from skills and tool docstrings, renders the boot window (recent turns plus summarised history), runs auto-recall over the memory index, and calls the model.
  4. The model's tool is run_cell(code) (plus bash in a shell-enabled build). Each call runs a Python cell in a persistent kernel; the cell's prints, last value and side effects come back as a digest.
  5. Interim text posts as chat bubbles with agent.done: false; the final reply posts with done: true, and the turn is appended to agent_turns with a traceRef pointing at the run.

Every HTTP call, model call, clock read and random number the loop makes crosses the effect boundary and lands in the trace — so the whole exchange can be replayed offline without the network, and inspected turn by turn with anyrt trace show.

Why it matters. Hosted agent frameworks keep threads, messages, usage and a "playground" on their servers. Here the thread is your chat, the usage counters are fields on the turn record, and the playground is the trace on your own device — end-to-end encrypted where it syncs, and yours to delete.

The one thing that leaves is the inference request: the model runs wherever its provider runs, and a hosted provider sees the prompt and the tool results the loop sends it. Sync encryption covers storage and transport between members, not that request. Search embeddings are a separate, local-capable setting (Embedders).

Two ways to run it

Mode What it is When
Embedded anyrt as a Rust library inside an app (the desktop app bundles it this way) one app, one device, no extra process
Standalone anyrt serve next to an any server, configured by anybao.toml headless machines, browser UI, remote runners

Both modes run the same agent against the same space. Run only one of them per chat on a device — two answer twice. Across devices the runtime elects the responder through the device registry, and a standby device still runs the jobs pinned to it — see Embedding anyrt.

In this section