Component reference
A practical guide to every building block in the component library: what it represents, where it connects, which settings you can change, and a small example.
How to read this page
Each entry starts with the component's ports — the connection points shown in the editor — and its settings. Then a use case shows the component doing its job in a small diagram. Port purposes are explained in Components & ports; the arrow styles follow the connection types.
Sources & triggers
Routing & compute
Data & state
Messaging
Control & orchestration
Boundaries & helpers
The editor is the final source for the choices available in your workspace. This page uses the same live component catalog, so its ports and settings stay aligned with the product.
Sources & triggers
Source components are where runs begin. An actor models traffic that a person or client system starts on demand; a scheduler models traffic that time starts for you.
Actor / clientTakes part in a run
Starts a bounded request and receives its explicit response.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | out | request | request | required |
| response | in | response | response | — |
| event | out | enqueue | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Request count | Root requests emitted for this journey. | 1–1,000 | 1 |
| Interval (ms) | Virtual milliseconds between root requests. | 0–3,600,000 | 0 |
Use case — a shopper checks out
A shopper presses Buy in a web shop. The actor’s request port starts the journey and its response port receives the final answer — that round trip is the story most journeys tell. Set Request count to 5 and Interval (ms) to 200 and the same actor becomes a small burst of shoppers, with each request visible throughout the run.
The event output is for things the client sends without waiting — an analytics beacon dropped onto a queue, or an event published to a topic — so you can model “tell and move on” traffic from the same actor that makes requests.
The actor's response input is the optional return half of a request. When this actor or a scheduler is selected as a journey start, the selected output must have exactly one executable route; use separate source components for separate public starts.
In a run you’ll see: TOKEN_EMITTED · CALL_STARTED · RESPONSE_RECEIVED · CALL_COMPLETED
Scheduler / triggerTakes part in a run
Starts bounded scheduled work by emitting tick events at a fixed virtual interval.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| tick | out | enqueue | event | required |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Tick count | Scheduled ticks emitted for this journey. | 1–100 | 1 |
| Interval (ms) | Descriptive virtual schedule duration; a journey may use a shorter run horizon. | 0–31,536,000,000 | 1000 |
| Start offset (ms) | Descriptive virtual schedule duration; a journey may use a shorter run horizon. | 0–31,536,000,000 | 0 |
Use case — a nightly report job
Nothing clicks a button at 2 a.m. — a schedule does. Here the scheduler stands in for a cron job: each tick drops a job onto a queue, and a worker service builds the report. Set Tick count to 3 and Interval (ms) to 60,000 to watch three job cycles play out — including what happens when one of them fails and retries.
The tick port sends events, so it plugs into anything that consumes events: a queue’s enqueue, a service’s event input, or a topic’s publish. Ticks are bounded — the run emits exactly the count you configure, after the Start offset (ms) and spaced by Interval (ms) in virtual time — so a scheduled journey always finishes. If the descriptive schedule extends past the run horizon, the compiler warns that the later ticks will not be reached.
In a run you’ll see: TOKEN_EMITTED · QUEUE_ENQUEUED · QUEUE_DEQUEUED
Routing & compute
These are the components that carry a request through the middle of a system: the gateway decides where traffic goes, services do the work, and transforms reshape data on the way through.
Gateway / routerTakes part in a run
Validates and routes a request through ordered rules.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request in | in | request | request | required |
| request out | out | request | request | required |
| response in | in | response | response | — |
| response out | out | response | response | — |
| error | out | terminal | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Route mode | How ordered routing rules choose a branch. | first-match | first-match |
Use case — a public API edge
A mobile app calls your public API. The gateway checks each request and routes it onward using its outgoing request connections as ordered rules — the connection priorities set the order, and with first-match routing the first rule that applies wins. Requests the gateway refuses leave through the error port instead, so a rejection is a visible route in the diagram, not a silent dead end.
The responses flow back through the gateway’s response in and response out ports. You never draw those return connections yourself — they’re paired automatically when you draw the forward requests — so the caller always gets an answer through the same route it called.
In a run you’ll see: ROUTE_EVALUATED · ROUTE_SELECTED · RESPONSE_SENT
Service / functionTakes part in a run
Performs bounded compute and explicit downstream calls.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request in | in | request | request | required |
| call | out | request | request | — |
| return | in | response | response | — |
| response | out | response | response | required |
| data command | out | write | command | — |
| data result | in | read | record | — |
| event | in | consume | event | — |
| ACK | out | ack | response | — |
| NACK | out | nack | response | — |
| publish event | out | enqueue | event | — |
| write record | out | write | record | — |
| publish event | out | publish | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Operation | Safe, provider-neutral service behavior. | pass-through | worker | pass-through |
| Duration (ms) | Illustrative virtual execution duration. | 0–3,600,000 | 10 |
Use case — a checkout service orchestrating a purchase
The service is the workhorse of most diagrams. This checkout service receives an order on request in, then uses three different kinds of ports for three different conversations: call / return to ask the auth service a question and wait, data command / data result to read the orders database, and publish event to announce the finished order without waiting for anyone.
What the service does with these connections — and in which order — is its handler: call auth, load the order, publish the event, respond. Switch Operation to worker and the same component plays the other classic service part: consuming messages from a queue through event in and reporting its verdict through ACK / NACK.
Choose the port by the conversation you are modeling. Command out sends a write command; record in receives a record; record out writes a record; event in consumes an event; and event out, publish out, or a named custom event output publishes an event. The ACK and NACK outputs belong to queue delivery, not to a synchronous response.
In a run you’ll see: NODE_ENTERED · CALL_STARTED · CALLER_WAITING · RESPONSE_SENT · NODE_EXITED
TransformTakes part in a run
Projects and validates bounded request or record payloads without arbitrary code.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
| record input | in | read | record | — |
| record output | out | write | record | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Mapping | Allowlisted payload mapping for this transform. | identity | identity |
Use case — normalizing a legacy record
A profile service reads customers from a legacy database whose records don’t match what the rest of the system expects. Placing a transform between the database result and the service makes that reshaping an explicit, visible step — the payload before and after the transform shows up in the run, which is exactly where data-shape surprises like to hide.
The current mapping choice is identity: the transform validates and passes the payload through unchanged. The current catalog exposes both a request/response path and a record input/output path; use the path whose message kind matches the connection. If you author actions for the arrival, those actions control the route instead of the untouched identity fallback.
In a run you’ll see: SCHEMA_VALIDATED · TRANSFORM_APPLIED
Data & state
State components remember things between steps of a run. What they hold at the start comes from your journey’s fixtures; what they hold at the end is part of the story the run tells.
Cache / key-value storeTakes part in a run
Models explicit get, set and delete operations with lazy TTL.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| lookup | in | read | command | required |
| hit | out | response | record | — |
| miss | out | response | record | — |
| write | in | write | record | — |
| written | out | ack | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| TTL (ms) | Virtual lifetime of a cached value. | 0–31,536,000,000 | 60000 |
| Key path | Bounded payload path used as the cache key. | text | /key |
Use case — cache-aside session lookup
A session service checks the cache before touching the database. The cache’s defining feature is that hit and miss are separate output ports, so the fast path and the slow path are two different routes you can see and follow. On a miss the service loads from the database — and the database’s result can feed the cache’s write port directly, modeling the write-back that makes the next lookup a hit.
The TTL setting gives every entry a virtual lifetime, and Key path says which part of the payload identifies the entry (like /sessionId). Preload entries through journey fixtures to start a run with a warm cache — or leave it cold and watch the misses.
Key paths are JSON Pointers. A lookup uses the configured pointer when it resolves; scalar values are stringified and composite values are canonicalized. If the pointer is missing or cannot resolve, the runtime falls back to the correlation or token identity. An entry expires lazily when a lookup reaches its expiry time, so a lookup at or after the TTL is a miss. A zero TTL therefore expires an entry at the same virtual time as the write.
In a run you’ll see: CACHE_LOOKUP · CACHE_HIT · CACHE_MISS · CACHE_WRITE · CACHE_EXPIRED
DatabaseTakes part in a run
Reads and deterministically mutates bounded journey fixture records. Get preserves the input payload and adds /record; query adds /records.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| query | in | read | command | required |
| result | out | response | record | required |
| write | in | write | command | — |
| written | out | ack | response | — |
| record read | in | read | record | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Collection | Journey fixture collection used by the database. | text | records |
| Record path | RFC 6901 JSON Pointer evaluated from the write payload root to select the record. | text | (empty) |
| Key path | RFC 6901 JSON Pointer selecting the stable key: reads evaluate it from the payload root, while writes evaluate it from the record selected by recordPath. | text | /id |
| Read operation | Operation used for arrivals at queryIn. Get merges its result at /record; query merges results at /records. | get | query | get |
| Write operation | Operation used for arrivals at writeIn. | insert | update | upsert | delete | upsert |
Use case — the orders system of record
The database holds the records your journey cares about. An order service reads through query / result and mutates through write / written — two explicit conversations, so reads and writes are separate arrows you can trace in the run. In the current catalog, Read operation choosesget or query and Write operation choosesinsert, update, upsert, or delete against the configured collection. The defaults areget and upsert.
Records come from your journey’s fixtures — you decide exactly which rows exist before the run starts, which is what makes runs repeatable. Writes during the run show up as state patches you can inspect afterwards.
For a write, Record path is a JSON Pointer to the object that should be stored, and Key path is evaluated inside that object to find its stable key. With {"job":{"jobId":"job-1001"}}, use /job and /jobId. An empty record path selects the whole incoming value. Connect get and query to the query port; connect insert, update, upsert, and delete to the write port. A get result is added at /record; a query result is added at /records.
The current v1.3 read path is query in. The catalog keepsread in for older graph versions, but a current get/query interaction connected to that legacy port fails at runtime with an operation-port mismatch. For writes, an insert/update/delete can fail when its key or record is missing or conflicts with the selected operation. Keep the record and key pointers valid RFC 6901 JSON Pointers.
Database fixtures are grouped by the configured collection name. A database configured for jobs, for example, starts from a fixture shaped like {"jobs":{"job-1001":{...}}}. Each run receives its own copy; mutations never alter the saved journey fixture.
In a run you’ll see: DB_READ · DB_RESULT · DB_MUTATION · STATE_PATCH_APPLIED
Object storageTakes part in a run
Stores opaque objects behind explicit put, get and delete operations; tokens carry object references, never blob bytes.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| put | in | write | command | required |
| stored | out | ack | response | — |
| get | in | read | command | required |
| object | out | response | record | — |
| missing | out | response | record | — |
| delete | in | write | command | — |
| deleted | out | ack | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Bucket | Journey fixture namespace holding this store's objects. | text | objects |
| Key path | RFC 6901 payload pointer resolving the string, number, or boolean object key. | text | /key |
Use case — an image upload pipeline
An upload API stores a photo, and a thumbnailer fetches it later. Object storage models the S3-style half of that story: put stores an object and acknowledges through stored; get looks one up and branches — object when it exists, missing when it doesn’t — so the not-found path is a real route, just like a cache miss.
Tokens never carry the object’s bytes — only a reference (its key and metadata), the way real systems pass presigned URLs instead of file contents. The Bucket setting names the fixture namespace the store reads and writes. A get is one synchronous interaction: both the object and missing returns lead to the caller's record arrival. Put and delete acknowledgements are responses instead: stored and deleted lead to the caller's response arrival. The Key path must resolve to a string, number, or boolean; an absent or non-scalar key fails the operation. The compiler also requires the get interaction to include both the object and missing return routes, and authored actions on get in are not supported.
In a run you’ll see: OBJECT_PUT · OBJECT_GET · OBJECT_MISSING · OBJECT_DELETED
Messaging
Messaging components decouple the sender from the receiver. The queue is point-to-point — one message, one consumer, with retries. The topic is broadcast — one event, every subscriber. Together they cover most of the asynchronous patterns in modern systems.
QueueTakes part in a run
Models bounded competing consumers, retries and explicit dead-letter routing.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| enqueue | in | enqueue | event | required |
| dispatch | out | request | event | required · max 1 connection |
| ACK | in | ack | response | — |
| NACK | in | nack | response | — |
| DLQ | out | terminal | event | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Maximum attempts | Total delivery attempts before dead-letter routing. | 1–100 | 3 |
| Backoff (ms) | Virtual delay before a retry becomes available. | 0–31,536,000,000 | 1000 |
| Consumer slots | Maximum deterministic deliveries active at the same virtual time. | 1–100 | 1 |
Use case — a fulfilment worker with retries and a DLQ
Checkout finishes and hands fulfilment to a queue so the customer never waits on it. The queue dispatches each message to its single consumer — the worker — which reports back through ACK or NACK. A NACK sends the message back for another attempt after the configured backoff; when Maximum attempts runs out, the message takes the DLQ route instead of retrying forever.
The dispatch port accepts one connection, so the queue sends work to one consumer. Consumer slots controls how many deliveries that consumer may have active at once; it does not add more dispatch connections. Maximum attempts includes the first delivery, so a value of 3 permits the initial attempt plus two retries. Watching a message bounce through MESSAGE_REQUEUED into MESSAGE_DEAD_LETTERED is one of the most instructive stories Mockflow can tell.
A worker sends ACK or NACK back to the queue. ACK completes that delivery. NACK schedules another delivery after the virtual Backoff (ms) until the attempt limit is reached; then the queue emits its dead-letter event and uses DLQ out when it is connected. Without a DLQ route, the exhausted delivery still ends rather than retrying forever.
In a run you’ll see: QUEUE_ENQUEUED · QUEUE_AVAILABLE · QUEUE_DEQUEUED · MESSAGE_ACKED · MESSAGE_REQUEUED · MESSAGE_DEAD_LETTERED
Topic / event busTakes part in a run
Broadcasts one published event to every subscription, forking a correlated child token per subscriber with recorded lineage.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| publish | in | publish | event | required |
| deliver | out | subscribe | event | required |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Delivery mode | How published events fan out to subscriptions. | all-subscribers | all-subscribers |
Use case — fanning out an order-placed event
When an order is placed, three unrelated parts of the system care: email wants to confirm it, analytics wants to count it, loyalty wants to award points. Instead of the checkout calling all three, it publishes one event to a topic. Every connection drawn from the topic’s deliver port is a subscription, and each subscriber receives its own copy.
Each subscription receives its own copy of the event. Want a subscriber to get retries and a dead-letter path? Send that subscription to a queue first.
A topic has no queue state or retry policy of its own. Conditions are supported on the topic's deliver subscription edges; a false condition skips that subscriber. A published event creates a correlated child token for each selected subscriber, so a join after the topic can gather one fan-out wave.
In a run you’ll see: TOPIC_PUBLISHED · TOKEN_FORKED · TOKEN_COMPLETED
Queue or topic? Ask who should handle the message. Exactly one consumer, with retries — queue. Everyone who subscribed, each with their own copy — topic.
Control & orchestration
Control components shape when and how work happens: pausing it, gathering parallel branches back together, and driving multi-step processes to completion.
Timer / delayTakes part in a run
Advances virtual time and resumes through an explicit output.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Duration (ms) | Virtual time advanced before the output resumes. | 0–31,536,000,000 | 1000 |
Use case — an explicit pause in the flow
Real systems are full of deliberate waits: a cool-down before a retry, a grace period before an escalation. The timer makes that wait a visible box in the diagram. A request arriving at request advances the run’s virtual clock by the configured duration, then continues through response — nothing hidden, no implicit delays.
The current ports carry a request and its response, so the timer keeps the caller’s synchronous interaction paired while advancing virtual time. In the run you can watch the virtual clock jump: the wait costs virtual time, never real time. Older timer graph versions may expose the equivalent start / elapsed control ports.
In a run you’ll see: WAIT_STARTED · WAIT_COMPLETED
Join / aggregatorTakes part in a run
Waits for correlated branch arrivals and lets one satisfying token continue once its policy is met, completing earlier arrivals at the barrier.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| branch | in | join | event | required |
| joined | out | join | event | required · max 1 connection |
| timeout | out | terminal | event | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Join policy | How many correlated branches must arrive before continuing. | all | any | count | all |
| Required count | Branches to await when the policy is Exact count. | 1–64 | 2 |
| Timeout (ms) | Virtual milliseconds before an unsatisfied group continues through timeout (0 preserves unresolved-barrier behavior). | 0–3,600,000 | 0 |
Use case — scatter-gather price quotes
A travel site asks two suppliers for a price at the same time and can only answer once both quotes are in. The fan-out half is a topic; the fan-in half is the join. Each supplier’s answer arrives at branch, and the join waits at the barrier until its policy is met — all branches, any branch, or an exact count (a quorum). Then the story continues through joined.
Mockflow keeps branches from the same request together, so two shoppers' quotes never mix. The branch that satisfies the policy is the one that continues.
Join policies count distinct inbound branch edges in one fan-out wave; repeated arrivals from one branch do not satisfy all or an exact count. A count cannot exceed the statically reachable branches (or a bounded for each iteration). One join wave must share fork history — either all descending from the same fan-out, or none forked at all; mixing a forked branch with a never-forked one won’t meet. Set a positive Timeout (ms) to send an unsatisfied group through timeout. An arrival exactly at the deadline wins before the timeout fires; with timeout 0, an incomplete barrier remains unresolved.
In a run you’ll see: JOIN_ARRIVED · JOIN_SATISFIED · JOIN_TIMED_OUT · TOKEN_JOINED
Workflow / sagaTakes part in a run
Runs graph-derived steps sequentially as a durable saga, answering its caller once every step completes.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| start | in | request | request | required |
| step | out | request | request | required |
| step result | in | response | response | required |
| compensate | out | control | event | — |
| completed | out | response | response | required · max 1 connection |
| failed | out | terminal | response | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| On step failure | How the workflow reacts when a step fails; after at least one earlier step completes, compensation dispatches every connected route without waiting for acknowledgement. | compensate | fail-fast | compensate |
Use case — an order saga, step by step
Placing an order really means several things in a row: reserve the stock, charge the payment. The workflow receives the original request on start, then drives each outgoing step connection as one sequential step — the connection priorities set the order. Each step is an ordinary synchronous call whose answer returns on step result; when the last step completes, the workflow answers its caller through completed.
Workflow steps run by the unique priority on each step request: lower values run first. MCP and editor authoring append omitted priorities, and WORKFLOW_STARTED reports the resolved order. A failed step returns through failed so the synchronous caller can close its continuation; that return edge uses the error kind. With Compensate completed steps, every compensate connections are dispatched as detached fire-and-forget work once for each completed step, in reverse step order. The compensation event records dispatch, not acknowledgement. A fail action ends that handler activation immediately: earlier effects remain, but later actions do not run.
In a run you’ll see: WORKFLOW_STARTED · WORKFLOW_STEP_STARTED · WORKFLOW_STEP_COMPLETED · WORKFLOW_STEP_FAILED · WORKFLOW_COMPLETED · WORKFLOW_FAILED · WORKFLOW_COMPENSATED
Boundaries & canvas helpers
The external dependency marks the edge of the world you’re modeling; groups and notes keep the picture readable without affecting behavior at all.
External dependency / terminalTakes part in a run
Models a fixed-latency dependency that answers synchronous calls with a configured success or failure outcome.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
| event | in | terminal | event | — |
| callback request | out | request | request | — |
| callback response | in | response | response | — |
| publish event | out | publish | event | — |
| data command | out | write | command | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Mode | Fixed provider-neutral dependency outcome. | success | failure | success |
| Outcome | Named terminal outcome shown in the story. | text | completed |
| Latency (ms) | Virtual milliseconds before the configured boundary outcome. | 0–3,600,000 | 10 |
Use case — a payment provider you don’t control
Your checkout calls a payment provider, but the provider’s internals aren’t your story — only its answers are. The external dependency stands in for it: after the latency you choose, success mode replies through the matching interaction, while failure mode fails with the named outcome. Flip one setting and the same diagram tells the sad-path story — what your system does when payments are down.
Its event input also makes it a terminal sink: point a queue’s DLQ or any fire-and-forget event at it to give a story an explicit, named ending — “lands in ops audit” — instead of trailing off the edge of the diagram.
The current boundary also exposes callback and publish ports:request out can start a callback request, response in receives its return, event out publishes an event, and command out sends a write command. The intrinsic fixed-outcome behavior applies to an untouched request in: success needs its matching response out route; failure raises the configured outcome and does not use an error output. Other ports need authored handlers.
In a run you’ll see: RESPONSE_SENT · ERROR_RAISED
Diagram linkTakes part in a run
References another diagram in this workspace as a typed boundary; answers callers with a configured outcome and navigates to the linked diagram in the editor.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | required |
| response | out | response | response | — |
| error | out | terminal | control | — |
| event out | out | publish | event | — |
| event in | in | subscribe | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Linked diagram | Opaque UUID of the target diagram in this workspace; empty means unlinked. Format is checked in pure validation, existence never is. | text | (empty) |
| Mode | Fixed provider-neutral boundary outcome for synchronous calls. | success | failure | success |
| Outcome | Named outcome attached to the response or terminal exit. | text | ok |
| Latency (ms) | Deterministic virtual-time service latency before answering. | 0–3,600,000 | 10 |
Use case — decomposing a big estate into diagrams
A real system is many diagrams, not one enormous canvas. A diagram link stands in for another diagram in the workspace: your order flow can point to Accounts without redrawing it. Select the node, choose the target diagram, then use Open to visit it. Mockflow leaves a trail back to the original diagram.
During a run, the link acts as a boundary with the success, failure, outcome, and delay you set on the link itself. It does not run the contents of the other diagram. This keeps the current story focused and predictable.
On an untouched request, success follows the matching response out route, or the first response route when no interaction match is available; if there is no response route, the token completes. Failure takes the first error out route when one is connected and otherwise ends the token with the configured outcome. An empty or malformed target ID is shown as an advisory unlinked/broken state; it does not make the host graph's pure configuration validation fail.
If the target is removed or you lose access to it, the node shows a broken-link state. The rest of the current diagram can still be opened, saved, and run.
In a shared view, a diagram link is shown as a labeled boundary. The viewer cannot open the linked diagram unless it was shared separately.
In a run you’ll see: RESPONSE_SENT · ERROR_RAISED
Group / boundaryVisual helper
Organizes trust zones, regions, systems or teams without executing.
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Collapsed | Hide child components while preserving the boundary. | on | off | false |
Use case — showing who owns what
A diagram that mixes two teams’ services needs boundaries. Draw a group around the payments components and label it — reviewers instantly see ownership, trust zones, or regions. Collapse a group to hide its children while you focus elsewhere; expand it when the detail matters again. Groups never execute and never change a run.
Note / legendVisual helper
Adds plain-text documentation without affecting behavior.
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Note text | Plain-text documentation; markup is never executed. | text | (empty) |
| Fit canvas note to content | Grow the canvas note vertically so its complete plain-text content remains visible. | on | off | true |
Use case — explaining the diagram to the next reader
Notes hold the things a diagram alone can’t say: assumptions (“charges are idempotent”), pointers (“see the retry journey”), or a legend for your labels — as in the figure above. Note text is always plain text: it’s never executed, never rendered as markup, and never affects a run.
The note text is limited to 2,000 characters and preserves line breaks. Fit canvas note to content grows the note vertically so the plain text remains visible; when it is off, you can set the note's width and height directly. The optional inspector description is context for editors and is not shown on the canvas.
Authoring & runtime rules
The live catalog supplies the port and setting tables above. These rules explain the parts that are easy to miss when you only look at a component in isolation.
A connection must run from an output to an input with the same message kind and payload contract. The editor derives the connection kind from the port roles. A response connection is the reverse half of a synchronous request; keep the request and its response paired with the same interaction.
Handlers and default behavior
Every input port has one ordered handler. An empty catalog_default handler has no actions, so components that use the generic executor do not invent a route from their connections. Add an explicit handler action — for example call, emit, respond, assign, or fail — when the input should continue the story. The handler reference describes the action sequence and catch rules.
Components with an intrinsic executor — including cache, database, queue, timer, external, transform, object storage, topic, join, and workflow — have documented default paths. Authored actions can control the supported handler paths, while some intrinsic paths remain fixed: object storage get, for example, must use its object/missing interaction rather than an authored handler. The compiler reports unsupported combinations before a run.
Starts, fan-in, and resilience
A journey start is one selected output from an actor or scheduler, or an external component's request/event output. That output must have exactly one executable route. A topic may fan out after the start, but the selected start itself cannot be multiply routed.
Join arrivals are counted by distinct inbound branch edges within one fan-out wave. Repeated arrivals from the same branch do not satisfy a multi-branch policy. A positive join timeout creates a virtual-time deadline; with the default zero timeout, an incomplete barrier remains unresolved and a drained run reports it.
Interaction resilience belongs to a synchronous request/response interaction and is owned by the component that sends the request. Its settings are timeout, maximum attempts, fixed or exponential backoff, and retryable outcomes: timeout, network_error, http_429, or http_5xx. One-way event interactions do not have a caller return path, so the graph validator rejects a resilience policy on them.
Outputs, custom events, and simulation limits
An output port can have an optional JSON Schema or an inferred schema from an example payload. That describes the output for inspection and validation; it does not add a connection or change simulation behavior. Protocol-bound outputs keep their intrinsic result contract.
Services can add named event outputs for separate publish routes. A label is trimmed and normalized, must be non-empty, and is limited to 80 characters. A service can have at most 64 graph ports, and a custom event output must be disconnected before it can be removed. Use the canonical event out or publish out port when a named custom route is not needed.
The Behavior tab also supports simulation-only traffic limits. Requests over time is a sliding window counter: it records all attempts for a global, payload-keyed, or variable-keyed bucket and rejects attempts above its limit. Requests at once is a capacity limit: it admits up to Maximum concurrent, queues up to Maximum queued, and rejects work beyond both. These limits affect runs only, not a real deployment. New limits default to 60,000 ms and 120 attempts with rate_limited, or 8 concurrent and 0 queued with capacity_exhausted. Keyed limits use RFC 6901 JSON pointers and expose only a derived key hash in runtime events.