Documentation / Advanced

Bound work and policy decisions

Put limits around the workflow, not just individual handlers. An allow decision must still satisfy authority, budget and ownership checks.

Bound the run

Limit iterations, phase executions, handler/tool/external calls, duration, retries, recovery and concurrent operations. maxChildWorkflows limits child operations; it does not create a new sub-workflow phase API.

json
{
  "maxIterations": 4,
  "maxToolCalls": 8,
  "maxConcurrentOperations": 2,
  "maxDuration": "30m"
}
Complete example · JSON / YAML

JSON

json
{
  "name": "advanced-controls",
  "version": "1.0.0",
  "lanes": {
    "inline": {
      "mode": "sync_lambda",
      "target": "lambda://local-inline"
    }
  },
  "phases": {
    "work": {
      "service": "hello",
      "lane": "inline",
      "scope": "root",
      "terminal": true
    }
  },
  "controls": {
    "policyVersion": 1,
    "limits": {
      "maxIterations": 4,
      "maxToolCalls": 8,
      "maxHandlerInvocations": 12,
      "maxConcurrentOperations": 2,
      "maxDuration": "30m",
      "maxChildWorkflows": 2,
      "maxRetries": 2,
      "maxRecoveryAttempts": 2
    },
    "hooks": {
      "before_external_side_effect": {
        "handler": "policy.check",
        "timeout": "5s",
        "onFailure": "deny"
      }
    }
  }
}

YAML

yaml
name: advanced-controls
version: 1.0.0
lanes:
  inline:
    mode: sync_lambda
    target: lambda://local-inline
phases:
  work:
    service: hello
    lane: inline
    scope: root
    terminal: true
controls:
  policyVersion: 1
  limits:
    maxIterations: 4
    maxToolCalls: 8
    maxHandlerInvocations: 12
    maxConcurrentOperations: 2
    maxDuration: 30m
    maxChildWorkflows: 2
    maxRetries: 2
    maxRecoveryAttempts: 2
  hooks:
    before_external_side_effect:
      handler: policy.check
      timeout: 5s
      onFailure: deny

Download JSON · YAML

shell
rippflow controls validate advanced-controls.workflow.yaml --json

Expected: ok: true. This checks the contract; deployment/enforcement is separate.

Give loops a termination condition

A loop needs both a bound and an until predicate. Its body names sub-phase handlers. Reaching a control limit follows the configured violation action; it is different from QA rework fallback.

json
{
  "type": "loop",
  "controls": {
    "limits": {
      "maxIterations": 3
    }
  },
  "until": {
    "resultPath": "$.approved",
    "equals": true
  }
}
Complete example · JSON / YAML

JSON

json
{
  "name": "advanced-bounded-loop",
  "version": "1.0.0",
  "phases": [
    {
      "id": "review",
      "type": "loop",
      "service": "hello",
      "until": {
        "resultPath": "$.approved",
        "equals": true
      },
      "controls": {
        "limits": {
          "maxIterations": 3
        }
      },
      "body": [
        {
          "id": "revise",
          "handler": "hello"
        }
      ],
      "terminal": true
    }
  ]
}

YAML

yaml
name: advanced-bounded-loop
version: 1.0.0
phases:
  - id: review
    type: loop
    service: hello
    until:
      resultPath: $.approved
      equals: true
    controls:
      limits:
        maxIterations: 3
    body:
      - id: revise
        handler: hello
    terminal: true

Download JSON · YAML

shell
rippflow controls validate advanced-loop.workflow.yaml --json

Expected: ok: true. This checks the contract; deployment/enforcement is separate.

Keep hooks fail-closed

Lifecycle hooks can allow, deny, pause, defer for retry, require approval, terminate or quarantine. Configure onFailure: deny for sensitive checks. Hook timeouts are 100 ms–30 seconds. A dry-run validates admission policy; it does not execute your hook or prove every future side-effect decision.

json
{
  "before_external_side_effect": {
    "handler": "policy.check",
    "timeout": "5s",
    "onFailure": "deny"
  }
}
Verified sources

Checked 2026-11-05.

Let's talk

Contact Rippflow

Tell us about your workflows, deployment or pricing.

We'll reply to your email.

Search docs

Search workflows, handlers and operations.