> ## 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.

# Runs, results & follow-ups

> Every execution tool (plungeai_execute_workflow, plungeai_execute_agent, plungeai_execute_tool, plungeai_run_mission, plungeai_learn) creates an execution and answers with its execution id. This chapter covers what you do with that id afterwards: read the output, check the status, browse your …


Source: `orchestration/mcp-gateway/tools.ts` (`getResult`, `getWorkflowStatus`, `plungeaiExecutions`, `plungeaiFollowup`, `plungeaiContinue`), `orchestration/mcp-gateway/ops/executions.ts` (`reconcileRunningRow`), `orchestration/mcp-gateway/conversation.ts`, `orchestration/mcp-gateway/execution.ts` (`loadStoredResult`, `STALE_RUN_SECONDS`), `orchestration/mcp-gateway/leg-state.ts`, `orchestration/mcp-gateway/tool-outcome.ts` (`pauseOutcome`, `renderAs`), `orchestration/mcp-gateway/server.ts` (`TOOL_DEFS`, `StatusOutputSchema`, server instructions).

Every execution tool (`plungeai_execute_workflow`, `plungeai_execute_agent`, `plungeai_execute_tool`, `plungeai_run_mission`, `plungeai_learn`) creates an execution and answers with its **execution id**. This chapter covers what you do with that id afterwards: read the output, check the status, browse your history, ask a follow-up, and answer a run that paused for you. The examples use `https://mcp.plungeai.com/v1`. `https://api.plungeai.com/v1/mcp` is the same server.

| Tool | What it does | Read-only | Runs a model |
|---|---|---|---|
| `plungeai_get_result` | the output of one execution, or of one task in it | yes | no |
| `plungeai_get_workflow_status` | status, error, duration, and whether the run is paused for you | yes | no |
| `plungeai_executions` | your run history; also output, thread, `files`, `steer`, `cancel`, `delete` | no (`steer`, `cancel` and `delete` change state) | no |
| `plungeai_followup` | a new turn on an execution: continues it, or steers it while it runs | no | yes |
| `plungeai_continue` | answers a paused run, or approves its staged action | no | yes |

Full parameter tables are in the [Tool reference](/mcp/tool-reference).

## 9.1 Execution ids

**Where the id comes from.** An `ok` answer ends with a footer line:

```
---
execution: `<execution_id>` — use this id for plungeai_get_result / plungeai_followup on this run.
```

A guidance answer for a run that did start (`needs_approval`, a paused `needs_input`, a classified failure) ends with `_(execution: <execution_id>)_`. A `mode:"async"` call returns the id at once. With `format:"json"` the id is the outcome's `execution_id` field.

**An execution id is not a workflow id.** A workflow id names the recipe, a saved workflow. Every run of it gets a new execution id. The result and status tools need the execution id. If you only have the workflow, list its runs with `plungeai_executions {action:"list", workflow_id:"<workflow_id>"}` and take the id from there.

**Which forms are accepted.**

| Id | Example shape | Accepted by |
|---|---|---|
| execution id | a UUID | every tool in this chapter |
| engine id | `exec-…` (hyphen), as scheduler surfaces show it | `plungeai_get_workflow_status`, `plungeai_get_result`, `plungeai_executions` `get` / `output` / `cancel`. `plungeai_executions` `delete` and `conversation` need the execution id itself. `plungeai_followup` and `plungeai_continue` resolve an `exec-…` id but save the new turn under it, so the thread does not show in `plungeai_get_result` or Studio (and a follow-up misses the run's stored result as context): pass them the execution id. `plungeai_executions {action:"list"}` shows it in the ID column; `plungeai_get_workflow_status` does not (its `execution_id` echoes what you passed) |
| scheduler run id | `exec_…` (underscore), from old scheduled runs | none. `plungeai_get_result` and `plungeai_get_workflow_status` answer with a pointer to `plungeai_schedule {action:"runs"}`, whose Execution ID column gives the id to use ([Scheduling](/mcp/scheduling)) |

**Ownership.** Every tool here checks that the execution belongs to the key's user before it reads anything. You see your own runs only.

**"Show me #2."** A numbered reference means the Nth row of a list as you saw it. The server instructions tell clients to resolve it against the list already shown in the conversation, never against a freshly fetched one: new runs land all the time and shift the newest-first numbering.

**A refusal is not a run.** A call stopped before dispatch (missing field, unknown agent, unknown model) creates no execution and has no id. See [Errors, feedback & limits](/mcp/errors-limits).

## 9.2 Get a result: plungeai_get_result

Pass `execution_id`. `workflow_id` is accepted as an older alias, and it still means an execution id. Add `task_id` to read one task's output instead of the final result.

A full result is assembled in this order:

1. **An identity line.** The workflow name and the first 80 characters of the question, then the start time in UTC and the first 8 characters of the execution id. People rerun the same question often; this line says which run you are looking at.
2. **The final output.** Finished Markdown, as the run produced it.
3. **Steps in this run (N).** Only for runs with two or more steps: each step's task id and the agent that ran it, with the final step marked. Any step is one call away with `task_id`.
4. **Conversation thread (N messages).** Only when the run has follow-up or continue turns: the whole thread, as `**User:**` / `**Agent:**` turns.
5. **A ⏸ block** when the run is paused and waiting for you ([9.6](#96-paused-runs-plungeai_continue)).

The server instructions tell clients to show this output verbatim and in full. Some chat clients still summarize long answers; asking for it "verbatim, don't summarize" stops that.

**Where results live.** When a run finishes, its final output is saved with the execution and does not expire; Studio and this server write the same record. When that saved copy is missing (an older run, or a failed save), the final output is read from the run's shared memory instead, which does expire. The outputs of the other steps live only in shared memory. So `task_id` for an old run can come back empty while the full result still reads fine.

**One step.** `task_id` for a non-final step reads that step's own output (plus a ⏸ block if the run is paused). Passing the final step's id returns the full result. If the step output is gone, the answer is `No result found for workflow=<id>, task=<task_id>. The task may still be running, or its output has expired from SharedMemory.` (`isError: true`).

**When there is no output**, the answer says why. Before it answers, the tool self-heals a stuck `running` row the same way the status tool does ([9.3](#93-check-status-plungeai_get_workflow_status)).

| Situation | Answer |
|---|---|
| No id passed | 📝 NEEDS INPUT: ``Provide the id of the execution to fetch (as `execution_id`).`` |
| Unknown id, or not yours | 📝 NEEDS INPUT: ``No result found for `<id>`, or it is not one of your executions.`` The remediation points to `plungeai_executions {action:"list"}` |
| Scheduler run id `exec_…` | `That is a scheduler run id, which this tool cannot resolve. Use plungeai_schedule {action: "runs"} …` (`isError: true`) |
| The run failed | `This run failed: <reason>. (execution: <id>)` (`isError: true`). Fix the input and rerun; polling will not change it |
| Still running | `No result yet for <id> — it is still running. Poll plungeai_get_workflow_status, then retry.` (`isError: true`) |
| Completed, but nothing is stored any more | `Run <id> completed, but its stored result is no longer retrievable (expired from SharedMemory).` (`isError: true`) |

**JSON.** With `format:"json"` a result is the body `GET /v1/executions/{id}/output` returns on the One API, field for field: `execution_id`, `status` (`needs_input` / `needs_approval` while the run waits on you), `content` (the stored output, raw), `final_task_id`, `steps` (`task_id`, `agent`, `final`) and `continuation`, in the text and in `structuredContent`; it carries no rendered thread. With `task_id` it is `{execution_id, task_id, result}`. The not-ready answers above stay `{"content": "<the same text>"}`, and a NEEDS INPUT answer becomes the outcome object itself.

Try asking:

- *"Show me the result of that last run."*
- *"Show me the full result for that specific task, not just the summary."* Your client takes the task id from the **Steps in this run** index.

The full result of one run (replace `<execution_id>`):

```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_get_result","arguments":{"user_request":"show me the result of that last run","execution_id":"<execution_id>"}}}'
```

One step of it:

```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_get_result","arguments":{"user_request":"show me the full output of the search step","execution_id":"<execution_id>","task_id":"<task_id>"}}}'
```

An id that is not yours comes back as guidance, not an error:

```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_get_result","arguments":{"user_request":"show me that result","execution_id":"00000000-0000-4000-8000-000000000003"}}}'
```

The same output is also readable as the resource `plungeai://executions/{id}` ([Prompts & resources](/mcp/prompts-resources)).

## 9.3 Check status: plungeai_get_workflow_status

Pass `execution_id`. The tool has no `format` parameter: every answer carries both Markdown and `structuredContent`, which matches the tool's declared `outputSchema`.

The Markdown answer:

```
# Execution <execution_id>

- **Workflow:** <name>
- **Status:** <status>
- **Error:** <reason>                 (failed runs only)
- **Note:** The run stopped at its turn budget before finishing; the partial output is retrievable.   (incomplete only)
- **Started:** <ISO time>
- **Duration:** <n>ms
- **Final task:** <task_id>

Fetch output with plungeai_get_result.   (completed or incomplete)
```

A ⏸ block follows when the run is paused ([9.6](#96-paused-runs-plungeai_continue)).

**Status values.**

| `status` | Meaning | What to do |
|---|---|---|
| `running` | still executing | poll again |
| `completed` | finished; the output is stored | `plungeai_get_result` |
| `incomplete` | stopped at its turn or iteration budget before finishing; the partial output is stored (async runs only, below) | `plungeai_get_result` reads the partial output. Rerun with a larger budget if you need more |
| `failed` | failed; `error_message` carries the reason (null on the one poll that self-heals the row, below) | fix the input and rerun. Do not keep polling |
| `cancelled` | stopped with `plungeai_executions {action:"cancel"}` | nothing; rerun if you still want it |

An `incomplete` run is stored as `completed` with an `incomplete` outcome. This tool reports it as `incomplete` so a status-only poller never reads it as success. The history list ([9.4](#94-run-history-plungeai_executions)) shows the stored `completed`.

This holds for `mode:"async"` runs only. A sync execute or mission call stamps the outcome `ok` when it answers, which replaces the `incomplete` mark, so the same run then reports `completed` here, and its answer reads as a normal success ([7.7](/mcp/agents-missions#77-mission-bounds), [8.5](/mcp/workflows#85-what-a-run-returns)). This is current behaviour. Use async when you need to tell a finished run from one that ran out of turns.

**Self-heal.** Each read of a `running` row checks it first:

- the run's output exists but the row still says `running` → the row is set to `completed`;
- the row has had no heartbeat for more than 960 seconds (16 minutes) → it is set to `failed` with the reason `Interrupted (run did not complete)`.

The rule keys on the last heartbeat, not the start time. A live run keeps heartbeating, so a long run is not cut off by it. A background run that died without finishing is reported as failed instead of reading "running" forever. The answer that performs this fix already says `failed`, but its `error_message` is still null (and `plungeai_get_result` says `no error was recorded`); the next read carries `Interrupted (run did not complete)`.

**`structuredContent`** (the registered `outputSchema`):

| Field | Type | Notes |
|---|---|---|
| `execution_id` | string | the id you passed |
| `status` | string | one of the values above |
| `error_message` | string or null | set for `failed` runs only |
| `workflow_name` | string or null | the display name, e.g. `<name> · <agents that ran>` |
| `started_at` | string or null | ISO 8601 |
| `duration_ms` | number or null | |
| `final_task_id` | string or null | |
| `continuation` | object or null | non-null when the run is paused for you: `{ status, agent, question, pending_action }`. `status` is `needs_approval` or `question`; `question` is the question or null; `pending_action` is `{ summary, price? }` or null |

**Errors** (all `isError: true`):

| Answer | Cause |
|---|---|
| `Execution not found.` | no execution with this id is yours (an unknown id and another account's id read the same) |
| `That is a scheduler run id, which this tool cannot resolve. …` | an `exec_…` id; use `plungeai_schedule {action:"runs"}` |
| ❌ ERROR `Status storage is temporarily unavailable — please retry in a moment. (request <id>)` | a storage hiccup; retry once after a few seconds |

**Polling.** A `mode:"async"` run sends no live progress, so poll this tool until the status leaves `running`. Then fetch the output with `plungeai_get_result`. A paused background run shows up here as a `continuation`, so it never sits unseen.

Try asking: *"Is that still running?"*

```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_get_workflow_status","arguments":{"user_request":"is that still running?","execution_id":"<execution_id>"}}}'
```

An unknown id:

```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_get_workflow_status","arguments":{"user_request":"is that still running?","execution_id":"00000000-0000-4000-8000-000000000003"}}}'
```

## 9.4 Run history: plungeai_executions

One tool with eight actions. Every action except `list` needs `execution_id`.

| `action` | Does | Markdown answer | With `format:"json"` |
|---|---|---|---|
| `list` | your runs, newest first | `# Executions (N)` and a table: ID, Question (first 60 characters), Workflow, Status, Source, When | `{"executions": [{id, input, workflow_name, status, start_time, duration, source}]}`; `start_time` is Unix seconds, `duration` is milliseconds, `source` is the surface that started the run (`null` when unrecorded) |
| `get` | the same answer as `plungeai_get_workflow_status` | the status block | the status object |
| `output` | the same full result as `plungeai_get_result` | the result | `{"content": "<markdown>"}` |
| `conversation` | the run's follow-up thread only | `# Conversation — <id>` and the turns, or `No conversation thread for this execution yet.` | `{"execution_id", "messages": [...]}`, or `{"messages": []}` |
| `files` | the files the run wrote | `# Files of <id> (N)` and a table: Path, Size, Type, or `This run wrote no files.` | `{"content": "…"}` |
| `steer` | queues `message` for a running execution | ``Queued your message to running execution `<id>` (delivered at its next turn).`` | `{"content": "…"}` |
| `cancel` | stops a running execution | ``Cancelling execution `<id>` — the run stops at its next turn or tool boundary.`` | `{"content": "…"}` |
| `delete` | deletes the execution record and its stored result | ``Deleted execution `<id>`.`` | `{"content": "…"}` |

**`list`.** `limit` defaults to 20 (1–100); `offset` defaults to 0 (up to 100,000). `workflow_id` narrows the list to runs of one workflow. The Status column shows the stored status, so an `incomplete` run shows `completed` here; `get` gives the honest status. The Source column names the surface that started the run: `mcp` (this server), `api` (the One API), `cli` (either of those, called with the header `X-Ocean-Client: cli`), `studio`, `mini-app`, `scheduler` or `campaign-agent`; older rows without one show `—`.

**`cancel`** works on a `running` execution only. Anything else answers `Execution is <status>, not running — nothing to cancel.` (`isError: true`). The cancel is cooperative: the tool writes a cancel marker that the engine and the harness read at their next safe boundary, and it sets the row to `cancelled` (reason `Cancelled by user`) at once. A step that finishes late does not relabel the row.

**`steer`** works on a `running` execution only: the message is queued for the live loop and delivered at its next turn. A finished run answers ``Execution is <status>, not running — nothing to steer.`` (`isError: true`); continue a finished run with `plungeai_followup` ([9.5](#95-follow-ups-plungeai_followup)).

**`delete`** cannot be undone. It removes the execution row and its stored result, and tells connected apps (Studio and the others) that the run is gone.

**Errors.** `execution_id is required for this action.` and `Execution not found.` (unknown, or not yours) are `isError: true`. A storage hiccup while reading a thread comes back as the ❌ ERROR envelope with a request id.

Try asking:

- *"Show me my last 10 executions."*
- *"Cancel that run."*
- *"What files did that run write?"* The client runs `files`.
- *"Tell the running bot to skip the Berlin leads."* The client runs `steer` with the message.

```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_executions","arguments":{"user_request":"show me my last 10 executions","action":"list","limit":10,"format":"json"}}}'
```

Cancelling a run changes its state (not verified here):

```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_executions","arguments":{"user_request":"cancel that run","action":"cancel","execution_id":"<execution_id>"}}}'
```

Listing the files a run wrote is read-only (it needs a real id, so it has no verifier marker):

```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_executions","arguments":{"user_request":"what files did that run write","action":"files","execution_id":"<execution_id>"}}}'
```

Steering a running bot or agent queues a message for its next turn and changes the run (not verified here):

```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_executions","arguments":{"user_request":"tell the running bot to skip the Berlin leads","action":"steer","execution_id":"<execution_id>","message":"Skip the Berlin leads."}}}'
```

## 9.5 Follow-ups: plungeai_followup

A follow-up keeps a run's context instead of starting over. Pass `execution_id` and `prompt`. What happens depends on the state of the run:

| State of the run | What happens | Answer |
|---|---|---|
| still `running` | your message is queued into the live run and delivered at its next turn (steering). No new run starts | ``Queued your message to running execution `<id>` (delivered at its next turn).`` |
| finished, with an open agent session | the same agent continues its conversation with your message | the agent's reply, plus a ⏸ block if it pauses again |
| finished, no session | the researcher fallback: `harness-agent` answers with the run's stored result as context | the answer |

**The researcher fallback** takes the first 9,000 characters of the run's stored output as prior context. It runs with the tools `recall`, `recall_history`, `knowledge`, `web_search`, `web_fetch`, `registry_search` and `task_complete`, for up to 12 turns. It is told to verify any new factual question with web search, cite source URLs, and never answer from the prior context alone. Because the stored result does not expire, an old run can still take follow-ups, when you pass the execution id itself ([9.1](#91-execution-ids)).

**Both turns are saved.** Your message and the answer are appended to the run's conversation thread. When you passed the execution id, the thread shows up in `plungeai_get_result`, in `plungeai_executions {action:"conversation"}`, and in Studio.

**It narrates itself.** While it works it sends live status on the progress channel ([Protocol & transport](/mcp/protocol)):

```
🔎 Looking up the run and checking for an open session…
💬 <agent> working — continuing the conversation…              (open session)
📚 No open session — loading the run's stored result as context…   (fallback)
🔬 Researching with harness-agent — <n> chars of prior context…
⏳ Collecting the answer…
💾 Saving this turn to the conversation thread…
✅ Complete — continued the existing session
```

The answer is plain Markdown text, not the outcome envelope, and the tool has no `format` parameter. Errors are `isError: true`: `Execution not found.`, `Followup agent call failed`, `Failed to retrieve follow-up response`.

Follow-up or continue? A follow-up is for a finished run, or for steering a running one. A run that stopped to ask you something is answered with `plungeai_continue` ([9.6](#96-paused-runs-plungeai_continue)).

Try asking: *"Now do the same analysis but focus on the competitive landscape."*

This runs a model and costs credits (not verified here):

```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_followup","arguments":{"user_request":"now do the same analysis but focus on the competitive landscape","execution_id":"<execution_id>","prompt":"Do the same analysis, but focus on the competitive landscape."}}}'
```

## 9.6 Paused runs: plungeai_continue

Some agents stop instead of finishing: always before spending money, and sometimes to ask a question ("which wallet?", "what should the call say?"). Nothing has been executed when a run pauses.

**How a pause shows up.**

- On the run's own answer (the sync execute tools): the outcome `needs_approval` with the summary `⏸ AWAITING USER APPROVAL: <action> (<price>). Relay this to the user verbatim and ask them to decide — NEVER approve on your own.`, or the outcome `needs_input` with `⏸ AWAITING USER: <question>`. The remediation names `plungeai_continue` and the execution id.
- On `plungeai_get_result`, `plungeai_get_workflow_status` and follow-ups: a closing block.

  ```
  ---
  ⏸ AWAITING USER APPROVAL: <action> (<price>)
  Ask the user to confirm, then call plungeai_continue with execution_id "<id>" and approve: true (or message: "<their words>").
  ```

  For a question: `⏸ AWAITING USER: <question>` and `Relay this to the user, then call plungeai_continue with execution_id "<id>" and message: "<their answer>".`
- In the status tool's `structuredContent.continuation` ([9.3](#93-check-status-plungeai_get_workflow_status)). This is how `mode:"async"` runs surface a pause.

**The loop.**

1. The run comes back paused. Nothing has run yet.
2. Your client relays the ⏸ block and asks you to decide. The server instructions tell it never to approve on its own.
3. You answer in your own words. *"Yes"* or *"approve"* becomes `approve: true`. Anything else, including *"no"*, goes back as `message`.
4. On approve, the held action runs exactly once. A repeated or stale approve is harmless: the agent answers that nothing is awaiting approval, so it can never pay twice.

**Parameters.** `execution_id` plus `message`, or `approve: true`. If you pass both, the approval is sent. `approve: false` on its own is rejected; to deny, pass the user's words as `message`.

**What comes back.** The agent's reply, then either a new ⏸ block (it paused again) or `✅ Conversation resolved (no further input needed).` The tool waits up to about 30 seconds for the reply, because an approved payment or outside call runs during this turn. The turn is saved to the run's thread; an approval is recorded as `✅ Approved`.

**Errors** (all `isError: true`):

| Answer | Cause | What to do |
|---|---|---|
| `` Provide `message` or `approve: true` `` | neither was passed | pass one |
| `Execution not found` | unknown id, or not yours | check the id |
| `No conversation session for this execution (expired or not a conversational agent)` | the run holds no paused session | nothing to continue; use `plungeai_followup` for more on a finished run |
| `This run isn't paused — it already completed. Use plungeai_followup to ask a follow-up about it.` | the session is finished and you sent a `message` | use `plungeai_followup` |
| `Agent continuation failed` | the engine call failed, or no reply arrived in the ~30-second window | check `plungeai_get_workflow_status` and `plungeai_get_result` before you retry: an approved action may already have run |

**The trust fence is different.** A structured tool called directly with `plungeai_execute_tool` (or a workflow task) for an outward, irreversible operation (send, pay, transfer, buy, withdraw) comes back ⏸ NEEDS APPROVAL from the engine's fence, with nothing run, no `approve_via` action and no paused session. `plungeai_continue` does not apply to it (it answers `No conversation session…`). Relay it to the user: such an operation runs only from an interactive session such as Ocean Studio, where a person can approve it. See [6.6](/mcp/tools#66-the-trust-fence--needs-approval).

Try asking: *"Yes, go ahead"* / *"Use the second option"*.

Approve, only after the user said yes. This runs the held action, which may spend money (not verified here):

```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_continue","arguments":{"user_request":"yes, go ahead","execution_id":"<execution_id>","approve":true}}}'
```

Answer a question instead:

```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_continue","arguments":{"user_request":"use the second option","execution_id":"<execution_id>","message":"Use the second option."}}}'
```

## 9.7 Which tool when

| You want | Call |
|---|---|
| the answer of a run | `plungeai_get_result {execution_id}` |
| one step's full output | `plungeai_get_result {execution_id, task_id}`; the ids are in **Steps in this run** |
| to know if it is done, failed or paused | `plungeai_get_workflow_status {execution_id}` |
| your recent runs, or the runs of one workflow | `plungeai_executions {action:"list"}` (with `workflow_id` to filter) |
| to stop a running run | `plungeai_executions {action:"cancel", execution_id}` |
| more on a finished run, with its context | `plungeai_followup {execution_id, prompt}` |
| to change course while it still runs | `plungeai_followup` (it queues the message into the run) |
| to answer a ⏸ block | `plungeai_continue {execution_id, message}` or `{approve: true}` |
