// run it anywhere

Deploy & Gateway

Start on the local CLI — zero infra, fully on-device. Scale out by wrapping orchestrator.run behind a thin service. Keep the model local even when hosted, so the privacy story holds.

┌─ options

Local first. Hosted when you need it.

default

Local CLI

The most private path: zero infrastructure, fully on-device. The brain (Qwen2.5 / Ollama) and tools (stdio MCP) all run locally. Nothing leaves the box.

scale out

Gateway

Wrap orchestrator.run behind a thin service — a run_agent MCP server for Claude Code, or an HTTP/SSE gateway for Telegram/Slack. Put auth, rate-limits, and a per-tenant allowlist at the edge. Keep the model local even when hosted; cloud secrets stay in tachibot-mcp.

// gateway API

Async jobs + an SSE stream.

All requests require Authorization: Bearer <token>. The async-job + SSE shape survives disconnects — resume replay via Last-Event-ID.

bash — start the gateway
export GATEWAY_TOKEN="change-me" GATEWAY_PORT=8787
export TACHIBOT_CMD="npx -y tachibot-mcp"
npm run build && node dist/frontends/gateway.js
Method & pathResponsePurpose
POST /runs
{task, maxIterations?}
202 {run_id} Start a run (async job).
GET /runs/:id state + result Poll run state and final result.
GET /runs/:id/events SSE Stream step / assistant / tool-result / final / error / heartbeat.
DELETE /runs/:id cancel Cooperative abort (Ctrl-C semantics).
┌─ L2.5 — daemon

Long-running, attachable, resumable.

A long-running daemon reuses the gateway and lets thin clients attach mid-run.

  • Thin-client attach + session handoff. Detach and reconnect without losing the run.
  • Durable monotonic event sequence. Buffered replay on reconnect via Last-Event-ID.
  • Refcount-aware TTL / GC. Runs evict when no client holds a reference; graceful drain on shutdown.
  • UnifiedClient. Makes local and daemon execution interchangeable — swap a single constructor, no behavior change.
  • Standalone foundation. Run it under launchd / systemd and it operates unattended: a crash-safe persistent task queue (POST /tasks), recurring schedules, per-task drivers via TACHI_DRIVER, outcome notifications, and durable run logs — read the Standalone page →
// OpenClaw bridge

Delegate over the gateway.

Let OpenClaw delegate tasks to tachi-agent over the gateway's HTTP/SSE API. Run the gateway with a GATEWAY_TOKEN, then use the bundled GatewayClient:

typescript — GatewayClient
import { GatewayClient } from "tachi-agent";

const tachi = new GatewayClient({
  baseUrl: "http://127.0.0.1:8787",
  token: process.env.TACHI_GATEWAY_TOKEN!,
});
const answer = await tachi.runAndWait("research X");

See docs/openclaw-bridge.md for plugin / skill wiring.

┌─ security posture

Local-first is the security model.

local-first

Near-zero secret surface

Default brain is Qwen2.5 on 127.0.0.1 (no SSRF); tools run over local stdio. tachi-agent holds no cloud keys — the council's provider keys live in tachibot-mcp.

trust boundary

Config, not messages

MCP server commands come only from config / env (*_CMD), never from a user or model message — no command injection. The allow list keeps dangerous tools out unless granted.

edge auth

Untrusted front-ends

Telegram / Slack / HTTP authenticate at the edge — allowed user-ids, app tokens, localhost-only MCP. The task string is data; the agent can only call allowlisted tools, never arbitrary shell.

prompt injection

Tool output is untrusted

Search and tool results may carry injection. Mitigate with a bounded allowlist (no shell / file-write by default), treat tool output as untrusted data, and gate any write tool behind approval (roadmap).