Skip to content

Build a Governed Flow in VB-OS

Flows define what happens after a boundary evaluation produces a verdict. They are directed acyclic graphs (DAGs) of nodes and edges that route to different actions depending on whether the evaluation returned ASSERT or DEFER.

  • Webhook dispatch: send evaluation results to external systems on ASSERT or DEFER
  • Notifications: alert operators when a boundary produces DEFER
  • Conditional routing: check evidence field values to decide which actions fire
  • Logging: record structured log entries for specific evaluation outcomes
POST /v1/projects/{project_id}/flows
Content-Type: application/json
{
"name": "payment-verification-reactions",
"description": "Dispatch webhooks and notifications after payment boundary evaluation"
}

The flow is created in DRAFT status.

Step 2: Create a Version with Nodes and Edges

Section titled “Step 2: Create a Version with Nodes and Edges”

A flow version contains the full DAG definition. Define the nodes (trigger, evidence, boundary, condition, and action nodes) and the edges that connect them.

POST /v1/projects/{project_id}/flows/{flow_id}/versions
Content-Type: application/json
{
"definition": {
"schema_version": 1,
"nodes": [
{
"id": "trigger-1",
"type": "trigger",
"config": {}
},
{
"id": "evidence-1",
"type": "evidence",
"config": {
"declared_evidence_fields": ["transaction_amount", "risk_score"]
}
},
{
"id": "boundary-1",
"type": "boundary",
"config": {
"boundary_ref": "payment-authorization",
"boundary_version_id": "BOUNDARY_VERSION_UUID"
}
},
{
"id": "assert-webhook",
"type": "assert_action",
"config": {
"action_type": "webhook",
"url": "https://example.com/hooks/approved",
"max_attempts": 3,
"backoff_seconds": 5,
"evidence_disclosure_projection": ["transaction_amount"]
}
},
{
"id": "defer-notify",
"type": "defer_action",
"config": {
"action_type": "notification",
"title": "Payment deferred",
"body": "A payment evaluation was deferred"
}
},
{
"id": "defer-log",
"type": "defer_action",
"config": {
"action_type": "log",
"message": "Payment deferred for review"
}
}
],
"edges": [
{ "id": "e1", "source": "trigger-1", "target": "evidence-1" },
{ "id": "e2", "source": "evidence-1", "target": "boundary-1" },
{ "id": "e3", "source": "boundary-1", "target": "assert-webhook", "label": "assert" },
{ "id": "e4", "source": "boundary-1", "target": "defer-notify", "label": "defer" },
{ "id": "e5", "source": "boundary-1", "target": "defer-log", "label": "defer" }
]
}
}

Approval runs full semantic validation (DAG acyclicity, branch isolation, reachability, fail-closed check). Deployment binds the version to a specific environment.

POST /v1/projects/{project_id}/flows/{flow_id}/versions/{version_id}/approve
POST /v1/projects/{project_id}/flows/{flow_id}/versions/{version_id}/deploy
Content-Type: application/json
{
"environment_id": "ENVIRONMENT_UUID"
}

Before deploying, activate the flow:

PATCH /v1/projects/{project_id}/flows/{flow_id}
Content-Type: application/json
{
"status": "ACTIVE"
}

When a boundary evaluation completes in the deployed environment, the platform matches active flow deployments by environment and boundary version. The flow walks the DAG from the boundary node, follows the edge matching the decision (ASSERT or DEFER), evaluates any condition nodes, and creates action dispatches for each reachable action node.

There is no “execute flow” API. Flows fire automatically when a matching evaluation occurs.

Test a flow version without creating a real execution:

POST /v1/projects/{project_id}/flows/{flow_id}/versions/{version_id}/dry-run
Content-Type: application/json
{
"decision": "DEFER",
"evidence": {
"transaction_amount": 15000,
"risk_score": 85
}
}

The dry run returns the DAG path that would be taken and which action nodes would fire, without dispatching any actions.