The self-hosted AI agent platform — with a real browser, a real sandbox.
English · 简体中文 · 🚀 Install · ✨ What you get · 👋 First run · 🎛️ Day-2 control · 🏗️ Architecture · 🗺️ Roadmap
⭐ Tianshu (天枢) — the brightest star of the Big Dipper, the celestial pivot.
| What | Why |
|---|---|
| Node 22+ | Runtime. Use a Node manager (nvm / volta / asdf); avoid system Node with sudo. |
| Docker (recommended) or macOS Apple Silicon / Linux + KVM | Sandbox layer. The default OpenShell backend needs a running Docker daemon (Docker Desktop / Colima / OrbStack / …). The alternative microsandbox backend needs hardware virt instead of Docker. Pick one — they're mutually exclusive. Chat still works without either, but exec / browser tools won't. |
| An LLM API key | Anthropic, OpenAI, or Google. Or a local model server reachable on the network. |
npm install -g @tianshu-ai/tianshu@latestDon't sudo. If you hit EACCES, switch to a Node manager that
puts the global bin under your user directory — not a system
folder.
tianshu setupA short interactive wizard. It:
- Asks which provider to use — Anthropic / OpenAI / Google, or "OpenAI-compatible endpoint" for anything that speaks the OpenAI API (Qwen/DashScope, vLLM, LM Studio, a gateway, a local llama.cpp, …). Pick that and the wizard walks you through the base URL and model id — no need to know the flags.
- Reads your API key with a hidden prompt.
- Writes
~/.tianshu/config.json(settings) and~/.tianshu/.env(secret).
Configuring a model is the only step you have to do by hand. Once it's wired up, the setup agent (below) drives everything else — search keys, sandboxes, plugins, updates.
Prefer one command (no prompts)? Use the non-interactive flavour — this is also what you run in Docker / CI:
# Anthropic / OpenAI / Google
tianshu setup --non-interactive --provider=anthropic --api-key=sk-***
# Any OpenAI-compatible endpoint — pass --base-url and --default-model.
# (--provider=openai-compatible is an alias for --provider=openai here.)
# Alibaba Qwen (DashScope), mainland-China endpoint:
tianshu setup --non-interactive --provider=openai --api-key=sk-*** \
--base-url=https://dashscope.aliyuncs.com/compatible-mode/v1 \
--default-model=openai/qwen-plus
# outside China: use https://dashscope-intl.aliyuncs.com/compatible-mode/v1
# A local model server:
tianshu setup --non-interactive --provider=openai --api-key=*** \
--base-url=http://localhost:8080/v1 --default-model=openai/<your-model-id>Flags use
--key=value(an=, not a space).--base-urlis the prefix before/chat/completions, not the full endpoint URL.
Once a model is configured, the wizard hands you over to the
setup agent — an LLM-driven assistant running in the same
terminal that can finish the rest of the configuration for
you. It has 18 tools (run_doctor, sandbox_inventory,
config_write, plugin_enable, build_sandbox,
use_sandbox_build, secret_write, apply_update, ...) and
asks for your confirmation before every state-changing call.
Things you can ask it right now:
- "Set me up a search API key for the web-search plugin." —
it'll ask which provider (Tavily / Brave / SerpAPI / ...),
prompt for the key, and write it via
secret_writeinto the right tenant's plugin config. No editing JSON by hand. - "Build my sandboxes so I can use the browser." — it
calls
sandbox_inventoryfirst to see what's already on disk, thenbuild_sandboxanduse_sandbox_buildto fill in whatever's missing. Browser tools work the moment the layeredtask-runner-with-browsersnapshot is published. - "Doctor's complaining about my provider — fix it." — it
reads
run_doctor, finds the offending line, and proposes the specificconfig_writeorsecret_writecall to fix it before running anything. - "Am I on the latest version?" — it runs
check_for_updateand, if you say yes,apply_update.
You can exit anytime (type done / Ctrl-C) and come back later — the agent re-reads state from disk on each invocation.
tianshu startOn macOS this installs a launchd agent
(~/Library/LaunchAgents/ai.tianshu.prod.plist) that auto-starts
at login and auto-restarts on crash. Linux systemd support is on
the roadmap; for now, run npm run dev from a checkout.
Open http://localhost:3110 and start chatting.
tianshu doctorReports across 8 dimensions — runtime / version freshness / config files / LLM providers / network / sandbox / plugins / tenant DBs. Read-only. Run it anytime something feels off.
Tianshu is a runtime, not a chatbox. Three things make it different:
🌐 A real Chromium sidecar per tenant. Playwright + noVNC. The agent navigates, clicks, types — you watch it live in a side panel, take the mouse back when you want to.
📦 A real Linux sandbox per tenant. Every exec runs in an
isolated sandbox — crash it, fork-bomb it, fill the disk, your host is
untouched. Two interchangeable backends ship as plugins (pick one;
they're mutually exclusive): OpenShell (Docker container, the
recommended default — near-zero idle CPU on Apple Silicon and a
built-in per-host network egress policy) or
microsandbox (a
Hypervisor.framework / KVM microVM, if you'd rather not run Docker).
📁 A real per-tenant workspace. The agent reads and writes files you can preview in the UI; they persist across sessions. The file tree is a first-class citizen, not a "tool output."
Plus:
-
🎛️ Workforce Studio — your agent config, as a versionable Solution. Stop hand-editing scattered
agent.json/SOUL.mdfiles. Studio extracts your live setup (main agent + every worker + the plugin enable-set + prompt blocks) into one Solution you can edit in a three-pane IDE, diff against what's running, export/import as a file, and activate in one click. Override a single worker's model or execution-bias, include/exclude plugins, tune prompt fragments — then apply the whole thing atomically. See docs/architecture/solutions.md. -
💻 OpenCode workers. Beyond the built-in worker, run opencode + oh-my-openagent inside a prebuilt sandbox image as a first-class worker type — near-real-time transcript and resolved tool chips stream back to the board.
-
🤖 Background workers, not "tools." Dispatch parallel agents onto a Kanban board; watch elapsed time per task; intervene when one stalls. Define task dependency graphs in a single batch.
-
🔍 The orchestrator is a supervisor. The main agent (天枢, literally "the pivot") doesn't just dispatch — it reads across every worker run on the board (duration, intervention rate, failure-reason clusters, token cost) and proposes tuning back to you: “Your
web-researchworker hits the 10-min watchdog on 1 in 5 runs — want me to raise itstimeoutMsto 15 min?” Analytics is a recommendation surface, never an auto-tuning control loop — every change still needs your confirm. See ADR-0002 §12 for the full story. -
🏢 Multi-tenant from row 1. Every record carries
tenantId. Sidecars, workspaces, and worker pools are tenant-isolated. -
🧠 A setup assistant that fixes things.
tianshu setupruns a Claude/Codex-driven wizard with 18 tools: it can read your doctor report, enable plugins, write config, build sandboxes, and even upgrade itself. See it talk you through it in the launch video. -
🎚️ Point-and-click day-2 controls. A Settings surface for the things you used to hand-edit: a Models page to manage the provider catalog (add/edit providers + models, pick the default, keys stay server-side), a Network Policy page to see sandbox egress denials and allow hosts with one click, and MCP-server and per-plugin config pages. Config files stay the source of truth — edit either way, they stay in sync.
-
🔌 Resilient model calls. Rate-limit-aware retries (honours
Retry-After), and a client that rides out a dropped connection with exponential backoff and resumes the interrupted turn — no duplicated messages, no lost prompt. -
🔎 Key-free web search built in. An Exa/Parallel-backed
web_searchplus aweb_fetchtool, no extra API key to wire up.
⚠️ Security note (0.5.0): the admin/Settings pages (Models, MCP servers, Network Policy, plugin config) are not yet behind an authorization gate — any signed-in user can edit host-wide config. Run Tianshu as a single trusted operator for now, and don't expose the admin surface to untrusted users on a multi-tenant box. A proper auth/role gate lands with the login work on the roadmap.
Almost everything above is a plugin — capabilities the host loads, enables per tenant, and exposes to the agent as tools / admin pages / channels. Tianshu ships these built-in:
| Plugin | What it does |
|---|---|
| Workspace Files | Browse, read, preview, and upload files in the per-tenant workspace. The file tree is a first-class panel in the UI, and files persist across sessions. |
| OpenShell (recommended sandbox) | Runs the agent's shell (exec) in an NVIDIA OpenShell-managed Docker sandbox. Near-zero idle CPU on Apple Silicon and a built-in per-host network egress policy (allow-list + live denial log). Needs a Docker daemon. |
| MicroSandbox (alternative sandbox) | Runs exec in a microsandbox microVM (Apple Virtualization.framework / KVM) — no Docker needed, but needs hardware virt. Mutually exclusive with OpenShell — enable exactly one. |
| Workboard | The Kanban task board + worker pool. The orchestrator drops tasks onto Ready; workers pick them up, run them (with a live transcript), and report back through In-progress → Done. Supports task dependency graphs and per-worker config. |
| Workforce Studio | Inspect, edit, diff, export/import, and activate your whole agent configuration (main agent + every worker + the enabled plugin set + prompt blocks) as a single versionable Solution, in a three-pane IDE. |
| Web Search | Key-free web_search (hosted Exa / Parallel endpoint, no API key) plus a web_fetch tool that reads any page to markdown. |
| Data Sources | Connect agents to databases — Neo4j graph, MySQL, and more. Agent tools (ds_query, ds_schema, ds_panel) plus a side-panel query explorer with resizable columns, sort, and filter. Board apps get board.ds() / board.dsList() for live database queries inside dashboards. |
| Boards | Interactive HTML dashboards the agent builds and drops into chat or the side panel. Built-in board.llm() for LLM calls and board.ds() for database queries — no API keys needed inside board code. Fullscreen mode for data-heavy dashboards. |
| Scheduler (Cron) | Scheduled and recurring jobs with a calendar panel. Fire a message into a session or drop a task on the workboard at a set time or on a cron schedule. Timezone-aware. |
| Wiki | LLM-powered knowledge vault that distils conversations into an Obsidian-style wiki. Auto-files entities, concepts, and topics. Side-panel browse + semantic search. |
| Local Bridge | Connect tools on your own machine (browser, files, shell) into tianshu over WebSocket. No VM needed — runs on your actual machine. Scoped to your sessions. |
| WeChat (微信) | A chat channel backed by Tencent's iLink bot API — scan a QR code to authorise, then inbound DMs route to the agent through the channel system. |
Manage them under Settings → Plugins (enable/disable + per-plugin config). Third-party plugins install the same way; see docs/architecture/plugins.md.
A narrated walk-through. From zero to "agent driving a real browser on your screen":
npm install -g @tianshu-ai/tianshu@latest
tianshu setupThe wizard picks a provider, reads your key, writes config. If
you skip the LLM step you can edit ~/.tianshu/config.json by
hand later.
tianshu startThe wizard already verified network / config. tianshu start
installs the launchd agent and waits for the server to answer
/api/health.
After tianshu setup writes the provider config it drops you
straight into the setup agent (still in the same terminal).
This is where you finish wiring things up. Type plain English:
You: Set up sandboxes so I can use the browser tool.
The agent will:
- Run
sandbox_inventoryto see what's already built. - If a snapshot is missing, propose
build_sandbox (template='task-runner')and ask you to confirm. - After ~10 min (cold) or ~3 min (warm) the snapshot lands; the
agent publishes it to the
taskrole pointer withuse_sandbox_build. - Repeat for the browser layer
(
task-runner-with-browseron top of the task snapshot).
If the build looks stuck, the agent calls check_build_progress
first — it reads the launchd logs, classifies the build state
(in_progress / stalled / errored), and tells you whether
to wait or retry. It will NOT silently retry a 10-minute build
that's still pulling apt packages.
While you're here, you can keep talking to the agent about
other setup work — say "add a Tavily API key for web search"
or "check for tianshu updates" and it'll handle them with the
same confirm-before-mutating loop. When you're done, type
done or Ctrl-C; the agent saves state to disk and you can
come back later with another tianshu setup.
open http://localhost:3110This is the actual product UI — the chat surface your agent runs under. Try:
You: Open hacker news and tell me the top story right now.
Watch the side panel: a real Chromium tab navigates. The agent can click, type, scroll. You can take the mouse back any time.
Done. You've got a working agent.
| Symptom | First step |
|---|---|
tianshu doctor flags a blocker |
Read the line; the detail field has the fix. |
| Browser tool says "runner not ready" | sandbox_inventory in chat; build the missing snapshot. |
tianshu start says "server didn't respond" |
tianshu logs --stream=err -f for the actual error. |
| Setup wizard wedged | Ctrl-C, re-run tianshu setup --wizard. |
npm install -g errors with EACCES |
Switch to nvm / volta / asdf. Don't sudo. |
More in Troubleshooting.
Once things are running, these are the commands you'll use daily:
tianshu status # plist label, pid, port, /api/health
tianshu logs -f # tail stdout + stderr
tianshu restart # bounce the server
tianshu stop # bootout the launchd agent
tianshu tenant list # tenants + users + open-in-browser URLs
tianshu update # check + install npm latest
tianshu update --check # only check, exit 0/1/2Behind a Cloudflare tunnel or reverse proxy? Set
server.publicUrl in ~/.tianshu/config.json once — every CLI
command prints that hostname instead of localhost.
When something breaks:
tianshu doctor # what's wrong?
tianshu logs -f # what's the server saying?
ls ~/Library/LaunchAgents/ai.tianshu*.plist # is the agent installed?
launchctl list | grep tianshu # is it loaded? PID? exit code?Deeper guides: Getting started · Updating · Running as a service · Developing from a checkout.
flowchart LR
subgraph Browser["Browser"]
UI["React + Vite UI"]
end
subgraph Server["@tianshu-ai/server"]
REST["REST /api"]
WS["WebSocket /ws"]
Agent["Agent runtime<br/>pi-agent-core"]
Workers["Background worker pool"]
DB[("SQLite<br/>(WAL)")]
end
subgraph Sidecars["Per-tenant sidecars"]
ChromiumBox["Chromium + Playwright + noVNC"]
SandBox["Linux sandbox<br/>(OpenShell / microsandbox)"]
Files["Workspace filesystem"]
end
LLM[(LLM providers<br/>Anthropic / OpenAI /<br/>Google / local)]
UI <-- WebSocket --> WS
UI <-- HTTP --> REST
WS --> Agent
REST --> Agent
Agent <--> DB
Agent --> Workers
Workers --> ChromiumBox
Workers --> SandBox
Workers --> Files
Agent <--> LLM
The agent runtime stands on
@earendil-works/pi-agent-core
by @badlogic. The sandbox layer is
pluggable: OpenShell (Docker, the recommended default) or
microsandbox
(Hypervisor.framework / KVM) — one at a time.
A 0.x repo, but the core loop — chat, sandbox exec, sidecar browser,
multi-tenant filesystem, background workers — works end-to-end today.
See the Architecture Decision Records for
the full picture.
Shipped (0.3.x)
-
npm install -g @tianshu-ai/tianshupublished to npm - Production single-port server (SPA + API on
:3110) -
tianshu doctor— runtime / config / network / sandbox / plugins - Setup agent with 18 tools (inventory, build, fix, upgrade)
- Tenant model, plugin registry, sandbox role pointers
Shipped (0.4.x → 0.5.0)
- Workforce Studio — extract / edit / diff / export / activate your agent config as a Solution
- OpenCode workers — opencode + oh-my-openagent as a worker type, in a prebuilt sandbox image
- Settings UI — Models (provider catalog), Network Policy (sandbox egress), MCP servers, per-plugin config
- Rate-limit-aware model retries + client auto-reconnect / resume
- Key-free
web_search+web_fetch - Worker task dependency graphs in one batch
- Data Sources plugin — unified multi-database connector
(Neo4j + MySQL), query panel with sort/filter/resize,
board.ds()API for dashboard apps - Board enhancements —
board.llm()+board.ds()APIs, fullscreen mode, chat-embedded boards with API access - Setup agent improvements — full plugin catalog knowledge,
runtime mutual-exclusivity enforcement,
compatfield guidance, cross-arch deployment flow, China network hints - Doctor improvements —
supportsDeveloperRolecompat check, HOME env check, only checks enabled plugins' prerequisites
Next (0.5.x → 0.6)
- Auth + roles — login, and an authorization gate on the admin/Settings surface (see the security note above)
- Docker image with sandbox layer baked in
- Linux systemd service (
tianshu-prod.servicefor npm global installs) - Skills marketplace (registry + install command)
- Orchestrator analytics:
worker_analytics/worker_task_timeline/worker_propose_tuningtools so the main agent can read across worker runs and propose concrete tuning (see ADR-0002 §12)
Tracked in GitHub Issues.
- ❌ A drop-in ChatGPT clone — see LibreChat, Open WebUI.
- ❌ A no-code workflow builder — see Dify, Flowise.
- ❌ A hosted SaaS — no billing, no SSO, no SLA. Run it on a box you own.
- ❌ An LLM dev framework — Tianshu is an application on top of pi-agent-core.
A development log goes out roughly every week.
Latest — v0.5.0: "I said I'd build it. Now it runs." YouTube · Bilibili · dev.to write-up · 抖音 · 小红书
Pick the channel that fits you:
| Channel | Language | Format |
|---|---|---|
| dev.to/tianshu_ai | English | Long-form articles |
| YouTube @Tianshu-AI | English | Long-form video |
| Bilibili 天枢AI | 中文 | Long-form video |
| X / Twitter @tianshuAIdev | English | Build-in-public threads |
| 小红书 / 抖音 | 中文 | Short-form clips |
PRs, issues, and discussions are welcome — even on day 0. See CONTRIBUTING.md for setup and code style.
For security issues please follow SECURITY.md. Do not file vulnerabilities in public issues.
Apache License 2.0 © 2026 Yu Yu and Tianshu contributors.
Built on pi-agent-core (MIT) by @badlogic; sandbox backends NVIDIA OpenShell and microsandbox (Apache-2.0, by @nyxxxie and contributors).





