Skip to content

Engine Authentication For Agents

Any agent, script, SDK client, or external service talking to tandem-engine over HTTP/SSE needs an engine token. tandem-engine serve enables token auth by default.

This page explains:

  • how the token is created
  • where an operator may store it
  • how agents should use it
  • how to avoid common auth mistakes

The short version

To start a local engine, run:

Terminal window
tandem-engine serve \
--hostname 127.0.0.1 \
--port 39731

If no explicit token is provided, the engine loads or creates the shared Tandem credential using the same keychain-first/file-fallback mechanism as desktop and TUI. Then authorize requests with either:

  • X-Agent-Token: <token>
  • X-Tandem-Token: <token>
  • Authorization: Bearer <token>
  • or an SDK client configured with token: "<token>"

How tokens are usually created

Engine-managed default token

By default, tandem-engine serve resolves its HTTP API token in this order:

  1. --api-token or TANDEM_API_TOKEN
  2. TANDEM_API_TOKEN_FILE
  3. the shared Tandem credential from keychain storage when available
  4. the shared token file when keychain storage is unavailable or empty
  5. a newly generated shared token if no shared token exists

This is the preferred path for local desktop, TUI, control-panel, and direct CLI use because all clients can share the same engine credential.

CLI-generated token

For explicit deployments, an operator can still generate a token manually:

Terminal window
tandem-engine token generate

That generated token is then passed into:

  • --api-token "<token>"
  • or TANDEM_API_TOKEN=<token>

Control panel-managed token

When using the packaged control panel flow:

Terminal window
tandem panel init

Tandem creates or updates the local .env and ensures an engine token is available for the panel.

Important environment variable:

  • TANDEM_CONTROL_PANEL_ENGINE_TOKEN

The panel uses that token to talk to the engine.

How agents become “agent-authored” at the API level

Every request is inspected for two signals:

  • x-tandem-agent-id (agent identity)
  • x-tandem-request-source

If x-tandem-request-source is control_panel, Tandem treats the request as human-owned even when an agent header is present.

That means today’s packaged control panel create path intentionally writes x-tandem-request-source: control_panel so workflows are treated as human-created unless the panel explicitly enables a test path.

Permission and capability checks for agent-created automations

When an agent is recognized, Tandem enforces extra safety checks before automations/v2 mutate:

  • agent identity must be present (x-tandem-agent-id)
  • creation quota and review requirements can apply
  • spend and recursion depth limits are enforced
  • requested capability escalation (for example creates_agents or modifies_grants) requires prior approval

Those checks still require a valid engine token. Agent mode does not remove authentication; it only changes who is recorded as the actor and which governance gate runs.

In the control panel, test mode uses an explicit developer flag that sends:

  • x-tandem-agent-test-mode: 1 (or true)
  • x-tandem-request-source: agent
  • x-tandem-agent-id: <agent-id>

This is currently a debugging/testing control and is not required for normal panel use.

Where an agent might get the token

Only use a token source that has been intentionally provided to the agent.

Common legitimate sources are:

  • an explicit environment variable such as TANDEM_API_TOKEN
  • a process launch command that includes --api-token
  • the control panel environment file containing TANDEM_CONTROL_PANEL_ENGINE_TOKEN
  • a secrets manager or operator-provided config layer
  • an SDK constructor that already has the token passed in

Agents should not assume they are allowed to scan arbitrary files or shell history for secrets unless the task explicitly permits that.

Advanced tokenless local mode

Operators can intentionally disable engine API token auth for trusted local development only:

Terminal window
tandem-engine serve --hostname 127.0.0.1 --port 39731 --unsafe-no-api-token

or:

Terminal window
TANDEM_UNSAFE_NO_API_TOKEN=1 tandem-engine serve --hostname 127.0.0.1 --port 39731

Agents should treat tokenless mode as exceptional. Do not recommend it for 0.0.0.0, reverse-proxied, hosted, tunneled, shared-machine, or public deployments.

How to authenticate HTTP calls

Header form used in the docs

Terminal window
curl -s http://127.0.0.1:39731/global/health \
-H "X-Agent-Token: tk_your_token"

Use the same header for mission, workflow, automation, and memory routes.

Example: mission builder preview

Terminal window
curl -sS -X POST http://127.0.0.1:39731/mission-builder/compile-preview \
-H "X-Agent-Token: tk_your_token" \
-H "content-type: application/json" \
-d @mission-blueprint.json

Example: workflow plan preview

Terminal window
curl -sS -X POST http://127.0.0.1:39731/workflow-plans/preview \
-H "X-Agent-Token: tk_your_token" \
-H "content-type: application/json" \
-d '{"prompt":"Create a staged automation for recurring intake and verification."}'

Example: V2 automation create

Terminal window
curl -sS -X POST http://127.0.0.1:39731/automations/v2 \
-H "X-Agent-Token: tk_your_token" \
-H "content-type: application/json" \
-d @automation.json

How to authenticate SDK calls

TypeScript

import { TandemClient } from "@frumu/tandem-client";
const client = new TandemClient({
baseUrl: "http://localhost:39731",
token: process.env.TANDEM_API_TOKEN || "",
});

Python

from tandem_client import AsyncTandemClient
import os
client = AsyncTandemClient(
base_url="http://localhost:39731",
token=os.environ["TANDEM_API_TOKEN"],
)

In the SDK path, the client handles the request header for you.

How an agent should decide what to call

After authentication is set up:

  • use workflow plans when intent must be compiled into an automation
  • use mission builder when you want a staged mission blueprint compiled and applied
  • use V2 automations when the DAG is already known
  • use missions runtime when you are updating mission work state

See Creating And Running Workflows And Missions for the path selection guide.

Safe patterns for agents

Good agent behavior:

  • read token from an explicitly provided environment variable or config source
  • send authenticated requests only to the intended engine URL
  • fail clearly when the token is missing
  • treat the token as a secret and avoid echoing it back in logs or artifacts

Bad agent behavior:

  • hardcoding a token into source files
  • writing the token into workflow artifacts or mission outputs
  • printing the token in terminal transcripts or chat replies
  • assuming a control panel .env is always the right credential source

How to verify the token works

Use a health check first:

Terminal window
curl -s http://127.0.0.1:39731/global/health \
-H "X-Agent-Token: tk_your_token"

If that succeeds, the same token should work for:

  • workflow plan routes
  • mission builder routes
  • automations routes
  • missions routes
  • memory routes

Common failure cases

401 or unauthorized

Usually means:

  • token is missing
  • wrong token
  • wrong header
  • wrong engine instance

Control panel works but your script does not

Usually means:

  • the panel has TANDEM_CONTROL_PANEL_ENGINE_TOKEN, but your script does not
  • your script is pointing at the wrong baseUrl

Local engine restart broke your script

Check whether:

  • the engine was restarted with a new token
  • TANDEM_API_TOKEN changed
  • your script cached an old token

For agents that need to create and run workflows or missions:

  1. verify engine URL
  2. obtain token from an explicitly provided secure source
  3. call /global/health
  4. choose the right authoring path
  5. preview before apply
  6. apply and schedule
  7. inspect runs with the same authenticated client

Import preview is read-only, but durable import, apply, and repair all mutate engine state, so they should use the same authenticated client path as the rest of the workflow lifecycle.

See also