Core Concepts
Runs & Events
A Run is the core unit of work in Reduck. One prompt = one run. This page explains the lifecycle, events, and how to handle them.
Run lifecycle
Starting a run
A run is created when you call:
- TypeScript:
client.run(prompt, { deviceId }) - CLI:
reduck -q "prompt"
The runner sends a web push to the target device’s extension.
Event types
Events stream in real time as the automation runs. The SDK exposes them as an async iterator; the CLI prints them formatted to your terminal.
| Type | Key fields | Terminal? | Description |
|---|---|---|---|
run_started | timestamp | No | Automation has started |
progress | text, timestamp | No | Step-by-step progress update |
assistant | text, timestamp | No | Assistant message |
turn_completed | timestamp | No | Agent turn completed |
run_completed | timestamp | No | Automation finished executing |
done | success, output? | Yes | Final result |
failure | error | Yes | Automation failed |
cancel | — | Yes | Automation was cancelled |
A terminal event means the run is over and the stream closes.
Cancelling a run
From the SDK:
await run.cancel()
From the CLI:
- Press Ctrl+C during a run
- Or:
reduck interrupt <run-id>
The extension receives the cancel signal and stops the current automation. A cancel event is emitted.
Error handling
for await (const event of run) {
if (event.type === "failure") {
console.error("Run failed:", event.error ?? "unknown");
// Maybe retry, alert, or log
}
}
Common failure reasons:
- Extension not reachable (device offline or push failed)
- Page navigation error (site down, CAPTCHA, auth expired)
- Timeout (automation took too long)
- LLM error (the AI planner couldn’t figure out how to proceed)