# Interactive Testing & Debugging

> Applies to: ChengOS v0.1.0+ ｜ Last verified: 2026-08-12 ｜ Source: `chengflow-ui/src/features/execution`, `crates/cheng-api/src/ws/protocol.rs`, `crates/cheng-api/src/rest/handlers/execution`

You do not have to deploy a workflow to see whether it works. Runs happen from the editor, and
events stream back over WebSocket while they happen, so debugging is a matter of watching and
then reading — not of guessing from a final error string.

## Running from the editor

Save, then run from the control panel. Running is blocked while an execution is already
running, paused, or waiting for review, so you cannot accidentally start two runs of the same
graph on top of each other. If the workflow has never been saved, saving is part of the run.

## Watching it happen

The execution panel shows live status, progress, and elapsed time. As the run proceeds the
canvas annotates itself: each node moves through `waiting` → `ready` → `running` →
`completed` / `failed` / `skipped`, and nodes with no dependency between them light up
simultaneously — which is often the first time you notice your graph is more parallel (or less)
than you assumed.

Streaming nodes are handled specially. A model node emits its output token by token
(`NODE_STREAM_START`, then `NODE_STREAM_CHUNK`, then `NODE_STREAM_COMPLETE`), so you see text
appear rather than waiting for the whole response.

Agent nodes report more still: per-iteration events, tool call start/complete/failure, turn
boundaries, and context window status. For an agent, that stream *is* the debugging
surface — see [the ReAct guide](/docs/agent-react-guide).

## Controlling a run

| Action | Effect |
|---|---|
| **Pause** | Suspend at the next safe point; resumable |
| **Resume** | Continue a paused run |
| **Cancel** | Stop and move to the terminal `cancelled` state |
| **Approve** | Supply the decision a run waiting for review needs |

`waiting_for_review` is a normal state, not a stall: a node asked for a human decision. The
approval card appears in the panel; the run continues once you answer.

## Reading a failure

Click the failed node. The execution detail shows the error **and the inputs that node actually
received**, which is the part that usually settles it — most failures are a value that was not
what you expected, not a broken node.

Work outward from there:

- **Inputs wrong?** The problem is upstream. Follow the edge back and check that node's output.
- **Inputs right, node failed?** The problem is configuration or an external service.
- **Node skipped?** A conditional branch routed around it. That is often correct; check the
  router's condition if it is not.

The log viewer shows the run's log output, and the result preview shows values produced. Insert
`utils/preview` nodes mid-graph while developing — a preview node exists to make an
intermediate value visible, and pulling one out later costs nothing.

## Traces

Beyond the live view, every execution keeps a durable trace:

| Endpoint | Contents |
|---|---|
| `GET /api/v1/executions/:id` | Status, timings, per-node results |
| `GET /api/v1/executions/:id/logs` | Log output |
| `GET /api/v1/executions/:id/trace-snapshot` | Full structured trace |
| `GET /api/v1/executions/history` | Past runs |
| `GET /api/v1/executions/active` | Currently active runs |

The trace survives a browser reload, which matters for long agent runs: closing the tab does
not lose the run or its history. The editor reconnects and rejoins the stream. If the event
stream goes silent for 30 seconds, the client reconciles against the API rather than waiting
indefinitely, so a dropped socket shows you real state instead of a spinner.

## Common first-run failures

| Symptom | Usual cause |
|---|---|
| Model node fails immediately | No credential configured, or a model name the provider does not recognise |
| A field you set is ignored | Something is wired into that input port; the edge wins over the typed value |
| `{{variable}}` appears literally in output | Name does not match an upstream output — use the variable selector |
| Node never runs | An upstream node failed or was skipped, so its dependency never became ready |
| Run refuses to start | A previous execution is still active — cancel it first |

## Next steps

- [Execution model](/docs/exec-model) — why nodes run in the order they do.
- [Execution failures](/docs/fix-execution-failures) — a deeper diagnostic path.
- [Node configuration](/docs/editor-node-configuration) — the panel in detail.
