Bamboo π
π δΈζηθ―·η README.zh-CN.md
Bamboo β the local-first Rust agent runtime that powers Zenith (the execution engine).
What is this
Bamboo is the "brain" of an AI assistant that runs on your own machine. It does far more than chat β it takes notes, grows a searchable long-term memory, uses tools (read/write files, run commands, search the web), and automatically compacts very long conversations so the assistant never "forgets" or grinds to a halt. All of this lives inside one compact, self-hostable program, with your data staying local by default.
If Bodhi is the AI product you see, Bamboo is the engine running underneath it.
Key Capabilities at a Glance
| Capability | What it does |
|---|---|
| π§ Memory system | Session notes, Dream notebook, cross-session durable memory, with auto-dream and background gardener |
| ποΈ Context compression | Hybrid compression with rolling summary + recent-window retention, automatic trimming of oversized tool output, executed against the model's context-window budget |
| π οΈ Built-in tools | 22 built-in tools: files, search, Shell, Web, plan mode, tasks, permission requests, and more |
| π― Skills | Optional/discoverable skills with lightweight selection based on request hints, including built-in docx / pdf / pptx / xlsx / skill-creator |
| π MCP | Model Context Protocol client that hooks into external tool servers |
| β° Workflows & schedules | Declarative workflow loading + a cron-style schedule trigger engine |
| π HTTP / SSE | Actix server, REST API, Server-Sent Events streaming, compatible with OpenAI / Anthropic / Gemini endpoints |
| ποΈ Multi-provider | anthropic (default), openai, gemini, copilot, bodhi routing |
Architecture
Bamboo is a Cargo workspace: a thin root binary (bamboo-agent, which exposes the bamboo command) sits on top of focused crates organized into four tiers β crates/core/ (types + interfaces), crates/infra/ (independent services), crates/engine/ (core logic), and crates/app/ (executables + entry points). The live server is crates/app/bamboo-server (there is no duplicate server tree). bamboo-agent-core depends only on bamboo-domain, keeping the core abstractions clean.
graph TD
CLI["bamboo (root bin)<br/>serve / config / -p headless / actor / broker"] --> SRV[bamboo-server<br/>Actix HTTP + SSE, routes, schedules, workflows]
SRV --> ENG[bamboo-engine<br/>agent runtime, auto-dream, gardener, metrics]
ENG --> CORE[bamboo-agent-core<br/>core abstractions]
CORE --> DOM[bamboo-domain<br/>pure domain types]
ENG --> MEM[bamboo-memory<br/>session notes, durable memory, plan store, budget]
ENG --> CMP[bamboo-compression<br/>token budgeting, summarizer, limits]
ENG --> SKILLS[bamboo-skills<br/>selection, access control, runtime metadata]
ENG --> MCP[bamboo-mcp<br/>MCP client: manager, protocol, transports, tool_index]
ENG --> TOOLS[bamboo-tools<br/>22 built-in tools, registry, guides, permissions]
ENG --> INFRA[bamboo-infrastructure<br/>config, LLM providers, session store]
SRV --> INFRA
TOOLS --> INFRA
MEM --> INFRA
CLI2["bamboo-cli / bamboo-tui<br/>thin clients over HTTP"] -.-> SRV
Workspace members (from Cargo.toml), organized by tier:
crates/core/βbamboo-domain(pure domain types),bamboo-agent-core(core abstractions)crates/infra/βbamboo-config,bamboo-llm,bamboo-storage,bamboo-a2a,bamboo-infrastructure,bamboo-memory,bamboo-metrics,bamboo-notification,bamboo-skills,bamboo-mcp,bamboo-permission,bamboo-compression,bamboo-subagent,bamboo-analytics(dev-only)crates/engine/βbamboo-engine,bamboo-toolscrates/app/βbamboo-server,bamboo-server-tools,bamboo-sdk,bamboo-cli,bamboo-tui,bamboo-client-core,bamboo-broker
β¦plus the root bamboo-agent binary.
Place in the Zenith stack: lotus (the React UI) and bamboo communicate over HTTP; bodhi (the Tauri shell) is just the container that hosts the interface. Bamboo is the execution engine, and bodhi-server (Go) handles accounts/persistence/billing and the LLM proxy.
Signature Deep-Dives
Memory System Β· crates/infra/bamboo-memory
Memory has three layers:
- Session notes β written by the
session_notetool (actions:session_read/session_append/session_replace/session_clear/session_list_topics); these are temporary drafts/facts within the current session. - Dream notebook β a background process "dreams" over a stretch of conversation, distilling it into structured candidate memories and consolidating them into the notebook (
auto_dream.rs). - Durable memory β survives across sessions, with frontmatter (type, status, source, relations, retrieval metadata), scoped as
session/project/global(memory_store/types.rs).
Auto-dream (MemoryConfig.auto_dream_enabled, off by default because it consumes model tokens) performs extraction, consolidation, and Dream generation as the conversation evolves; it supports three modes: Incremental, Refine, Rebuild.
Gardener (bamboo-engine/src/gardener.rs, gardener_enabled off by default) specializes in splitting "multi-topic blob memories." It has cost guardrails: a hard per-run split cap, a slow cadence (daily by default), and it calls no LLM when the deterministic pre-screen finds no candidates β an idle gardener costs nothing. The split "work list" is produced for free by MemoryStore::scan_blob_candidates; only the split "decision" uses the model.
Why it matters: the memory system lets the assistant understand your project better over long-term use, while keeping cost controlled and data local.
Context Compression Β· crates/infra/bamboo-compression
Long conversations don't grow without bound. Bamboo uses a hybrid strategy: a rolling summary + a recent message window.
counterβ counts tokens via tiktoken BPE or heuristic estimation (TiktokenTokenCounter/HeuristicTokenCounter).segmenterβ preserves the atomicity of tool calls when segmenting (it won't split a single tool call apart).limitsβ deliberately ships no per-model table. Real context/output limits come from (1) provider runtime metadata, (2) user overrides inmodel_limits.json; with neither, it falls back to a global default of 200K context / 64K output. This way the table never goes stale as models are updated.summarizer/preparationβ builds the compression plan, generates the summary message, prepares context against the budget (prepare_hybrid_context), and can estimate prompt-cache savings.- Oversized output β oversized output produced by tools is trimmed/managed at
bamboo-tools/output_manager.rs, avoiding stuffing the context all at once.
Why it matters: the assistant can do long, multi-step work without crashing from context overflow or "losing its memory."
Skill System Β· crates/infra/bamboo-skills
Skills are enableable capability bundles. At runtime it resolves the "selected skills" from session metadata (supporting JSON arrays or the legacy comma-separated format), and performs lightweight, request-hint-based relevance selection for unselected skills to inject into context (capped at MAX_UNSELECTED_SKILLS_IN_CONTEXT = 24), avoiding stuffing every skill into the prompt. It also includes access control and runtime metadata.
Built-in skills live in builtin_skills/: docx, pdf, pptx, xlsx, skill-creator.
Tools, Workflows, Schedules, MCP
- Tools (
bamboo-tools, 22 built-in, registered inexecutor.rs::register_builtin_tools):Bash,BashOutput,KillShell,Read,Write,Edit,NotebookEdit,Glob,Grep,GetFileInfo,Workspace,WebFetch,WebSearch,JsRepl,Task,Sleep,EnterPlanMode,ExitPlanMode,RequestPermissions,SessionNote,ConclusionWithOptions, and more. Tools come with usage guides injected at runtime, a permission/policy-aware execution path, and parallel execution support (parallel.rs). - Workflows β declarative loading (
bamboo-server/src/workflow/loader.rs), exposed via/bamboo/workflows. - Schedules β a cron-style trigger engine and store (
bamboo-server/src/schedules/:manager,trigger_engine,session_factory,store). - MCP β Model Context Protocol client (
crates/infra/bamboo-mcp/:manager,protocol,transports,tool_index), managing external tool servers via the/mcp,/serversroutes.
Quick Start & Development
Run the server
# build & run from the workspace
# or install then run
Arguments supported by bamboo serve (all override the config file):
--port, --bind, --data-dir, --static-dir, --workers (plus --parent-pid, a sidecar orphan-guard: the process exits when that PID goes away).
Other subcommands (bamboo --help / bamboo <cmd> --help for the full list):
| Command | What it does |
|---|---|
bamboo serve |
Start the HTTP/SSE server (above). |
bamboo config [--path] [--show-secrets] |
Inspect the resolved configuration. |
bamboo -p "<prompt>" |
One-shot headless agent run (boots the full runtime incl. sub-agents, prints the result, exits). Optional -s <session> to continue, -m provider:model to pin the model, --workspace, --data-dir, --stream-json (NDJSON on stdout), --echo (keyless transport smoke). |
bamboo actor run|serve|list|call |
Drive the sub-agent actor fabric from the terminal (spawn + stream, run as a service, discover, or send a task). |
bamboo broker serve |
Run the standalone sub-agent message broker (WebSocket bus over durable mailboxes). |
bamboo broker-agent serve |
Run a broker-connected agent (local / Docker / remote) that answers Ask/Task for its mailbox. |
bamboo health |
Probe a running server's /health (exit non-zero if unreachable/unhealthy β usable as a readiness check). |
bamboo status |
One-screen overview of a running server: address, health, session counts. |
bamboo sessions |
List sessions on a running server (stop one with bamboo stop <id>). |
bamboo stop <session_id> |
Stop a running session's agent loop. |
The admin commands (health / status / sessions / stop) are thin HTTP clients over a running bamboo serve; point them at a non-default server with --server-url / --port / --data-dir. (bamboo subagent-worker also exists but is an internal worker process spawned by the server β not for interactive use.)
Defaults (verified against code):
- HTTP API:
http://127.0.0.1:9562/api/v1(port defaults to9562, bind defaults to127.0.0.1) - Health:
GET /api/v1/health - Data dir:
BAMBOO_DATA_DIRor${HOME}/.bamboo - Default provider:
anthropic
Call the agent loop
Once the server is running, the simplest way to run the full agent loop β the LLM plans, calls tools, and streams its work β is two HTTP calls: kick off a turn with POST /api/v1/chat, then watch the live events on the SSE feed GET /api/v1/stream.
# 1. Start an agent turn. This runs the agent loop against the LLM and returns immediately.
# Response: { "session_id": "...", "stream_url": "...", "status": "streaming" }
# 2. Watch the agent work in real time (resumable SSE event feed).
# Each event is one step of the loop: assistant text, tool calls, tool results,
# token usage, and completion.
message and model are the only required fields. Useful optionals: session_id (continue a conversation), system_prompt, selected_skill_ids, workspace_path, provider, images. The chat call returns right away and the loop runs in the background; the stream endpoint (SSE, resumable via ?since=<seq> or the Last-Event-ID header) is where the assistant's reasoning, tool calls, and final answer arrive as they happen.
Use it as a Rust SDK (in-process)
No server needed β the same agent loop runs in-process. The bamboo_sdk crate is an ergonomic facade over the engine: you supply a model and an instruction, .with_defaults_for_data_dir wires the eight runtime dependencies (storage, persistence, attachment reader, skills, metrics, config, provider, default tools) from ~/.bamboo, and then agent.run(&mut session, input) drives one turn (draining events internally) while agent.run_stream(session, input) streams AgentEvents back over an mpsc channel. Every call funnels into the engine's single canonical execution path β the facade never forks the loop. The ergonomic types live in bamboo_sdk::agent (Agent, AgentBuilder, ExecuteRequestBuilder, plus re-exported AgentEvent, Session, β¦).
use ;
async
Precondition:
with_defaults_for_data_dirreads~/.bamboo/config.json(the same configbamboo serveuses) and needs the active provider configured with a non-emptyapi_keyβ otherwise provider creation returns an error (here surfaced by.expect). A fresh data dir with noconfig.jsondefaults toanthropicwith no key and will fail;copilotis the only provider that authenticates keyless (cached OAuth). Set the key in the config file, or pass.api_key("sk-β¦")on the builder beforewith_defaults_for_data_dir.
Don't need the event stream?
agent.run(&mut session, input).await?drives the turn to completion and leaves the answer as the last message onsession. For full control over per-request overrides (split fast/background/summarization models, skill selection, provider handles, β¦) build anExecuteRequestwithExecuteRequestBuilder(both re-exported frombamboo_sdk::agent) and callagent.execute(&mut session, req)β the same canonical engine pathrun/run_streamfunnel into.
Add the facade crate as a dependency (path or git):
[]
= { = "https://github.com/bigduu/Bamboo-agent" }
= { = "1", = ["full"] }
= "5"
= "1"
Prefer not to manage these dependencies yourself? Run
bamboo serveand use the HTTP API above β it drives the exact same loop. The full SDK type reference is the rustdoc at docs.rs/bamboo-agent (the published crate re-exports the facade asbamboo_agent::agent);docs/guides/API.mdcovers the HTTP/SSE surface.
Example configuration
${HOME}/.bamboo/config.json:
Config precedence: file < environment variables < CLI arguments. Environment variables include
BAMBOO_DATA_DIR,BAMBOO_PORT,BAMBOO_BIND,BAMBOO_PROVIDER,BAMBOO_WORKERS,BAMBOO_CORS_ALLOW_ORIGINS.
Docker
&&
docker-compose.yml maps 9562:9562 and sets BAMBOO_DATA_DIR=/data, BAMBOO_PORT=9562, BAMBOO_BIND=0.0.0.0.
Selected API routes
REST prefix /api/v1: chat, execute/{session_id}, stream, sessions, skills, tools, tools/execute, models, commands, workflows, metrics/*, mcp, servers, stop/{session_id}, health.
There are also provider-compatible endpoints: /openai/v1, /anthropic/v1, /gemini/v1beta, /v1/{chat/completions,responses,messages}.
Tests & quality
The Rest of the Stack
Zenith is a monorepo, and bamboo is the execution-engine submodule within it.
| Module | Role |
|---|---|
| bodhi | Desktop AI product surface (Tauri shell) |
| lotus | React+Vite UI layer (talks to bamboo over HTTP) |
| bamboo | Local-first Rust agent runtime (this repo) |
| bodhi-server | Go backend: auth, persistence, billing+quota, LLM proxy |
| pavilion | Official website & docs |
| Zenith (root) | Monorepo entry, submodule pointers, release train |
In-module docs:
- API reference:
docs/guides/API.md - Migration:
docs/guides/MIGRATION_GUIDE.md - CONTRIBUTING Β· CHANGELOG Β· SECURITY
License
MIT