MCP
Agents & missions
Source: orchestration/mcp-gateway/tools.ts (ExecuteAgentSchema, executeAgent, RunMissionSchema, plungeaiRunMission, fenceRefusal, renderRunResult), orchestration/mcp-gateway/registry-cards.ts (classifyCardAvailability, lowerToEngineTask), orchestration/mcp-gateway/execution.ts, orchestration/mcp-gateway/execution-do.ts, orchestration/mcp-gateway/leg-state.ts, orchestration/mcp-gateway/server.ts, core/core-base/provider-ids.ts, core/core-base/rate-card-client.ts, agents/agents/one-agent/call-config.ts + call-capabilities.ts + one-agent.ts + tools.ts + runtime.ts, orchestration/cnl-engine/executors.ts (executeHarnessTask); live registry reads 2026-09-24 and 2026-10-04 (one-agent).
Two tools run "one thing" without a workflow. plungeai_execute_agent runs one prompt-driven agent once, and you choose the model. plungeai_run_mission runs a bounded autonomous mission: a tool loop with a goal, a tool fence, an iteration cap and long-term memory. Structured tool-agents that take typed fields go through plungeai_execute_tool instead.
| You want | Tool | Runs as | Default mode |
|---|---|---|---|
| One answer from a model or persona | plungeai_execute_agent | One agent: task | sync only |
| One operation of a structured agent | plungeai_execute_tool (Tools) | One agent: task with typed fields | sync (mode: "async" optional) |
| A goal worked on over several steps with tools | plungeai_run_mission | One type: harness task | async (mode: "sync" optional) |
Base URL https://mcp.plungeai.com/v1. https://api.plungeai.com/v1/mcp is the same server. The One API equivalents are https://api.plungeai.com/docs#9-agents-plane (opens in a new tab) and the type: harness task (https://api.plungeai.com/docs#107-the-type-harness-task (opens in a new tab)). Always pass user_request. Parameter types and limits are in the Tool reference.
7.1 Run one prompt-driven agent — plungeai_execute_agent
The agent is one-agent, the platform's agent runtime. Here it runs in call mode: one model answer, plain or shaped by a persona. It is an active registry agent (live 2026-10-04). The legacy ids llm-agent and skill-agent still answer until the switch-over, but new calls name one-agent. A pre-built agent card (tag runtime:universal) is also accepted: it is a stored capability pack, not a deployed Worker, so it runs as a harness task on the universal runtime (lowerToEngineTask).
| Argument | Meaning |
|---|---|
agent | Registry agent id (required) |
prompt | What to ask (required) |
model, provider | Model choice, checked before the run (7.3) |
max_tokens (or maxTokens), temperature, top_p, reasoning_effort (low·medium·high·xhigh), thinking_level | Generation knobs, passed to the task as given. When both token spellings are sent, maxTokens wins |
persona | A persona (digital twin) id; one-agent answers in that voice. Find ids with plungeai_list_agents kind: "personas" |
session_id | Start or continue a conversational agent (7.4) |
streaming | Streaming is forced on by default. false opts this call out |
format | markdown (default) or json |
Try asking: "Ask one-agent in one sentence what a Cloudflare Durable Object is." It runs a single agent once, with no workflow needed.
This runs a model (it costs credits and writes an execution; not run by the docs verifier):
curl -s https://mcp.plungeai.com/v1 \
-H "Authorization: Bearer $PLUNGE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_execute_agent","arguments":{"user_request":"Ask one-agent in one sentence what a Cloudflare Durable Object is.","agent":"one-agent","prompt":"In one sentence: what is a Cloudflare Durable Object?","max_tokens":120}}}'On success the result text is the agent's answer plus the execution footer (--- / execution: `<id>` — use this id for plungeai_get_result / plungeai_followup on this run.). structuredContent is the outcome envelope (6.4): {"status":"ok","summary":"Agent completed.","result":"…","execution_id":"…"}. The run shows in your history and in Studio's sidebar under the agent's id, titled with your prompt.
7.2 Before it runs: the agent fence
The card is checked before any execution exists (classifyCardAvailability). A denial is not a run, so no failed row lands in your history:
| Case | Outcome | Summary |
|---|---|---|
| No card with that id | unavailable | "No such agent: <id> — that id does not exist in the registry (agent names cannot be guessed or carried over from other platforms). Discover callable agents with plungeai_list_agents — describe the capability in natural language (its search is semantic) and retry with an id from the results." |
Card exists, not status:active | unavailable | "Not permitted: <id> is not status:active, and only active agents are callable over MCP. Discover callable agents with plungeai_list_agents …" |
Both answers include up to three live alternatives (use_alternative). If the registry does not answer at all, the call proceeds (fail-open), and a truly missing agent then fails in the engine as "registered but not deployed" (unavailable).
The legacy loop id
harness-agentis not a registry id. It has no registry card (the registry answers 404, live-verified 2026-09-24), soplungeai_execute_agentrefuses it as "No such agent". For a loop, useplungeai_run_mission(7.6), which runs onone-agent.
7.3 Choosing a model
Try asking: "Ask one-agent, using claude-haiku-4-5, to summarize this paragraph." You can pick the model for a single-agent run. The model name is checked against the live catalog before anything runs. A name that doesn't exist is refused at once with suggestions; it never hangs.
How the check works (executeAgent):
- The catalog is the platform rate card's model catalog (
model_catalog, read from the rate-card snapshot). - A dated variant matches its catalog row by prefix:
claude-sonnet-4-5-20250929matchesclaude-sonnet-4-5. - Pass the model id as the catalog spells it, normally the bare id (
claude-haiku-4-5,gemini-3.1-flash-lite). A registry model-card id such asanthropic:claude-haiku-4-5-20251001is not a catalog id and is refused. - A known model also sets the task's provider from its catalog row, so a
claude-*model reaches Anthropic even when the agent's default provider is another one. - An explicit
providerwins over the catalog. It is lower-cased and mapped to the runtime id:google→gemini,google-vertex→vertex,x-ai→xai(toRuntimeProvider). - If the catalog itself cannot be read, the check is skipped and the run proceeds (fail-open).
- With no
model, the agent uses its default. Forone-agentthat isgemini-3.1-flash-liteongemini(agents/agents/one-agent/call-config.ts).
An unknown model returns needs_input with nothing executed:
📝 NEEDS INPUT — `one-agent`
Unknown model `claude-haiku-9` — it is not in the platform model catalog, and dispatching it would only fail after a long streaming timeout. Nothing was executed. Omit `model` to use the agent's default, or pick a catalog model: `<up to five catalog models whose id contains "claude">` (<provider>), ….
_This is structured guidance, not a crash — do not retry the identical call. Follow the remediation, or relay it to the user._The suggestions are catalog models whose id contains the first token of your name (the part before the first - or .). If none match, the answer suggests claude-sonnet-4-5 or gemini-3.1-flash-lite as examples.
"What models are available?" The client answers with plungeai_list_agents kind: "models" (Discovery). Model cards are named provider:model-id. Pass only the part after the colon as model. The registry's model cards and the rate card's catalog are separate lists, so a model shown there can still be refused here; the refusal then lists catalog models to pick from.
This runs a model (it costs credits; not run by the docs verifier):
curl -s https://mcp.plungeai.com/v1 \
-H "Authorization: Bearer $PLUNGE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_execute_agent","arguments":{"user_request":"Ask one-agent, using claude-haiku-4-5, to summarize this paragraph.","agent":"one-agent","model":"claude-haiku-4-5","prompt":"Summarize in two sentences: <paragraph>","temperature":0.2}}}'7.4 Conversations and personas
session_idis passed to the agent task. A conversational agent keeps its transcript under that id: send the samesession_idon the next call to continue. Every run's execution id also doubles as its conversation session id. That is howplungeai_followupandplungeai_continuepick a finished or paused run back up (Runs, results & follow-ups).personaselects a digital twin, one voice per call (one-agentcall mode,call-capabilities.ts). Persona ids come fromplungeai_list_agentskind: "personas".- Pauses. If the agent stops to ask a question or to get approval, the answer is
needs_input(⏸ AWAITING USER: …) orneeds_approval(⏸ AWAITING USER APPROVAL: …) with aplungeai_continueaction (6.6). - For a persistent chat with the platform assistant, use
plungeai_chat(Chat, memory & skills).
7.5 Outcomes and long answers
plungeai_execute_agent has no async mode. The call stays open until the agent answers. While it waits, the server streams progress: token frames (✍️ Writing (N chars) — …), the engine's heartbeat (⚙️ one-agent still working — 45s elapsed…), and a keepalive every 15 seconds (⏳ Working — Ns elapsed). Whether your client shows them is up to the client (4.6).
Claude Desktop cuts a single tool call at about 4 minutes. For anything that long, use plungeai_run_mission (async by default), or put the agent in a one-task workflow and run it with plungeai_execute_workflow mode: "async" (Workflows).
Failures are classified into the same outcome vocabulary as tools (6.4): a run-time 401 becomes needs_connection, a timeout becomes error with a retry-async hint, and so on. The status is stamped on the execution's outcome column. plungeai_execute_agent does no credential pre-flight. If an agent needs your connected account, check it first with plungeai_get_tool_contract (6.7).
7.6 Run a bounded mission — plungeai_run_mission
A mission bounds what an agent may do for one goal: a purpose, a fenced tool set, an iteration cap, optional success criteria, a persona and skills. plungeai_run_mission wraps your arguments into a one-task CNL workflow and runs it on one-agent in loop mode, a real ReAct tool loop. This is the task it builds (plungeaiRunMission):
workflow:
name: mcp-mission
tasks:
- type: harness
id: mission
agent: one-agent # or the agent you pass
goal: <goal>
mission:
mission: <mission, or the default purpose below>
allowed_tools: [web_search, web_fetch, task_complete] # unless you pass allowed_tools
max_iterations: 8 # unless you pass max_iterations
success_criteria: [...] # only if you pass them
persona: <id> # only if you pass it
skills: [...] # only if you pass them| Argument | Default | Meaning |
|---|---|---|
goal | required | The per-run task, in plain language |
agent | one-agent | The loop runtime that runs the mission. The gateway always sends it: a type: harness task with no agent: line still falls to the legacy harness-agent in the engine until the switch-over. A runtime you name passes the same active-only fence as plungeai_execute_agent |
mission | "You are a capable autonomous agent. Achieve the goal thoroughly and cite sources." | The standing purpose, which becomes the system-prompt frame |
allowed_tools | [web_search, web_fetch, task_complete] | The tool fence. Only these reach the model (7.7) |
max_iterations | 8 (max 50) | The loop's turn cap |
success_criteria | none | Statements the agent checks itself against. They are added to the system prompt as "the task is done only when all are met" |
persona | none | One persona id, one voice for the run |
skills | none | Skill ids (up to 20), injected into the run |
mode | async | sync waits for the result, with live progress |
The mission shows in your history as mcp-mission, titled with the goal. Every run also carries user_context (your time zone and approximate place, taken from the request's network location), which the agent uses for local time and as the default time zone for a schedule.
Try asking: "Ask One Agent a quick question: what's notable about Sun Valley, Idaho?" That is a bounded, one-shot mission, fast and reliable. Keep goals like this short and specific. An open-ended "research everything about X" goal can run long enough that you check on it later (Runs, results & follow-ups).
This runs a model loop with web tools (it costs credits and writes an execution; not run by the docs verifier):
curl -s https://mcp.plungeai.com/v1 \
-H "Authorization: Bearer $PLUNGE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_run_mission","arguments":{"user_request":"Ask One Agent a quick question: what is notable about Sun Valley, Idaho?","goal":"In five bullet points: what is notable about Sun Valley, Idaho? Cite a source URL for each.","max_iterations":6,"success_criteria":["five bullets","every bullet has a source URL"]}}}'The async answer comes back at once. It is an ok outcome carrying the execution id:
Started mission `<execution id>` (async). Poll plungeai_get_workflow_status with this id, then fetch output with plungeai_get_result once completed. The agent recalls and writes long-term memory automatically. If the status reports ⏸ AWAITING USER APPROVAL or AWAITING USER, relay it to the user and continue with plungeai_continue.
---
execution: `<execution id>` — use this id for plungeai_get_result / plungeai_followup on this run.Then poll plungeai_get_workflow_status and read plungeai_get_result (Runs, results & follow-ups). With mode: "sync" the call waits and returns Mission completed. with the result, or a classified outcome (the mission's agent, one-agent unless you passed agent).
7.7 Mission bounds
The tool fence. Only the tools in allowed_tools reach the model. The one-agent catalog has 27 tools (ALL_TOOLS, agents/agents/one-agent/tools.ts): read_file, write_file, edit_file, list_files, search_files, delete_file, web_search, web_fetch, load_skill, memory, knowledge, skill_manage, recall, recall_history, delegate, schedule, message_bot, browser, local_agent, registry_search, registry_lookup, call_agent, invoke_workflow, run_python, ask_user, platform_action, task_complete. The concierge spellings find_agent, agent_card and run_agent are accepted as aliases of registry_search, registry_lookup and call_agent. Include task_complete so the agent can finish.
The iteration cap. max_iterations (the legacy alias of the harness max_turns) stops the loop. An async mission that hits the cap before task_complete is reported incomplete by plungeai_get_workflow_status, not completed, and its partial output is still stored and retrievable (Runs, results & follow-ups). In mode: "sync" the answer reads Mission completed. even then: the sync path stamps the execution's outcome ok after the run, which replaces the incomplete mark (renderRunResult in tools.ts). Use async when you need to tell a finished mission from one that ran out of turns.
Unattended posture. An inline mission runs on one-agent unless agent names another runtime; one-agent's host profile is unattended (ONE in one-agent.ts). If you allow call_agent, the loop's agent fence refuses outward, irreversible operations (the floor list in 6.6) and agents in the payment and blockchain categories, unless a mission's allowed_agents names them (core/core-base/call-agent.ts). plungeai_run_mission has no allowed_agents argument, so a mission started here cannot call payment agents.
Questions. With ask_user in allowed_tools, the mission can pause with a question. plungeai_get_workflow_status then reports it as continuation, and you answer with plungeai_continue (Runs, results & follow-ups).
More mission fields. Experts, backgrounds, plugins, MCP servers, effort presets, spend caps and permissions are mission fields in CNL, but plungeai_run_mission does not expose them. For those, write a type: harness task yourself and run it with plungeai_execute_workflow (8.10; https://api.plungeai.com/docs#14-skills-plugins--capability-injection (opens in a new tab)).
7.8 Memory
A mission runs with your long-term memory, which is scoped to you:
- Recall at the start. A top-level mission (not a fan-out member, not a delegated sub-mission) gets a frozen snapshot of your memory prepended to its system prompt. It is built once per run and is best-effort: memory being down never blocks the run (
runtime.ts,executors.ts). - Write-back at the end. After the run, a background review curates durable facts from it into your memory. No
memorytool is needed for that. - Explicit writes mid-run need
memoryinallowed_tools.
To read or write memory yourself ("What do you remember about Circle's acquisitions?", "Remember that our fiscal year ends in June."), use plungeai_memory (Chat, memory & skills).
7.9 Async missions: the Ten-Minute Relay
Async missions (and every other mode: "async" run) are held by a per-run Durable Object, not by your tool call (execution-do.ts, leg-state.ts):
- The run executes in legs. A harness leg hands over at the first turn boundary after 10 minutes, and the next leg resumes from the stored checkpoints.
- A leg that is killed (deploy, host restart, the 15-minute alarm cap) is re-entered by a watchdog alarm set 12 minutes after the leg started, and repeats at most the turn that was in flight.
- Three killed legs in a row with no checkpoint fail the run: "Run was killed 3 times in a row without yielding a checkpoint. … Split the work or shorten the step, then re-run to retry."
- If the dispatch itself fails, the execution is marked failed with
Async dispatch failed: ….
Because the Durable Object holds the run, it survives your client disconnecting. There is no live progress feed on async runs. Poll plungeai_get_workflow_status, which also self-heals a row whose run finished but was never closed (Runs, results & follow-ups).