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
- A human posts to the space's general chat.
anyrt servewatches the chat over a subscription. - The runtime invokes the guest program
toolcaller@v1with{space, chatId, userText}. - 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.
- The model's tool is
run_cell(code)(plusbashin 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. - Interim text posts as chat bubbles with
agent.done: false; the final reply posts withdone: true, and the turn is appended toagent_turnswith atraceRefpointing 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.