Scenarios

Directed flows on the board—not a separate automation product

In the Digio workspace, Scenarios are saved graphs: manual triggers, HTTP steps, queue-to-agent tasks, and HTTPS webhooks. The runner walks only nodes reachable from the chosen trigger, orders them with a topological sort (Kahn), rejects cycles, and supports dry-run logging before any outbound call.

Graph + ports Dry run default Abort / pause
Persistence

What is stored per scenario

Each scenario is a JSON object on the team: stable id, display name, enabled flag, optional primaryAgentId, optional runOnAgentSchedule (only when primary resolves to a known agent), arrays of nodes and edges. Unknown node types normalize to manual triggers; malformed edges are dropped.

Identity

id · name · enabled

id is stable for webhooks and logs; enabled gates live side-effects while validation still explains disabled flows in dry mode.

Primary agent

primaryAgentId

When set and valid, add_task nodes with an empty agentId inherit it—so drafts stay valid after you pick a default specialist.

Graph

nodes[] · edges[]

Nodes carry canvas x/y plus type-specific fields; edges reference from/to node ids with optional outKey/inKey port names (defaults o0 / i0).

Schedule hook

runOnAgentSchedule

Boolean flag stored with the scenario; it only sticks when primaryAgentId is non-empty and matches the roster—used for agent-timed runs in the app shell.

Node palette

Five node types the runner understands

Types are fixed in code (trigger_manual, http_request, add_task, webhook_notify, integration_logo). The overlay palette instantiates defaults with sane ports; normalization clamps string lengths and numeric priority to 1–10.

Start

trigger_manual

Only entry points: no incoming edges allowed in normalization. You pick which trigger Run test uses when a flow has more than one.

Network

http_request

GET or POST with optional JSON body (up to 16k chars). Live run sets Accept, optional Content-Type + body for POST, captures up to 4k of response text for later webhook payloads.

Work

add_task

Queues a standing task: agentId, title (trimmed, required), priority. Live path calls the workspace hook with launchMode immediate; missing title or agent is logged as a skip, not a throw.

Notify

webhook_notify

POST only after URL passes the same HTTPS allow-list helper used for spreadsheet status webhooks. Body includes scenario id/name, node id, and a truncated preview of the last HTTP response.

Doc

integration_logo

Social or integration marker on the canvas—runner appends a log line for visibility in dry and live modes without performing I/O.

Wiring

Edges, ports, and invalid links

Edges store from, to, outKey, inKey, and their own id. Self-loops and edges into a manual trigger are removed. If an edge names a port missing on a node, normalization falls back to that node’s first declared port—so flows keep running after palette upgrades.

Directed only

Graph is treated as forward from the active trigger: unreachable nodes never execute—handy for experimental branches left on the canvas.

Parallel fan-out

Multiple outgoing edges from one port are allowed; Kahn’s algorithm yields a deterministic linear order among ready nodes—no hidden random shuffle.

Missing endpoints

Edges whose from/to do not resolve to existing node ids are dropped during normalize—Run test never throws on stale graph fragments.

Execution order

Reachability + topological sort + cycle guard

getScenarioExecutionOrder first DFS-marks nodes reachable from the chosen trigger, then builds indegree counts on that subgraph. A queue drains zero-indegree nodes; if the output length is less than reachable size, the graph returns error cycle—Run test stops before any I/O.

no_start

Returned when the trigger id is missing from the node map—usually corrupt paste or a deleted trigger still selected in UI.

no_trigger

executeScenarioFlow aborts early if the normalized graph contains zero trigger_manual nodes—every flow must declare an explicit start.

cycle

Any directed cycle in the reachable subgraph leaves residual indegree; the runner refuses order and surfaces the failure in the log panel instead of looping forever.

http_request

Outbound HTTP with bounded capture

Live mode uses the browser fetch implementation (or an injected test double). AbortSignal from the overlay is passed through so Cancel stops mid-flight. Responses are read as text, not forced JSON parse—binary-safe truncation to 4k chars for lastHttpPreview.

GET vs POST

Method toggles strictly between GET and POST; POST with a non-empty body sets Content-Type application/json and sends the raw string you authored.

Status line in log

Each live step logs HTTP status, OK/FAIL against response.ok, and byte length—enough to debug APIs without dumping secrets by default.

Dry-run line

Dry mode prints method + URL and explicitly marks simulation—no network tab noise while you teach the flow to others.

add_task

Queue work to a specific agent

The runner validates agentId and title after trim. Dry run echoes the tuple and marks simulation. Live run checks agentId against the current dashboard roster; unknown ids log agent missing and skip enqueue—protecting you from stale flows after a hire leaves.

Priority 1–10

Normalized at graph load: non-numeric becomes 5; values clamp to the inclusive 1–10 band used across standing tasks.

Immediate launch

onAddTask receives launchMode immediate—the same urgency path as pressing Run on a card, not a silent backlog draft.

Title length cap

Titles persist up to 500 chars at normalization; extremely long template strings survive import without breaking JSON storage.

webhook_notify

HTTPS callback with structured JSON

Live POST JSON includes event scenario_step, scenarioId, scenarioName, nodeId, and lastHttpPreview (first 1200 chars of the most recent HTTP response text). That lets your receiver correlate notify steps with upstream API payloads without re-fetching Digio internals.

URL policy

Invalid or non-HTTPS endpoints log skip bad webhook—same helper as spreadsheet status webhooks, so security rules stay consistent across products.

Errors stay in-log

Network failures append human-readable error strings; AbortError propagates as a halted run with ok false aborted, not a silent drop.

Dry-run preview

Dry mode prints truncated URL plus simulation marker—ideal when demoing a customer endpoint without firing their on-call.

Safety

Dry run is the default in the overlay

Run test boots with dryRun true so opening someone else’s scenario never fires webhooks accidentally. Validation still walks order: disabled scenarios print a disabled note in dry logs so reviewers see intent without side effects.

HTTP

Simulated only

No fetch call is made; method and URL appear in the log with the dry-run copy string from product strings.

Tasks

No enqueue

add_task branches log the would-be title and agent id, proving field mapping without touching the kanban or To do queue.

Webhooks

No POST

Webhook nodes log URL length-safe preview plus simulation—receiver teams can validate routing rules before go-live.

Logos

Still traced

integration_logo nodes always append a label line in both modes so documentation subgraphs show up in exported run logs.

Live iteration

Pause, resume, and cancel semantics

Between nodes the runner awaits scenarioWaitResume: if the overlay sets paused, the loop sleeps in 90ms slices until cleared or aborted. AbortError unwinds as ok false aborted; other errors on HTTP/webhook append to the log but continue when the code path allows—matching the forgiving behavior operators expect in demos.

Per-node await

Every step checks signal and pause gate before work—tight loop for integration_logo, meaningful for long HTTP calls.

Fetch injection

fetchImpl is overridable for unit tests or future server-side replay—production UI passes window.fetch.

Trigger pick

When triggerNodeId is empty or stale, the runner chooses the first normalized manual trigger—predictable for single-entry flows, explicit selector for multi-branch.

Overlay UX

Team scope, agent filter, integrations flyout

ScenariosOverlay receives scenarios[], agents[], teams[], activeTeamId, canEdit, and optional prefilterAgentId. The sidebar can filter flows whose primaryAgentId matches a selected specialist; the header scope control can emit select-team when you pick another dashboard—keeping lists consistent with the board you are viewing.

Local editing buffer

Changes stay in component state until you save—Run test always reads the latest normalized graph including unsaved canvas tweaks when the parent wires it that way.

Integrations entry

autoOpenIntegrationsFlyout can expand the credentials menu once—useful when launching Scenarios from an Assets or integration shortcut without hunting the dock.

Help string

Status info pulls scenarios lead, hotkeys line, and footer copy from uiStrings—so keyboard power users see the same guidance as mouse operators.

Where scenarios plug in

Same agents, tables, and API surface

Task steps use real agents from your roster; web rules match Tables. Heavier scheduled automation also lives in To do, Backlog, and Agent API—Scenarios are great for guided checks and manual test hops you design on the canvas.

Model cross-system checks, then flip dry run off once

Build the graph with manual triggers, validate order and skips, then run live with pause/rescue patterns your team already uses on the board.