Headless Service
Run Tandem as a standalone headless service with the master tandem CLI and optional embedded web admin.
Managed install
npm i -g @frumu/tandemtandem doctortandem service installtandem install paneltandem panel initUse tandem status and tandem service status to confirm the engine service is running.
Start the Engine (Headless)
tandem-engine serve \ --hostname 127.0.0.1 \ --port 39731 \ --api-token "$(tandem-engine token generate)"This starts the HTTP/SSE engine runtime without desktop UI requirements.
Enable Embedded Web Admin
tandem panel statustandem panel opentandem-engine serve \ --hostname 127.0.0.1 \ --port 39731 \ --api-token "tk_your_token" \ --web-ui \ --web-ui-prefix /admin$env:TANDEM_WEB_UI=“true”; .\src-tauri\binaries\tandem-engine.exe serve —hostname 127.0.0.1 —port 39731 —web-ui —state-dir .tandem-test
Open:
http://127.0.0.1:39731/admin
The admin page expects a valid API token and keeps it in memory for the current tab/session.
Environment Variable Mode
TANDEM_API_TOKEN=tk_your_tokenTANDEM_WEB_UI=trueTANDEM_WEB_UI_PREFIX=/admintandem statustandem-engine serve --hostname 127.0.0.1 --port 39731Common Headless Admin Endpoints
GET /global/healthGET /browser/statusPOST /browser/installPOST /browser/smoke-testGET /channels/statusPUT /channels/{name}DELETE /channels/{name}GET /global/storage/files?path=channel_uploads&limit=200POST /admin/reload-configPOST /memory/importPOST /memory/putPOST /memory/searchGET /memoryPOST /memory/promotePOST /memory/demoteDELETE /memory/{id}
These browser endpoints are for readiness, installation, and smoke testing. Actual browser automation in headless deployments goes through engine tools such as browser_open, browser_click, and browser_screenshot via POST /tool/execute or session-based runs with explicit tool allowlists.
Example: Check Health
curl -s http://127.0.0.1:39731/global/health \ -H "X-Agent-Token: tk_your_token"Example: Check Channel Status
curl -s http://127.0.0.1:39731/channels/status \ -H "X-Agent-Token: tk_your_token"Example: Browser Readiness + Install
curl -s http://127.0.0.1:39731/browser/status \ -H "X-Agent-Token: tk_your_token"
curl -s -X POST http://127.0.0.1:39731/browser/install \ -H "X-Agent-Token: tk_your_token"
curl -s -X POST http://127.0.0.1:39731/browser/smoke-test \ -H "X-Agent-Token: tk_your_token"Example: Browser Automation via Tool Execution
curl -s -X POST http://127.0.0.1:39731/tool/execute \ -H "X-Agent-Token: tk_your_token" \ -H "content-type: application/json" \ -d '{"tool":"browser_open","args":{"url":"https://example.com"}}'Example: Import Docs Into Memory
POST /memory/import indexes files that already exist on the engine host. The first import source is path-based; upload and zip imports are separate follow-up surfaces.
curl -s -X POST http://127.0.0.1:39731/memory/import \ -H "X-Agent-Token: tk_your_token" \ -H "content-type: application/json" \ -d '{ "source": { "kind": "path", "path": "/srv/tandem/imports/company-docs" }, "format": "directory", "tier": "project", "project_id": "company-brain-demo", "session_id": null, "sync_deletes": true }'Supported format values are directory and openclaw. Supported tier values are global, project, and session; project imports require project_id, and session imports require session_id.
The response includes import stats such as discovered_files, indexed_files, skipped_files, deleted_files, chunks_created, and errors.
Channel Uploads and Media
Channel adapters can persist inbound attachments under the engine storage root in channel_uploads/....
You can inspect saved files with:
curl -s "http://127.0.0.1:39731/global/storage/files?path=channel_uploads&limit=200" \ -H "X-Agent-Token: tk_your_token"Typical media flow:
- Channel receives media (
photo,document, etc). - Adapter stores file under
channel_uploads/<channel>/<chat_or_user>/.... - Adapter forwards prompt parts to engine with both text and file parts.
- Runs stream back over SSE like normal chat runs.
If provider/model cannot use a given media type, the run should still complete with text fallback guidance instead of hanging.
Headless and Channel Memory
When channels are enabled on a headless engine, Tandem keeps memory in two layers:
- full session transcript history in normal session storage
- compact global retrieval memory containing exact user-visible completed user+assistant exchanges
This is designed so that:
- long-running channel bots can recall prior work across sessions
- memory retrieval stays much smaller than full transcript replay
- the raw transcript remains preserved even if retrieval memory is compacted later
For the storage-level breakdown of these layers, see Memory Internals.
Security Notes
tandem-engine serverequires API token auth by default and will load or create a shared token when no explicit token is provided.- Use an explicit
--api-tokenorTANDEM_API_TOKENfor hosted/headless deployments where operators need to manage rotation externally. --unsafe-no-api-tokenis only for trusted local development and should not be used when binding beyond localhost.- Put TLS in front of Tandem when exposing it on a network.
- Do not expose the service directly to the public internet without a reverse proxy.
If an agent or external service needs to create workflows, missions, or automations against this engine, start with Engine Authentication For Agents and Creating And Running Workflows And Missions.