太刀tachi-agent · from install to first chat

Get started.

No API keys, no cloud account. One line installs the whole stack — Node, Ollama, agent + memory + council — and hands off to the tachi-agent setup wizard. Then open an interactive chat with bare tachi-agent. Ctrl-C halts cleanly; progress goes to stderr, the answer to stdout.

$curl -fsSL https://bypawel.github.io/tachi-agent/install.sh | sh
01 · Install & chat

One line installs everything. Then just chat.

The setup wizard
tachi-agent setup picks a brain — local Ollama by default, or paste one OpenRouter key to power the agent and the whole tachibot council — wires the MCP servers, generates GATEWAY_TOKEN, optionally installs the daemon service, then runs doctor. It's re-runnable and merge-preserving: existing values in ~/.tachi/.env become the defaults. Skip it with TACHI_NO_WIZARD=1.
~/.tachi/.env
Written chmod 600. Every tachi-agent bin loads it as defaults at startup — real env vars always win; TACHI_ENV_FILE overrides the path.
tachi-agent doctor
Checks your Ollama endpoint, required env vars, MCP server commands and coding-worker readiness. Run it the first time and whenever something looks off.
Your first chat
Bare tachi-agent opens a persistent REPL. The prompt shows tachi [driver·skill] ›. The session is multi-turn; /reset starts fresh; /help lists commands. Ctrl-D or /exit to leave.
one-line stack install + chat quickstartshell
1# ONE LINE — installs Node ≥ 22 + Ollama if missing, then tachi-agent + dokoro
2# + tachibot-mcp, and hands off to the interactive setup wizard
3curl -fsSL https://bypawel.github.io/tachi-agent/install.sh | sh
4
5# — or manually —
6# 1. install the stack globally
7npm i -g tachi-agent dokoro tachibot-mcp
8
9# 2. pull a local brain (the wizard offers OpenRouter as the one-key alternative)
10ollama serve &
11ollama pull qwen2.5
12
13# 3. run the wizard — picks a brain, wires MCP servers, writes ~/.tachi/.env (chmod 600)
14tachi-agent setup
15
16# 4. preflight check
17tachi-agent doctor
18
19# 5. open interactive chat
20tachi-agent
02 · One-shot & develop

One-shot tasks and local development.

Ctrl-C halts the run cleanly (AbortSignal → aborted). Progress streams to stderr; the final answer prints to stdout — so you can pipe the answer while still watching steps.

Installing globally (or npm link from a clone) puts eight binaries on your PATH:

tachi-agenttachi-agent-daemontachi-agent-mcptachi-agent-gatewaytachi-agent-telegramtachi-agent-slacktachi-agent-repltachi-agent-swarm
one-shot + developshell
1# one-shot task (pass a string argument)
2tachi-agent "verify HEAD against ADR-1..3"
3
4# develop from source
5npm install
6npm test # vitest — core orchestrator, fully mocked
7npm run build # tsc → dist/
from a clone (no registry needed)shell
1# 1. local brain
2ollama serve & # start Ollama
3ollama pull qwen2.5 # recommended local tool-calling model
4
5# 2. point at your MCP servers (council + memory)
6export TACHIBOT_CMD="npx -y tachibot-mcp"
7export DOKORO_CMD="npx -y @devlog-mcp/core" # optional; omit to run tachibot-only
8
9# 3. build + link the tachi-agent command
10npm install && npm run build && npm link
11
12tachi-agent # interactive chat (default, no args)
13tachi-agent "verify HEAD against ADR-1..3" # one-shot task
14tachi-agent --driver openai # chat with the OpenAI heart
15tachi-agent --skill researcher # chat with the researcher skill active
16# dev mode: npm run dev -- "your task"
Golden demo

All three layers in two commands.

The first command exercises every layer: dokoro recalls prior context (memory), tachibot_jury adjudicates the finding (reasoning), and the ReAct loop drives the whole flow (runtime). The second confirms the decision persists across sessions.

golden demoshell
1# 1. run a task that exercises memory → reasoning → runtime
2tachi-agent "review this repo, find one risky architectural issue, verify it with the council, remember the decision"
3
4# 2. next session: the agent recalls what you decided
5tachi-agent "what did we decide last time about that architecture risk?"
Front-ends

Talk to the same hub, any surface.

Every front-end just calls orchestrator.run(task) — or attaches to a running daemon with an identical surface.

CLI / REPL (default)
Bare tachi-agent opens the interactive REPL; multi-turn (the conversation carries across turns; /reset clears). Pass a string for a one-shot task.
Skills
--skill <name> loads a .tachi/skills/*.md recipe — system prompt + tool allowlist + driver preset.
Telegram
Bot front-end with allowed user-ids; the unified /commands surface and per-chat multi-turn memory.
Slack
Socket Mode app with a user-ID allowlist.
Claude Code
Connect in via the run_agent MCP server; pass driver / skill / systemPrompt to run tachi-agent as a configurable sub-agent. Or delegate to external CLIs with run_coding_agent.
HTTP / SSE Gateway
Async jobs + streamed events — see Deploy & Gateway.
OpenClaw bridge
Delegate over the gateway with GatewayClient.
Swarm
Fan-out / synthesize bin: npm run swarm — see Swarm.
Standalone daemon
Unattended queue + schedules + notifications: tachi-agent service install (macOS launchd, primary path) or node dist/daemon/index.js under systemd — see Standalone.
03 · Configuration

Env vars are the config surface.

Set them in ~/.tachi/.env (the wizard writes it) or a project .env loaded with node --env-file=.env. Real env vars always win.

Orchestrator

VariableDefaultPurpose
TACHI_ALLOWcurated council/search/memory setComma-separated tool allowlist (exact names or server_ prefixes). tachibot_,dokoro_ exposes everything.
TACHI_FORCE_SEARCHoff1/true/yes/on → force a grounding search before reasoning on every task.
TACHI_MAX_EMPTY_TURNS2Consecutive blank model turns nudged through before halting as empty-response.
TACHI_CALL_TIMEOUT_MS120000Per-MCP-tool-call timeout.
TACHI_RUN_TIMEOUT_MS90000Whole-run wall-clock cap for the run_agent MCP server (max 3600000); callers can pass timeoutMs per call. The MCP client's own call timeout must be ≥ this (Claude Code: MCP_TOOL_TIMEOUT).
TACHI_MAX_TOOL_RESULT_CHARS30000Truncate tool results before they reach the model context (0 disables).
TACHI_CONTEXT_INSPECToff1 → emit per-turn context JSONL to .tachi/context-inspect/.
TACHI_ENV_FILE~/.tachi/.envPath of the wizard-managed env file. Every bin loads it as defaults at startup; real env vars always win.
TACHI_NO_WIZARDunset1 skips the setup wizard at the end of the one-line installer.

Drivers

VariableDefaultPurpose
TACHI_DRIVERollamaDefault brain by registered name: ollama · hermes · openai · openrouter. A queued task's driver field overrides per task.
OLLAMA_BASE_URLhttp://127.0.0.1:11434Ollama endpoint for the local brain.
OLLAMA_MODELqwen2.5Local model name.
OLLAMA_NUM_CTX8192Context window override.
HERMES_BASE_URL / _MODEL / _API_KEYunsetOptional Hermes (OpenAI-compatible) driver.
OPENAI_API_KEYunsetRequired for the openai driver.
OPENAI_MODELgpt-4o-miniOpenAI model.
OPENAI_BASE_URLhttps://api.openai.com/v1OpenAI-compatible endpoint (include /v1).
OPENROUTER_API_KEYunsetRequired for the openrouter driver.
OPENROUTER_MODELopenrouter/autoOpenRouter model.
OPENROUTER_BASE_URLhttps://openrouter.ai/api/v1OpenRouter endpoint.

MCP servers & skills

VariableDefaultPurpose
TACHIBOT_CMDunsetCommand to spawn the tachibot multi-model MCP server (council tools).
DOKORO_CMDunsetCommand to spawn the dokoro memory MCP server. Optional.
TACHI_SKILLS_DIR.tachi/skillsDirectory of *.md skill files. Malformed files are skipped with a warning.

Front-ends

VariableDefaultPurpose
TELEGRAM_BOT_TOKEN / TELEGRAM_ALLOWED_USER_IDSrequiredBot token + comma-separated numeric allowlist (fail-closed: empty = refuse to start).
SLACK_BOT_TOKEN / SLACK_APP_TOKEN / SLACK_ALLOWED_USER_IDSrequiredBot + Socket-Mode app token + user-ID allowlist (fail-closed).

Gateway / daemon

VariableDefaultPurpose
GATEWAY_TOKEN / GATEWAY_TOKENSrequiredBearer auth (single token, or name:token pairs for tenants). The daemon refuses to start without one.
GATEWAY_PORT8787Gateway listen port (tachi-agent-gateway).
TACHI_DAEMON_URLunsetWhen set, thin clients (cli / repl / telegram / slack) attach to the daemon instead of building a local runtime.
TACHI_DAEMON_PORT8787Daemon listen port.
TACHI_SESSION_TTL_MS600000Idle TTL before an unattached finished run is GC'd.
TACHI_SESSION_BUFFER_MAX10000Per-run SSE replay ring-buffer cap.
TACHI_DRAIN_TIMEOUT_MS30000Hard upper bound on graceful-shutdown drain.
TACHI_DEBUGoffVerbose stderr diagnostics.

Standalone & swarm

VariableDefaultPurpose
TACHI_QUEUE_FILE.tachi/queue.jsonPersistent task-queue file (atomic writes; crash-safe).
TACHI_QUEUE_POLL_MS2000Worker poll cadence over the queue.
TACHI_RUN_LOG_DIR.tachi/runsDurable per-run JSONL event log directory.
TACHI_NOTIFYunsetOutcome push targets: comma-separated kind:target, e.g. telegram:123,slack:C0ABC.
TACHI_SCHEDULES_FILE.tachi/schedules.jsonHand-edited recurring schedules (state kept separately in …-state.json).
TACHI_SCHEDULES_POLL_MS30000Schedule evaluation cadence.
TACHI_SWARM_ROLESbuilt-in rolesComma-separated roles; name or name:driver; empty = defaults.
Coding-worker variables (TACHI_CODING_ROOTS, TACHI_CODING_ALLOW_WRITE, …) are documented on the Coding workers page.
04 · Extending

Extend without forking.

Register any brain, build the hub from a name, run. The complete public API is three interfaces — see src/types.ts. Implement Driver, ToolHost, or Memory and compose the same hub; no core changes required.

register a driverts
1import { createOrchestrator, registerDriver } from "tachi-agent";
2
3// 1. register any brain (Hermes, a cloud model, OpenClaw, a Kimi-swarm driver)
4registerDriver("hermes", () => new HermesDriver());
5
6// 2. build the hub from a registered name (or a raw Driver instance)
7const controller = new AbortController();
8const result = await createOrchestrator({
9 driver: "hermes",
10 host,
11 memory,
12 options: {
13 maxIterations: 12,
14 timeoutMs: 90_000,
15 signal: controller.signal,
16 // memoryInLoop: true // opt-in: refresh recall + write a working-memory note
17 // // each iteration. Off by default (adds per-step tool calls).
18 },
19}).run("verify HEAD against ADR-1..3");
20// elsewhere: controller.abort() → run halts with haltedBy: "aborted"