MCP Automated Agents
Set up scheduled agents that can use MCP connector tools with explicit per-agent tool allowlists.
Tandem-specific documentation is exposed through the built-in tandem-mcp
docs server, so agents should ask that MCP for platform guidance instead of
relying on embedded startup knowledge.
If you are building a governed recursive agent that has to inspect Tandem, discover a gap, request approval, author an automation, and publish a report, start with Self-Operator Playbook.
If another LLM or agent is generating the workflow or mission definition itself, use Prompting Workflows And Missions to keep stage prompts, handoffs, and recurring mission structure strong.
For the operational path after prompting, use Creating And Running Workflows And Missions. For engine tokens and authenticated HTTP or SDK calls, use Engine Authentication For Agents.
For a compact, agent-facing checklist that covers MCP discovery, clarifying questions, workflow import, apply, repair, and provenance, start with Agent Workflow Operating Manual.
If the engine is not installed or authenticated yet, the same manual also covers first-time setup. That path points agents to the install, control panel, first-run, and engine-authentication docs before they try to compile or run workflows.
If you want the shortest end-to-end checklist for an agent, start with Agent Workflow And Mission Quickstart.
If you want a showcase payload that demonstrates tight tool isolation, skip behavior, or approval boundaries, use Tandem Wow Demo Playbook.
For provider and model routing choices, use Choosing Providers And Models For Agents.
What You Get
- MCP connector lifecycle: add, enable/disable, connect, refresh
- Auto MCP tool discovery on connect (
initialize+tools/list) - Namespaced MCP tools in the global tool registry (for example
mcp.arcade.search) mcp_listfor a structured inventory of configured and connected MCP servers/toolsmcp_list_catalogfor the catalog overlay that distinguishes connected, cataloged, disabled, and uncataloged serversmcp_request_capabilityfor filing a capability gap into the approval queue- Routine-level
allowed_toolspolicy for scheduled bots - Agent Automation visibility for connector status and scheduled runs
Strict knowledge-bot channels
If an external chat channel is acting as a knowledge bot instead of a general assistant, pair the KB MCP allowlist with the channel setting:
{ "strict_kb_grounding": true}That combination keeps the same MCP tool names and request flow, but the final channel answer is rewritten from retrieved KB excerpts only. When the KB does not support the answer, Tandem returns I do not see that in the connected knowledgebase. instead of blending in general model knowledge.
How Tool Discovery Works
Tandem does not expose a separate “search the MCP registry by keyword” API. The public discovery path is:
- Use
mcp_listto get the engine’s current MCP inventory snapshot. - Treat that as the low-context discovery step before loading any larger tool lists into the prompt.
- If you need to distinguish cataloged versus uncataloged capabilities, call
mcp_list_catalog. - Connect the MCP server through the normal operator path.
- List discovered tools with
GET /mcp/tools. - List all engine tool IDs with
GET /tool/ids. - Filter the returned tool list locally by prefix, server name, or tool name.
- Execute the chosen tool directly through the engine or via
mcp_debugwhen you need to call a remote MCP server by URL.
If the required MCP server or tool is missing from mcp_list, do not guess. If mcp_list_catalog shows it as cataloged but not connected, ask a human to connect it. If it is uncataloged, file a capability request instead of switching to a different tool.
If the workflow requires an external tool the agent cannot see in mcp_list, stop and explain whether the server is cataloged, disconnected, or uncataloged before continuing.
The engine does have internal semantic tool retrieval for prompt-time tool selection, but that ranking path is separate from mcp_list and is not a public registry search endpoint.
The Context Bloat Solution: Strict Tool Isolation
Most AI agent frameworks attempt to solve the token limit problem of massive MCP servers (e.g., Arcade offering hundreds of tools) by using “Tool RAG” (dynamically retrieving tool schemas) or trying to truncate contexts on the fly. This is notoriously error-prone and wastes expensive tokens.
Tandem approaches this architecturally, not algorithmically. By enforcing strict allowed_tools policies at the Rust Engine parsing layer, Tandem categorically strips unrequested tools from the registry before serialization. A specialized worker agent only ever wastes tokens reading the schemas of the exact tools it has been explicitly authorized to use.
1) Configure MCP Connector
Add an MCP server:
curl -sS -X POST http://127.0.0.1:39731/mcp \ -H "content-type: application/json" \ -d '{ "name": "arcade", "transport": "https://your-mcp-server.example/mcp", "enabled": true, "headers": { "Authorization": "Bearer YOUR_TOKEN" } }'Add an MCP server with a server-level tool allowlist:
curl -sS -X POST http://127.0.0.1:39731/mcp \ -H "content-type: application/json" \ -d '{ "name": "notion", "transport": "https://your-mcp-server.example/mcp", "enabled": true, "allowed_tools": ["search", "get_page", "list_databases"] }'Connect it (this performs discovery and caches tools):
curl -sS -X POST http://127.0.0.1:39731/mcp/arcade/connectRefresh cached tools later:
curl -sS -X POST http://127.0.0.1:39731/mcp/arcade/refreshList connector tools:
curl -sS http://127.0.0.1:39731/mcp/toolsList all tool IDs (built-ins + MCP):
curl -sS http://127.0.0.1:39731/tool/idsUpdate an existing MCP server to narrow or clear its allowlist:
curl -sS -X PATCH http://127.0.0.1:39731/mcp/notion \ -H "content-type: application/json" \ -d '{ "allowed_tools": ["search", "get_page"] }'
curl -sS -X PATCH http://127.0.0.1:39731/mcp/notion \ -H "content-type: application/json" \ -d '{ "clear_allowed_tools": true }'Server-Level MCP Tool Allowlists
- Use MCP server
allowed_toolswhen a connector should expose only a subset of its discovered tools. - The desktop control panel now surfaces those discovered tools as checkboxes after a server connects.
GET /mcp/tools,mcp_list, and the runtime MCP registry only show tools that survive that server-level policy.clear_allowed_tools: truerestores the default behavior of exposing every discovered tool for that server.
Tool names inside allowed_tools are the remote MCP tool names for that server, not the fully qualified Tandem IDs. For example, if the Tandem tool ID is mcp.notion.search, the MCP server allowlist entry is search.
Knowledgebase MCP Grounding Metadata
MCP servers that should be treated as authoritative knowledge sources can opt into KB-first grounding.
Use either field on POST /mcp or PATCH /mcp/{name}:
{ "purpose": "knowledgebase", "grounding_required": true}The hosted Tandem KB MCP named kb is marked this way automatically. External KB MCPs should be marked explicitly.
When a channel/session enables an explicitly grounded KB MCP with an allowlist such as mcp.kb.*, the engine:
- injects a
knowledgebase_grounding_policysystem block, - reshapes the prompt request to
tool_mode: "required"with only the enabled KB MCP tool patterns, - requires a KB MCP tool result before the model can answer from evidence,
- emits
kb.grounding.*events for observability.
mcp_list is useful before the run for discovering KB tool names, but it is not sufficient evidence by itself. During a grounded channel answer, the agent should call an actual KB read/search tool before answering.
Provider Notes: Arcade
Arcade MCP Gateways are ideal when you want to curate a smaller, safer tool set for a specific bot.
Recommended flow:
- In Arcade, create an MCP Gateway for your bot mission.
- Select only the tools needed for that mission (avoid sending dozens of tools to one agent).
- Use the gateway URL in Tandem as the MCP
transport. - If using Arcade headers auth mode, pass required headers in Tandem (
Authorization, and user ID header if your setup requires it). - Keep
Arcade-User-IDstable across requests/sessions; changing it often triggers repeated authorization challenges.
Then in Tandem:
curl -sS -X POST http://127.0.0.1:39731/mcp \ -H "content-type: application/json" \ -d '{ "name": "arcade", "transport": "https://api.arcade.dev/mcp/YOUR-GATEWAY-SLUG", "enabled": true, "headers": { "Authorization": "Bearer YOUR_ARCADE_KEY" } }'curl -sS -X POST http://127.0.0.1:39731/mcp/arcade/connectMCP auth + refresh behavior
- Auth-gated MCP tools emit
mcp.auth.requiredwith an authorization URL. - If the same challenged tool is retried immediately, Tandem emits
mcp.auth.pendingand short-circuits repeated calls for about 15 seconds. - During this window, only the challenged tool is blocked; other MCP tools remain available.
- Complete authorization, then retry the tool call (engine restart not required).
- After successful authorization, one cooldown cycle may still apply before the next probe call succeeds.
- On connect/refresh failures, Tandem now clears stale MCP cache/session state before reporting errors to avoid phantom tool availability.
Provider Notes: Composio
For Composio MCP URLs, make sure your project’s MCP URL security requirements are satisfied.
Important dates from Composio changelog:
- Since December 15, 2025, new projects require
x-api-keyon MCP URL requests. - After April 15, 2026, requests without
x-api-keyare rejected.
Then in Tandem:
curl -sS -X POST http://127.0.0.1:39731/mcp \ -H "content-type: application/json" \ -d '{ "name": "composio", "transport": "https://mcp.composio.dev/YOUR_MCP_PATH", "enabled": true, "headers": { "x-api-key": "YOUR_COMPOSIO_API_KEY" } }'curl -sS -X POST http://127.0.0.1:39731/mcp/composio/connect2) Create a Scheduled Agent With Tool Allowlist
What The Bot Actually Does On Each Run
Each scheduled run executes this loop:
- Load automation definition: mission, mode, tool policy, model policy, outputs.
- Build run prompt from objective and success criteria.
- Enforce policy gates (
allowed_tools, approval flags, external side-effect settings). - Execute and stream run events over SSE.
- Persist run status/history and attach output artifacts.
Mission quality is the primary control lever. If the mission objective is vague, run behavior will be vague.
Create an automation that only allows selected tools (routines/* remains compatible):
curl -sS -X POST http://127.0.0.1:39731/automations \ -H "content-type: application/json" \ -d '{ "routine_id": "daily-mcp-research", "name": "Daily MCP Research", "schedule": { "interval_seconds": { "seconds": 86400 } }, "entrypoint": "mission.default", "allowed_tools": ["mcp.arcade.search", "read"], "output_targets": ["file://reports/daily-mcp-research.json"], "requires_approval": true, "external_integrations_allowed": true }'Trigger immediately:
curl -sS -X POST http://127.0.0.1:39731/automations/daily-mcp-research/run_now \ -H "content-type: application/json" \ -d '{}'Check run records:
curl -sS "http://127.0.0.1:39731/automations/runs?routine_id=daily-mcp-research&limit=10"Each run record includes allowed_tools so you can verify tool scope at execution time.
When a routine or automation uses exact MCP tool IDs, Tandem intersects those IDs with the server-level MCP allowlist before exposing tools to the run.
V2 Path (Recommended): Persistent Multi-Agent DAG Automation
For per-agent model routing and DAG checkpoints, use /automations/v2:
curl -sS -X POST http://127.0.0.1:39731/automations/v2 \ -H "content-type: application/json" \ -d '{ "name": "daily-mcp-research-v2", "status": "active", "schedule": { "type": "interval", "interval_seconds": 86400, "timezone": "UTC", "misfire_policy": "run_once" }, "agents": [ { "agent_id": "research", "display_name": "Research", "model_policy": { "default_model": { "provider_id": "openrouter", "model_id": "openai/gpt-4o-mini" } }, "tool_policy": { "allowlist": ["read", "websearch", "mcp.composio.github_issues_list"], "denylist": [] }, "mcp_policy": { "allowed_servers": ["composio"], "allowed_tools": ["mcp.composio.github_issues_list"] } }, { "agent_id": "writer", "display_name": "Writer", "model_policy": { "default_model": { "provider_id": "openrouter", "model_id": "anthropic/claude-3.5-sonnet" } }, "tool_policy": { "allowlist": ["read", "write", "edit"], "denylist": [] }, "mcp_policy": { "allowed_servers": [], "allowed_tools": [] } } ], "flow": { "nodes": [ { "node_id": "scan", "agent_id": "research", "objective": "Find relevant MCP updates." }, { "node_id": "draft", "agent_id": "writer", "objective": "Draft daily summary.", "depends_on": ["scan"] } ] } }'Use mcp_policy.allowed_tools when one agent should only see exact MCP tools from an allowed server. This is especially useful for public bots and automation workflows where a connector is enabled, but only a few actions should ever reach the model context.
Run immediately:
curl -sS -X POST http://127.0.0.1:39731/automations/v2/daily-mcp-research-v2/run_now \ -H "content-type: application/json" \ -d '{}'Observe runs:
curl -sS "http://127.0.0.1:39731/automations/v2/daily-mcp-research-v2/runs?limit=10"Cost tracking in Control Panel
Set this env var on the engine to estimate token spend for automation runs:
export TANDEM_TOKEN_COST_PER_1K_USD=0.30Then open Control Panel Dashboard and use Automations + Cost to monitor:
- Tokens (24h / 7d)
- Estimated cost (24h / 7d)
- Highest-cost automations/routines
2.5) Which Tools Should You Start With?
For autonomous bots, start narrow and expand only when runs are stable.
Recommended Starter Bundle (Most Teams)
Use one read channel + one write channel + one source-of-truth system:
mcp.<provider>.search/list/gettools for discovery and context- One ticketing/project write tool (create/update comment/status)
- One messaging output tool (post update to Slack/Teams/Discord)
Good First Mission Patterns
- Triage bot:
- read inbox/issues
- classify
- post summary + suggested next steps
- Status reporter:
- read project state + CI/test signals
- publish daily report artifact + message channel post
- Change assistant (with approval):
- prepare updates/comments/PR drafts
- require approval for any external side-effect tools
Avoid Early
- Huge tool surfaces in one agent (harder model routing, more mistakes)
- Destructive tools without approval gates
- Multi-system write actions in the same first rollout
Practical Rule
Start with 3-8 allowed tools max per routine. Increase only after you get predictable run history.
2.6) Ready-Made Routine Templates (Copy/Paste)
Replace MCP tool IDs with your connector namespaces (for example mcp.arcade.search or mcp.composio.github_issues_list).
Template A: Daily Research Digest
curl -sS -X POST http://127.0.0.1:39731/routines \ -H "content-type: application/json" \ -d '{ "routine_id": "daily-research-digest", "name": "Daily Research Digest", "schedule": { "interval_seconds": { "seconds": 86400 } }, "entrypoint": "mission.default", "allowed_tools": [ "websearch", "webfetch", "read", "write", "mcp.arcade.search" ], "output_targets": ["file://reports/daily-research-digest.md"], "requires_approval": true, "external_integrations_allowed": true }'Template B: 15-Min Issue Triage
curl -sS -X POST http://127.0.0.1:39731/routines \ -H "content-type: application/json" \ -d '{ "routine_id": "issue-triage-bot", "name": "Issue Triage Bot", "schedule": { "interval_seconds": { "seconds": 900 } }, "entrypoint": "mission.default", "allowed_tools": [ "read", "write", "websearch", "webfetch", "mcp.composio.github_issues_list", "mcp.composio.github_issue_comment_create" ], "output_targets": ["file://reports/issue-triage.json"], "requires_approval": true, "external_integrations_allowed": true }'Template C: Hourly Release Reporter (Unattended)
curl -sS -X POST http://127.0.0.1:39731/routines \ -H "content-type: application/json" \ -d '{ "routine_id": "hourly-release-reporter", "name": "Hourly Release Reporter", "schedule": { "interval_seconds": { "seconds": 3600 } }, "entrypoint": "mission.default", "allowed_tools": [ "read", "websearch", "webfetch", "write", "mcp.arcade.search" ], "output_targets": ["file://reports/release-status.md"], "requires_approval": false, "external_integrations_allowed": true }'3) Desktop Flow (Agent Automation)
From desktop:
- Open
Extensions -> MCPand add/connect connector servers. - Open
Agent Automation(robot icon in the left nav) and useAutomated Bots. - Create a scheduled bot:
- choose interval (seconds)
- set a clear mission objective (required)
- optionally use Mission Workshop to generate objective + success criteria
- choose entrypoint (for example
mcp.arcade.search) - choose
allowed_toolsfrom MCP and built-ins
- Use
Configured Routinesactions to pause/resume routines. - Use
Scheduled Botsrun actions (Approve,Deny,Pause,Resume) for gated runs. - In
Scheduled Bots, inspect tool scope shown on each run card. - Watch the per-run event rail chips (
Plan,Do,Verify,Approval,Blocked,Failed) for live execution state. - Click
Detailson a run to inspect latest event type/note, timestamps, output targets, and artifacts. - Use run filters (
All,Pending,Blocked,Failed) to quickly triage execution issues.
Mission Workshop (Desktop)
Agent Automation -> Automated Bots -> Mission Workshop provides a chat-style drafting helper.
Use it to:
- describe what the bot should achieve in plain language
- generate a mission objective + success criteria
- apply the draft into the automation form before saving
The resulting mission is stored in routine args (prompt + success_criteria) and is what the run executes.
Mission Modes (Desktop + Headless)
standalone: one agent executes the mission directly.orchestrated: run prompt uses aPlan -> Do -> Verify -> Notifycontract and expects orchestrator-style behavior.
For orchestrated mode with stricter tool discipline, set:
mode: "orchestrated"orchestrator_only_tool_calls: true
Desktop mapping:
- In
Agent Automation, chooseMode = orchestrated - Enable
Orchestrator-only tool callsin the form
Model Provider + Model Selection (Desktop + Headless)
Each automation can now carry a model routing policy in args.model_policy:
default_model: used by standalone runs and as fallback for orchestrated runsrole_models.orchestrator: preferred model for orchestrated mode todayrole_models.planner|worker|verifier|notifier: stored now for upcoming deeper role routing
Desktop mapping:
- In
Agent Automation, useModel Routing - Pick provider/model directly or apply a preset
Example policy payload:
{ "model_policy": { "default_model": { "provider_id": "openrouter", "model_id": "openai/gpt-4.1-mini" }, "role_models": { "orchestrator": { "provider_id": "openrouter", "model_id": "anthropic/claude-3.5-sonnet" }, "verifier": { "provider_id": "openrouter", "model_id": "anthropic/claude-3.5-sonnet" } } }}Recommended starting examples:
- OpenRouter (balanced):
openrouter/openai/gpt-4.1-mini - OpenRouter (orchestrator+verifier):
openrouter/anthropic/claude-3.5-sonnet - OpenCode Zen fast profile:
opencode_zen/zen/fast - OpenCode Zen quality profile:
opencode_zen/zen/pro
To clear model policy on a patch/update, send an empty object:
{ "model_policy": {}}4) SSE Visibility
Watch automation stream:
curl -N http://127.0.0.1:39731/automations/eventsRelevant events include:
mcp.server.connectedmcp.tools.updatedrun.startedapproval.requiredrun.failed
5) End-to-End Headless Example Scripts
Use the included scripts:
examples/headless/mcp_tools_allowlist/flow.shexamples/headless/mcp_tools_allowlist/flow.ps1
They automate:
- MCP add/connect
- MCP + global tool listing
- Automation creation with
allowed_tools+output_targets - Run trigger + run record/artifact verification
6) Headless “Just Run” Setup
Use this when you want unattended operation without opening desktop.
A) Start engine headless
cargo run -p tandem-ai --bin tandem-engine -- serve --host 127.0.0.1 --port 39731B) Register MCP and automation once
Use Sections 1 and 2 above (or run the included script):
examples/headless/mcp_tools_allowlist/flow.shexamples/headless/mcp_tools_allowlist/flow.ps1
C) Make it autonomous
For no human intervention:
- set
requires_approval: falseon automations you trust - keep
allowed_toolsexplicit and small - keep
output_targetsconfigured so every run leaves artifacts
D) Observe continuously
curl -N http://127.0.0.1:39731/automations/eventsWatch for:
run.startedrun.failedapproval.requiredmcp.tools.updated
E) Production tip
Run tandem-engine serve under a process supervisor (systemd, PM2, container orchestrator, or Windows Task Scheduler/service wrapper) so it auto-restarts after reboots/crashes.
F) Benchmark mission/automation cold start
If someone asks “how fast is mission startup?” benchmark exactly this:
- Engine launch to
ready=true run_nowAPI ack latency- Time until run record is visible
Scripts:
examples/headless/mcp_tools_allowlist/benchmark_cold_start.ps1examples/headless/mcp_tools_allowlist/benchmark_cold_start.sh
PowerShell:
cd examples/headless/mcp_tools_allowlist$env:BENCH_RUNS = "10".\benchmark_cold_start.ps1Bash:
cd examples/headless/mcp_tools_allowlistchmod +x benchmark_cold_start.shBENCH_RUNS=10 ./benchmark_cold_start.shBoth scripts output p50/p95 summary and write per-trial data to:
examples/headless/mcp_tools_allowlist/cold_start_results.json
7) App Testing Checklist (Release Readiness)
Use this checklist before shipping:
- MCP connectors:
- add, enable/disable, connect/disconnect, refresh
- verify
mcp.tools.updatedevents appear
- Automation creation:
- create standalone + orchestrated bots
- verify interval is interpreted as seconds
- verify
webfetchappears in allowed tools (andwebfetch_htmlwhen raw HTML fallback is needed)
- Model routing:
- apply a preset (OpenRouter/OpenCode Zen)
- verify selected provider/model appears in routine/run cards
- verify run emits model selection event (
routine.run.model_selected)
- Approval flow:
- verify pending approval run can be approved/denied
- verify blocked/failed filters surface problem runs
- Run details:
- verify timeline chips, timestamps, reason text, outputs, artifacts
- Headless:
- run
examples/headless/mcp_tools_allowlist/flow.shor.ps1 - confirm runs execute and artifacts are produced without desktop UI
- run
Safety Notes
- Keep connector secrets in headers/env, not logs.
- Default external side-effects are policy-gated (
requires_approvalandexternal_integrations_allowed). - Prefer explicit
allowed_toolsfor production automated agents.