太刀tachi-agent · 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.

01 · 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 (with driver / skill / systemPrompt parameters for configurable sub-agent runs), or an HTTP/SSE gateway for Telegram / Slack (POST /runs accepts history for multi-turn continuity). Put auth, rate-limits, and a per-tenant allowlist at the edge. Host only the thin orchestrator, not the brain; cloud secrets stay in tachibot-mcp.
02 · Gateway API

Async jobs + an SSE stream.

All requests require Authorization: Bearer <token>; run ids are namespaced per tenant (GATEWAY_TOKENS takes name:token pairs). The async-job + SSE shape survives disconnects — resume replay via Last-Event-ID.

start the gatewayshell
1export GATEWAY_TOKEN="change-me" GATEWAY_PORT=8787
2export TACHIBOT_CMD="npx -y tachibot-mcp"
3npm run build && node dist/frontends/gateway.js
Method & pathResponsePurpose
POST /runs {task, maxIterations?, driver?, systemPrompt?, allowTools?, history?}202 {run_id}Start a run (async job). history = up to 40 {role: "user" | "assistant", content} turns, ≤ 32 KiB — chat continuity.
GET /runs/:idstate + resultPoll run state and the final result.
GET /runs/:id/eventsSSEStream step / assistant / tool-result / final / error / heartbeat.
DELETE /runs/:idcancelCooperative 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. Set TACHI_DAEMON_URL and the CLI, REPL, Telegram and Slack front-ends attach to it instead of building a local runtime.

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
Under launchd / systemd it operates unattended: a crash-safe task queue (POST /tasks), recurring schedules, per-task drivers, 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 (npm run gateway) with a GATEWAY_TOKEN, then use the bundled GatewayClient. See docs/openclaw-bridge.md for plugin / skill wiring.

GatewayClientts
1import { GatewayClient } from "tachi-agent";
2
3const tachi = new GatewayClient({
4 baseUrl: "http://127.0.0.1:8787",
5 token: process.env.TACHI_GATEWAY_TOKEN!,
6});
7const answer = await tachi.runAndWait("research X");
03 · Security posture

Local-first is the security model.

local-first
Near-zero secret surface
The 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 McpToolHost({ allow }) allowlist keeps dangerous tools out unless granted.
edge auth
Untrusted front-ends
Telegram / Slack / HTTP authenticate at the edge — allowed user-ids (fail-closed), 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).