> ## Documentation Index
> Fetch the complete documentation index at: https://www.plungeai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents & missions

> 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 …


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`](/mcp/tools) 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](/mcp/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 and the `type: harness` task (https://api.plungeai.com/docs#107-the-type-harness-task). Always pass `user_request`. Parameter types and limits are in the [Tool reference](/mcp/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](#73-choosing-a-model)) |
| `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](#74-conversations-and-personas)) |
| `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):

```bash
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](/mcp/tools#64-the-outcome-vocabulary)): `{"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-agent` is not a registry id.** It has no registry card (the registry answers 404, live-verified 2026-09-24), so `plungeai_execute_agent` refuses it as "No such agent". For a loop, use `plungeai_run_mission` ([7.6](#76-run-a-bounded-mission--plungeai_run_mission)), which runs on `one-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-20250929` matches `claude-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 as `anthropic:claude-haiku-4-5-20251001` is 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 `provider` wins 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. For `one-agent` that is `gemini-3.1-flash-lite` on `gemini` (`agents/agents/one-agent/call-config.ts`).

An unknown model returns `needs_input` with nothing executed:

```markdown
📝 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](/mcp/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):

```bash
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_id`** is passed to the agent task. A conversational agent keeps its transcript under that id: send the same `session_id` on the next call to continue. Every run's execution id also doubles as its conversation session id. That is how `plungeai_followup` and `plungeai_continue` pick a finished or paused run back up ([Runs, results & follow-ups](/mcp/runs-results)).
- **`persona`** selects a digital twin, one voice per call (`one-agent` call mode, `call-capabilities.ts`). Persona ids come from `plungeai_list_agents` `kind: "personas"`.
- **Pauses.** If the agent stops to ask a question or to get approval, the answer is `needs_input` (`⏸ AWAITING USER: …`) or `needs_approval` (`⏸ AWAITING USER APPROVAL: …`) with a `plungeai_continue` action ([6.6](/mcp/tools#66-the-trust-fence--needs-approval)).
- For a persistent chat with the platform assistant, use `plungeai_chat` ([Chat, memory & skills](/mcp/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](/mcp/protocol#46-toolscall-over-sse-progress-and-keepalive)).

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](/mcp/workflows)).

Failures are classified into the same outcome vocabulary as tools ([6.4](/mcp/tools#64-the-outcome-vocabulary)): 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](/mcp/tools#67-connected-accounts-and-your-own-keys)).

## 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`):

```yaml
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](#77-mission-bounds)) |
| `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](/mcp/runs-results)).

This runs a model loop with web tools (it costs credits and writes an execution; not run by the docs verifier):

```bash
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:

```markdown
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](/mcp/runs-results)). 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](/mcp/runs-results)). 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](/mcp/tools#66-the-trust-fence--needs-approval)) 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](/mcp/runs-results)).

**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](/mcp/workflows#810-cnl-essentials-for-ad-hoc-yaml); https://api.plungeai.com/docs#14-skills-plugins--capability-injection).

## 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 `memory` tool is needed for that.
- **Explicit writes mid-run** need `memory` in `allowed_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](/mcp/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](/mcp/runs-results)).
