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

# Observability — watching, debugging, and pricing platform runs

> Every execution on PlungeAI is observable at four altitudes: live events while it runs, an execution record after it finishes, a persisted span-level trace, and the gateway's own request log with cost. Debugging is reading these in order — not re-running the workload to "see what happens".


<!-- sources-of-truth: orchestration/api-gateway/openapi.ts (traces, request log), orchestration/cnl-engine/README.md (SSE events, execution summary), orchestration/cnl-engine/executors.ts, orchestration/mcp-gateway/server.ts, orchestration/scheduler/README.md | last-synced: 2026-09-24 -->
Every execution on PlungeAI is observable at four altitudes: live events while it
runs, an execution record after it finishes, a persisted span-level trace, and the
gateway's own request log with cost. Debugging is reading these in order — not
re-running the workload to "see what happens".

## Correlation ids — wire them in from the start

- Every One API response echoes a server-generated **`x-request-id`**.
- Pass your own **`x-trace-id`** header on One API calls to correlate a whole
  operation across planes (an agent execute + a result redeem + a model call under
  one trace). **Fallback rule:** if you never sent `x-trace-id`, the trace id IS
  that request's `x-request-id` — so a call you did not pre-correlate is still
  traceable: take the echoed `x-request-id` and use it in `GET /v1/traces/{id}`.
- Every execution acknowledgement carries `workflow_id` (the execution id) and
  `request_id`. Log them; they are the keys to everything below.

## Live: SSE event stream

Streaming execution (`POST /v1/workflows/{id}/execute-stream`, and MCP streamed
runs) emits server-timestamped events in order:

```
request_received → workflow_loaded → workflow_started
  → task_dispatched (per task) → task_completed (per task)
→ workflow_completed → workflow_result
```

Per-task duration = that task's `task_completed` − `task_dispatched`, using the
SERVER timestamps — client network jitter is excluded. This event stream is the
ground truth for performance questions ("which branch was slow"); never time a run
from your own clock around the request.

## After the run: status and history

### `plungeai_get_workflow_status {execution_id}`

Structured status: `status`, `workflow_name`, `started_at`, `duration_ms`,
`final_task_id`, `error_message` (non-null on failure), and — crucially —
`continuation`: non-null when the run is PAUSED awaiting the user (an `ask_user`
question or an approval gate), carrying the agent, the question, and any pending
action summary (with price when it is a money action). Relay that to the user and
resume with `plungeai_continue`. The status check also **self-heals stuck runs** —
poll it before declaring a run dead. Full parameter/return contract:
`plungeai-workflows` (`references/mcp.md`).

### `plungeai_executions` — the run ledger

`action: list|get|output|conversation|delete`. `list` is the "what ran lately"
view; `get` the record; `output`/`conversation` the content (final, user-ready
markdown — relay verbatim). This is also your idempotency check: before re-firing
anything with side effects, look here for what already ran. Full parameter/return
contract: `plungeai-workflows` (`references/mcp.md`).

### Execution summary (per run)

Every engine run reports: `total_tasks_executed`, `tasks_skipped`,
`conditions_evaluated`, `nesting_levels_processed`, `parallel_blocks_executed`,
`sequential_blocks_executed`, per-task durations (with attempts), and
**`failed_branches[]`** — parallel branches that failed WITHOUT aborting the run.
The key is present only when something was lost; its absence is the all-clear.
Always check it before trusting a synthesis built over a fan-out.

## Deep: persisted traces

```bash
curl -s https://api.plungeai.com/v1/traces/{traceId} \
  -H "Authorization: Bearer ozk_YOUR_KEY"
```

Returns two arrays:

- **`spans`** — engine execution spans: `type` (`request_received`,
  `task_dispatched`, `task_completed`, `workflow_result`, …), `workflow_id`,
  `task_id`, `agent`, `status`, `duration_ms`, timestamp. Large payloads are stored
  by reference (`payload_ref`); small ones inline (`payload_inline`,
  guard-scanned, ≤1 KB) — traces never leak megabytes into your context.
- **`gateway_requests`** — the router's own log per request: `plane`, `route`,
  `status`, `duration_ms`, and **`cost_usd`** where priced. This is where "what did
  that run cost" is answered; model usage is captured per task and priced post-hoc
  from the platform's pricing catalog.

Full route detail (parameters, error shapes, the outbound-MCP variant of tracing):
[`references/traces.md`](/skills/plungeai-results-traces/references/traces).

## Scheduler observability

Scheduled work has its own ledger on top (see `plungeai-scheduling`):
`plungeai_schedule {action: "stats"}` for the fleet (active/paused jobs, today's
success/failure split, average duration) and `{action: "runs", job_id}` for one
job's history — whose Execution ID column bridges into everything above.

## Quality signals in discovery

Registry search accepts `include=quality`: each card gains
`{score, success_rate, runs}` (null when unmeasured). Use it when choosing between
similar agents — measured success beats description prose.

## The debugging playbook

1. **Run seems hung** → `plungeai_get_workflow_status` (self-heals; may return a
   `continuation` — the run is waiting on a human, not hung).
2. **Run failed** → status `error_message` → the trace's failing span (`status`,
   `agent`, `duration_ms`) → that agent's outcome remediation.
3. **Run "succeeded" but output is thin** → execution summary `failed_branches[]`
   and `tasks_skipped` (a false condition silently skips tasks — that is a feature,
   verify the condition).
4. **Slow** → per-task durations from events/spans. Parallel block cost = slowest
   child; a staircase of child durations against one destination means queueing at
   that service — spread destinations, don't widen the block (`plungeai-workflows`).
5. **Expensive** → `gateway_requests.cost_usd` by route + the run's per-task model
   usage; then cap with `effort`/`max_turns` (missions, `plungeai-missions`) or a
   cheaper `model` (`plungeai-models`).
6. **Behaved as if instructions were missing** → the run's warnings: capability ids
   that failed to resolve or were deferred over budget (`plungeai-skills-plugins`).

## What to log in YOUR integration

Minimum for a production integration calling the platform: the `x-request-id` of
every call, the `workflow_id`/`execution_id` of every run you start, and your own
`x-trace-id` per user-visible operation. With those three, every incident is
reconstructable from the platform side; without them you are grepping timestamps.
