Workflow sequence
- 01Receive message and attachments
- 02Deduplicate by message ID
- 03Extract supplier and line items
- 04Validate totals and currency
- 05Request review when uncertain
- 06Write rows with source links
Sequence definition
Use this sequence definition as a starting point. Set tenant_id to your tenant and use a fresh UUID for id before publishing. Implement the named business handlers in your workers; the JSON does not include provider integrations. Keep credentials in the credential store.
{
"id": "423e32ab-b5de-5df1-941c-94256baff489",
"tenant_id": "demo",
"namespace": "default",
"name": "whatsapp_quotes_to_excel_v1",
"version": 1,
"deprecated": false,
"blocks": [
{
"type": "step",
"id": "dedupe",
"handler": "deduplicate_message",
"params": {}
},
{
"type": "step",
"id": "extract",
"handler": "extract_quote",
"params": {}
},
{
"type": "step",
"id": "validate",
"handler": "validate_quote_totals",
"params": {}
},
{
"type": "router",
"id": "confidence_gate",
"routes": [
{
"condition": "outputs.extract.confidence < 0.9",
"blocks": [
{
"type": "step",
"id": "review",
"handler": "human_review",
"params": {},
"wait_for_input": {
"prompt": "Approve extracted quote rows?",
"timeout": 86400000,
"store_as": "review_decision",
"choices": [
{
"label": "Approve",
"value": "approved"
},
{
"label": "Reject",
"value": "rejected"
}
]
}
}
]
}
],
"default": []
},
{
"type": "step",
"id": "write",
"handler": "append_excel_rows",
"params": {
"idempotency_key": "{{context.data.message_id}}"
},
"when": "outputs.extract.confidence >= 0.9 || context.data.review_decision == "approved""
}
],
"created_at": "2026-09-05T00:00:00Z"
}Handlers must validate required inputs and outputs. Quote extraction returns confidence; document validation returns needs_review; source archiving returns sha256. Guards read these values through outputs, and approval decisions through context.data.
Idempotency keys in params are a contract for your worker to enforce at the provider. They do not make an external write exactly-once automatically.
Steps with wait_for_input resume through an authorized human_input:{block_id} signal carrying a declared choice. A CRM or scheduling integration may supply a verified choice. Timeouts fail the wait; they do not select a follow-up or escalation branch automatically. Configure alerts and recovery for timed-out runs before production.
Review rejection skips the guarded publish or spreadsheet write. No write is authorized merely because the review step finished.
Production controls to keep
✓ Stable idempotency keys around external writes
✓ Explicit validation before the success state
✓ Bounded retries with provider-aware backoff
✓ Searchable source and destination identifiers
✓ A named owner for exhausted retries
✓ A replay test using duplicate input