Engine Commands
The tandem-engine binary supports several subcommands for running the server and executing tasks.
Command Map
Section titled “Command Map”flowchart TD ROOT[tandem-engine] --> SERVE[serve] ROOT --> STATUS[status] ROOT --> CONFIG[config] ROOT --> RUN[run] ROOT --> PAR[parallel] ROOT --> TOOL[tool] ROOT --> TOKEN[token] ROOT --> BROWSER[browser] ROOT --> STORAGE[storage] ROOT --> MEMORY[memory] ROOT --> SMOKE[smoke] ROOT --> PROV[providers] ROOT --> CHAT[chat placeholder] SERVE --> API[HTTP + SSE runtime] STATUS --> HEALTH[Health check] CONFIG --> CFG[Startup config validation] RUN --> ONE[Single prompt] PAR --> MANY[Concurrent prompt batch] TOOL --> DIRECT[Direct tool execution] TOKEN --> AUTH[API token utilities] BROWSER --> DIAG[Browser diagnostics] STORAGE --> CLEAN[Storage doctor + cleanup + migrate] MEMORY --> IMPORT[Memory import utilities] SMOKE --> E2E[End-to-end runtime smoke test]
Starts the Tandem Engine server. This is the default mode for handling client connections.
tandem-engine serve [OPTIONS]Options:
--hostname <HOSTNAME>/--host <HOSTNAME>: The interface to bind to (default:127.0.0.1, env:TANDEM_ENGINE_HOST).--port <PORT>: The port to listen on (default:39731, env:TANDEM_ENGINE_PORT).--state-dir <DIR>: Custom directory for storing engine state (config, logs, storage).--in-process: Run in in-process mode (for development/debugging).--provider <ID>: Provider ID for this process (openai,openrouter,anthropic,ollama,groq,mistral,together,azure,bedrock,vertex,copilot,cohere).--model <ID>: Provider model override for this process.--api-key <KEY>: API key override for the selected provider for this process.--config <PATH>: Override config file path.--api-token <TOKEN>: Set an explicit token for HTTP endpoints (Authorization Bearer, canonicalX-Agent-Token, or compatibilityX-Tandem-Token; env:TANDEM_API_TOKEN). If omitted,serveloads or creates a shared token by default.--unsafe-no-api-token: Advanced local-only opt-out that disables HTTP API token auth (env:TANDEM_UNSAFE_NO_API_TOKEN=1).--web-ui: Enable embedded web admin UI (env:TANDEM_WEB_UI).--web-ui-prefix <PATH>: Path prefix for embedded web admin UI (default:/admin, env:TANDEM_WEB_UI_PREFIX).
status
Section titled “status”Checks engine health by calling GET /global/health on a target host/port.
tandem-engine status [OPTIONS]Options:
--hostname <HOSTNAME>/--host <HOSTNAME>: Hostname or IP to check (default:127.0.0.1, env:TANDEM_ENGINE_HOST).--port <PORT>: Port to check (default:39731, env:TANDEM_ENGINE_PORT).
acmeslackdemo
Section titled “acmeslackdemo”The feature-gated acme-slack-demo command resets and runs the deterministic
five-profile ACME Slack governance proof against a stopped server’s state
directory. It is available only in builds compiled with --features acme-demo.
cargo run -p tandem-ai --features acme-demo -- acme-slack-demo \ --state-dir /absolute/path/to/tandem-stateThe JSON result reports persisted receipt IDs, Slack post count, approval
decision IDs, and reset/replay counts. See docs/ACME_SLACK_DEMO_HARNESS.md
for operating constraints and evidence details.
config
Section titled “config”Inspect and validate startup environment before the engine binds.
tandem-engine config checktandem-engine config check --jsontandem-engine config referenceconfig check
Section titled “config check”Prints a masked effective-config summary and exits non-zero when startup settings are invalid.
Validated fail-fast invariants include:
- hosted or enterprise auth mode requires context assertion public keys
- hosted or enterprise auth mode requires an explicit transport token from
TANDEM_API_TOKEN,TANDEM_API_TOKEN_FILE, or--api-token - hosted or enterprise auth mode rejects
TANDEM_UNSAFE_NO_API_TOKEN - malformed key material, invalid booleans, invalid modes, and out-of-range numeric settings fail validation
- unknown
TANDEM_*environment variables are reported as warnings
Use --json for CI and deployment automation.
config reference
Section titled “config reference”Prints the generated Markdown configuration reference used by docs/ENGINE_CONFIGURATION.md.
The standard install-verification step: a one-command end-to-end health check of the governed runtime path. By default it boots an isolated in-process server with a fresh state directory and the deterministic local echo provider, so it needs no network access and no API keys.
tandem-engine smoke [OPTIONS]Options:
--against <URL>: Target an already-running engine instead of booting in-process.--token <TOKEN>: API token for--againstmode (env:TANDEM_API_TOKEN).--scenario <NAME>: Run only the named scenario (repeatable):session-prompt,approval-gate,policy-denial,memory-roundtrip.--json: Emit machine-readable JSON results.--timeout-secs <N>: Overall deadline in seconds (default:60).
Scenarios:
session-prompt: session create →prompt_async→ assistant reply observed in the message log.approval-gate: gated automation run reachesawaiting_approval, is approved through the gate API, and completes with the decision recorded ingate_history.policy-denial: an agent-sourced governance mutation is rejected with a structured error and recorded in the protected audit log.memory-roundtrip: governed memoryput→searchreturns the stored fact.
The exit code is non-zero if any scenario fails. The same check runs as the
engine-smoke job in CI on every engine PR.
# In-process, all scenariostandem-engine smoke
# Against a running engine, JSON output for CItandem-engine smoke --against http://127.0.0.1:39731 --token "$TANDEM_API_TOKEN" --jsonbrowser
Section titled “browser”Browser readiness and diagnostics. This is the operator-facing entrypoint for headless browser setup on desktops and VPS hosts.
tandem-engine browser <status|doctor|install> [OPTIONS]browser status
Section titled “browser status”Check browser readiness through a running engine (GET /browser/status).
tandem-engine browser status [OPTIONS]--hostname <HOSTNAME>/--host <HOSTNAME>: Hostname or IP to check (default:127.0.0.1, env:TANDEM_ENGINE_HOST).--port <PORT>: Port to check (default:39731, env:TANDEM_ENGINE_PORT).
browser doctor
Section titled “browser doctor”Run local browser readiness diagnostics using the same effective engine config the server would use.
tandem-engine browser doctor [OPTIONS]--state-dir <DIR>: Engine state directory used to resolve the config file.--config <PATH>: Override config file path.--json: Print the full readiness payload as JSON.
browser install
Section titled “browser install”Install the matching tandem-browser sidecar onto the engine host from GitHub Releases.
tandem-engine browser install [OPTIONS]--state-dir <DIR>: Engine state directory used to resolve the config file.--config <PATH>: Override config file path.--json: Print the install result as JSON.
Browser HTTP Endpoints
Section titled “Browser HTTP Endpoints”The browser command group pairs with runtime HTTP endpoints:
GET /browser/statusPOST /browser/installPOST /browser/smoke-test
These endpoints are for browser readiness and install flows. Actual browser automation is exposed through engine tools such as browser_open, browser_click, browser_type, browser_extract, and browser_screenshot.
Use one of these paths for browser automation:
tandem-engine tool --json ...POST /tool/execute- session-based agent runs with the browser tools included in the run allowlist
For browser_wait, the canonical tool args use condition: { kind, value }, but the engine also accepts wait_for / waitFor, camelCase fields like sessionId, and short forms like top-level selector, text, or url.
Headless Hosts
Section titled “Headless Hosts”Browser automation does not require a visible desktop session. On Linux VPS hosts the engine only needs:
tandem-browserinstalled on the same host astandem-engine- a Chromium-based browser executable such as Chrome, Chromium, or Edge
- the required Linux shared libraries for Chromium
If the browser executable is not on PATH, set TANDEM_BROWSER_EXECUTABLE or browser.executable_path.
For a full setup and test flow, see Browser Setup and Testing.
storage
Section titled “storage”Inspect and clean local Tandem storage.
storage migrate
Section titled “storage migrate”Transfer the stateful orchestration store between SQLite and PostgreSQL with a locked source and a fingerprint-verified target. When a different target state directory is supplied, the authoritative session/message and runtime-event SQLite stores are snapshot-copied and verified with it. Stop the engine first.
tandem-engine storage migrate --from sqlite --to postgres \ --state-dir /srv/tandem \ --target-postgres-url "$TANDEM_STORAGE_TARGET_POSTGRES_URL" --json--from <sqlite|postgres>and--to <sqlite|postgres>select different endpoints.--state-dir <DIR>identifies the source runtime root.--target-state-dir <DIR>selects a different target root; it is useful for a PostgreSQL-to-SQLite rollback and otherwise defaults to--state-dir.--source-postgres-urland--target-postgres-urlprovide the applicable PostgreSQL endpoint.--jsonemits source/target fingerprints, record count, and idempotent completion evidence.
The target fails closed while a migration is in progress. Re-running the same command resumes a verified transfer; a populated target or changed source is refused. See the stateful PostgreSQL backend runbook for backup and retention guidance.
tandem-engine storage <doctor|worktrees|cleanup> [OPTIONS]storage doctor
Section titled “storage doctor”Print a local storage report without mutating files.
tandem-engine storage doctor --json--state-dir <DIR>: Engine state directory to inspect.--json: Print the report as JSON.
storage cleanup
Section titled “storage cleanup”Move root-level feature JSON into canonical data/<feature>/ paths, archive old context runs, and optionally purge the legacy embedded-doc seed.
tandem-engine storage cleanup --dry-run --context-runs --jsontandem-engine storage cleanup --dry-run --root-json --jsontandem-engine storage cleanup --dry-run --default-knowledge --jsonCommon options:
--root-json: Migrate/quarantine legacy root JSON files into canonicaldata/directories.--context-runs: Archive terminal or stale old context runs from hot storage.--default-knowledge: Remove the legacy embedded-doc bootstrap marker andguide_docs:rows from memory.--retention-days <DAYS>: Keep recent context runs hot for this many days.--dry-run: Report planned actions without changing files.--quarantine: Move migrated root JSON to a backup quarantine instead of deleting it.--json: Print a machine-readable report.
When running cleanup against a deployed local service:
sudo systemctl stop tandem-enginetandem-engine storage cleanup --context-runs --root-json --quarantine --jsonsudo systemctl restart tandem-engineIf a developer machine has more than one tandem-engine on PATH, run which -a tandem-engine first and call the intended binary explicitly.
storage worktrees
Section titled “storage worktrees”Preview or remove stale repo-local managed worktrees through a running engine. This targets <repo>/.tandem/worktrees, not the engine state root.
tandem-engine storage worktrees --repo-root /abs/path/to/repotandem-engine storage worktrees --repo-root /abs/path/to/repo --apply --jsonCommon options:
--hostname <HOSTNAME>/--host <HOSTNAME>: Hostname or IP address of the running engine (default:127.0.0.1, env:TANDEM_ENGINE_HOST).--port <PORT>: Port of the running engine (default:39731, env:TANDEM_ENGINE_PORT).--repo-root <PATH>: Absolute repository root whose.tandem/worktreesshould be inspected.--apply: Remove stale worktrees instead of running a dry-run preview.--keep-orphan-dirs: Leave unregistered leftover directories on disk.--json: Print the full cleanup report as JSON.
This command calls POST /worktree/cleanup on the running engine. It skips worktrees the current runtime still tracks as active, removes stale Git worktree entries and managed branches when possible, and can also remove orphaned directories left under .tandem/worktrees.
memory
Section titled “memory”Memory import utilities for seeding Tandem memory from existing files or an OpenClaw export.
tandem-engine memory import [OPTIONS]The same importer is also exposed at runtime through POST /memory/import and the SDK memory import helpers. Use the HTTP or SDK API when an application, automation, or control panel flow should import knowledge without shelling out to the CLI.
memory import
Section titled “memory import”Import OpenClaw memory files or a markdown/text directory into Tandem memory.
tandem-engine memory import --path ./docs --tier global--path <PATH>: Path to an OpenClaw root or a directory of markdown/text files to import.--format <FORMAT>: Import format, eitherdirectoryoropenclaw(default:directory).--tier <TIER>: Target memory tier, one ofglobal,project, orsession(default:global).--project-id <PROJECT_ID>: Required when--tier project.--session-id <SESSION_ID>: Required when--tier session.--sync-deletes: Remove previously imported records whose source files no longer exist under the import root.--state-dir <DIR>: Engine state directory used to resolvememory.sqliteand config.
Examples:
tandem-engine memory import --path ~/.openclaw --format openclawtandem-engine memory import --path ./notes --tier globaltandem-engine memory import --path ./docs --tier project --project-id repo-123 --sync-deletesEquivalent HTTP request:
{ "source": { "kind": "path", "path": "./docs" }, "format": "directory", "tier": "project", "project_id": "repo-123", "session_id": null, "sync_deletes": true}The API returns import stats for discovered files, indexed files, skipped files, deleted files, created chunks, and errors.
Execute a single prompt and exit. Useful for quick CLI queries or scripting.
tandem-engine run "<PROMPT>"Options:
--provider <ID>: Provider for this run. Unknown IDs fail fast.--model <ID>: Provider model override for this run.--api-key <KEY>: API key override for this run’s provider.--config <PATH>: Override config file path.
Example:
tandem-engine run "What is the capital of France?"Provider precedence:
run --provideruses that provider explicitly.- If no explicit provider is passed,
default_providerfrom config is used. - If
default_provideris missing or unavailable, Tandem falls back to the first configured provider.
API key behavior:
--api-keyapplies only to the selected provider for that command invocation.- Without
--api-key, Tandem uses provider-specific config/env vars (for exampleOPENROUTER_API_KEY,OPENAI_API_KEY,ANTHROPIC_API_KEY).
Execute a specific tool directly by passing a JSON payload.
tandem-engine tool --json '<JSON_PAYLOAD>'Options:
--json <JSON>: The JSON payload defining the tool and arguments. Can be a raw string, a file path (@path/to/file.json), or-for stdin.--state-dir <DIR>: Custom state directory.
Example Payload:
{ "tool": "read", "args": { "path": "README.md" }}Browser automation uses this same tool execution surface. Example:
{ "tool": "browser_open", "args": { "url": "https://example.com" }}MCP auth-required and retry behavior
Section titled “MCP auth-required and retry behavior”For MCP-backed tools, Tandem can emit an explicit authorization event when upstream requires OAuth/account consent:
- Event:
mcp.auth.required - Event:
mcp.auth.pending(challenge still pending, call short-circuited) - MCP runtime state fields:
last_auth_challengemcp_session_id
If auth is required, complete authorization and retry the tool call. Tandem applies an engine-level re-probe cooldown (~15s) per challenged tool to prevent auth loops. A full engine restart is not required.
MCP argument normalization (engine-wide)
Section titled “MCP argument normalization (engine-wide)”Before forwarding MCP tools/call, Tandem normalizes common argument-key drift against tool schema.
Examples:
taskTitle->task_titlelistId->list_id- common alias recovery such as
name->task_titlewhen required by schema
This behavior runs in engine runtime and applies to web, TUI, channels, and direct CLI usage.
Planned interactive REPL mode. This command is currently a placeholder.
parallel
Section titled “parallel”Run multiple prompts concurrently and return a JSON summary.
tandem-engine parallel --json '<JSON_PAYLOAD>' --concurrency 4Options:
--json <JSON>: Array of prompts, array of objects, or{ "tasks": [...] }wrapper. Accepts raw JSON,@file, or-for stdin.--concurrency <N>: Max concurrent tasks (default:4).--provider <ID>: Default provider for tasks without explicit provider.--model <ID>: Default model override for the provider.--api-key <KEY>: API key override for this batch.--config <PATH>: Override config file path.
providers
Section titled “providers”List supported provider IDs for --provider.
tandem-engine providersAPI token utilities (used with --api-token).
tandem-engine token generateAgent Team HTTP Examples
Section titled “Agent Team HTTP Examples”These are HTTP endpoints exposed by the running engine (not CLI subcommands).
curl -s http://127.0.0.1:39731/agent-team/templates | jq .curl -s http://127.0.0.1:39731/agent-team/instances | jq .curl -s -X POST http://127.0.0.1:39731/agent-team/spawn \ -H "content-type: application/json" \ -d '{"missionID":"m1","role":"worker","templateID":"worker-default","source":"ui_action","justification":"parallelize implementation"}' | jq .Practical Examples
Section titled “Practical Examples”Run Engine with API Token
Section titled “Run Engine with API Token”TANDEM_API_TOKEN="tk_your_token_here" tandem-engine serve --hostname 127.0.0.1 --port 39731Run One Prompt with Explicit Provider and Model
Section titled “Run One Prompt with Explicit Provider and Model”tandem-engine run "Write a concise release summary." --provider openrouter --model openai/gpt-4o-miniRun a Concurrent Batch
Section titled “Run a Concurrent Batch”cat > tasks.json << 'JSON'{ "tasks": [ { "id": "plan", "prompt": "Create a 3-step rollout plan." }, { "id": "risks", "prompt": "List top 5 rollout risks." }, { "id": "comms", "prompt": "Draft a short launch update." } ]}JSON
tandem-engine parallel --json @tasks.json --concurrency 3Execute Tools Directly
Section titled “Execute Tools Directly”tandem-engine tool --json '{"tool":"workspace_list_files","args":{"path":"."}}'tandem-engine tool --json '{"tool":"websearch","args":{"query":"tandem engine protocol matrix","limit":5}}'tandem-engine tool --json '{"tool":"memory_search","args":{"query":"mission runtime","user_id":"user-123","limit":5}}'spawn_agent is runtime-gated and should be called from a session prompt (not tandem-engine tool direct mode):
curl -s -X POST http://127.0.0.1:39731/session/<session_id>/prompt_async \ -H "content-type: application/json" \ -d '{"parts":[{"type":"text","text":"/tool spawn_agent {\"missionID\":\"m1\",\"role\":\"worker\",\"templateID\":\"worker-default\",\"source\":\"tool_call\",\"justification\":\"parallelize implementation\"}"}]}'Start prompt_async with file attachments
Section titled “Start prompt_async with file attachments”Send rich prompt parts (text + files) in one call:
curl -s -X POST "http://127.0.0.1:39731/session/<session_id>/prompt_async?return=run" \ -H "content-type: application/json" \ -H "X-Agent-Token: tk_your_token" \ -d '{ "parts": [ { "type": "file", "mime": "image/jpeg", "filename": "photo.jpg", "url": "/srv/tandem/channel_uploads/telegram/123/photo.jpg" }, { "type": "text", "text": "Describe this image and summarize key details." } ] }'Notes:
urlmay be an HTTP URL, a local path, orfile://...path.mimeshould match the file type (image/jpeg,text/markdown,application/pdf, etc).- Stream completion can surface as
run.complete,run.completed, orsession.run.finisheddepending on client/version.
Browser Playground (Interactive)
Section titled “Browser Playground (Interactive)”Use the included browser playground in docs/example.html to test:
- session creation
- async runs + SSE streaming
- token-auth requests
- mission/routine API interactions
python -m http.server 8080 --directory docsThen open http://127.0.0.1:8080/example.html.