Skip to content

Feature 6: Success Criteria and Actions

Structural Results | Next: Execution Model →


UWS defines a first-class vocabulary for deciding whether an operation succeeded, and for specifying what to do when it did or did not. Criteria and actions are declared inline on the operation — there is no shared registry.

Criterion Object

A Criterion describes a condition to evaluate:

Field Required Description
condition REQUIRED Runtime expression or literal condition
type optional simple (default), regex, jsonpath, or xpath
context REQUIRED when type is regex, jsonpath, or xpath Value to apply the condition against

simple type (default) — uses the normative comparison grammar:

successCriteria:
  - condition: $response.statusCode == 200
  - condition: $response.body.success == true
  - condition: $response.body.count > 0

regex type — tests a string value against a regular expression:

successCriteria:
  - condition: "^(200|201|204)$"
    type: regex
    context: $response.statusCode

jsonpath type — evaluates a JSONPath expression against a context value:

successCriteria:
  - condition: "$.items[?(@.status == 'active')]"
    type: jsonpath
    context: $response.body

xpath type — evaluates an XPath expression against an XML context:

successCriteria:
  - condition: "//order[@status='confirmed']"
    type: xpath
    context: $response.body

Failure Actions

onFailure fires when the operation's successCriteria are not satisfied:

Field Required Description
name REQUIRED Unique action name
type REQUIRED end, goto, or retry
workflowId REQUIRED for goto (exactly one of workflowId/stepId) Target workflow
stepId REQUIRED for goto (exactly one of workflowId/stepId) Target step
retryAfter optional Seconds to wait before retrying. MUST be ≥ 0
retryLimit REQUIRED for retry Maximum retry attempts. MUST be ≥ 1
criteria optional Additional conditions that scope this action

Success Actions

onSuccess fires when the operation's successCriteria are all satisfied:

Field Required Description
name REQUIRED Unique action name
type REQUIRED end or goto
workflowId REQUIRED for goto (exactly one of workflowId/stepId) Target workflow
stepId REQUIRED for goto (exactly one of workflowId/stepId) Target step
criteria optional Additional conditions that scope this action

Example 1: Retry and Failure Routing

Retry server errors up to 3 times; end cleanly on client errors; route unmatched failures to an error handler.

operationId: charge_payment
sourceDescription: stripe_api
openapiOperationId: createCharge
successCriteria:
  - condition: $response.statusCode == 200
  - condition: $response.body.status == "succeeded"
onFailure:
  - name: retry_on_5xx
    type: retry
    retryAfter: 2
    retryLimit: 3
    criteria:
      - condition: $response.statusCode >= 500

  - name: skip_on_4xx
    type: end
    criteria:
      - condition: $response.statusCode >= 400
      - condition: $response.statusCode < 500

  - name: escalate
    type: goto
    workflowId: payment_error_handler

retry_on_5xx only activates when status ≥ 500. If the retry limit is exhausted, the operation returns the failure; later actions do not run as retry fallbacks. skip_on_4xx activates for 4xx. escalate catches failures not matched by the scoped actions.

Example 2: goto to a Specific Step

On success, branch directly to a named step rather than a whole workflow:

operationId: check_eligibility
sourceDescription: rules_api
openapiOperationId: evaluateRules
successCriteria:
  - condition: $response.body.eligible == true
onSuccess:
  - name: fast_track
    type: goto
    stepId: approve_immediately
    criteria:
      - condition: $response.body.score >= 90

  - name: standard
    type: goto
    stepId: queue_for_review

fast_track sends high-scoring applicants straight to approval. Everyone else goes to the review queue.

Example 3: goto to a Workflow on Failure

Route persistent failures to a dedicated error-handling workflow:

operationId: sync_inventory
sourceDescription: warehouse_api
openapiOperationId: syncStock
successCriteria:
  - condition: $response.statusCode == 200
onFailure:
  - name: retry_briefly
    type: retry
    retryAfter: 5
    retryLimit: 2
    criteria:
      - condition: $response.statusCode >= 500

  - name: raise_incident
    type: goto
    workflowId: ops_incident_workflow

After 2 failed retries, raise_incident fires and routes to the incident management workflow.

Example 4: end on Partial Success

Stop early when there is nothing left to do, without calling it an error:

operationId: list_pending_orders
sourceDescription: orders_api
openapiOperationId: getPendingOrders
successCriteria:
  - condition: $response.statusCode == 200
onSuccess:
  - name: nothing_to_process
    type: end
    criteria:
      - condition: $response.body.total == 0

If the list is empty, execution ends cleanly. If items exist, the default behavior continues to the next step.

Example 5: Multi-Criterion successCriteria

All criteria in successCriteria must be satisfied for the operation to be considered successful:

operationId: create_session
sourceDescription: auth_api
openapiOperationId: initiateSession
successCriteria:
  - condition: $response.statusCode == 201
  - condition: $response.body.token != null
  - condition: "^[A-Za-z0-9_-]{32,}$"
    type: regex
    context: $response.body.token
onFailure:
  - name: auth_failure
    type: goto
    workflowId: handle_auth_error

All three criteria must pass. If the token is missing or malformed, auth_failure fires.

Inline Declaration

UWS does not provide a reusable component registry for criteria and actions. Each operation declares its own. This keeps the document self-describing and allows sibling operations to evolve independently without shared state.

From The Big Fixture

The large fixture combines simple and regex criteria with retry and goto failure actions:

onFailure "retry_run_llm_primary" {
  type       = "retry"
  retryAfter = 5
  retryLimit = 2
  criterion {
    condition = "$error.transient == true"
    type      = "simple"
  }
  criterion {
    condition = "timeout|rate limit"
    type      = "regex"
    context   = "$error.message"
  }
}

onFailure "review_run_llm_primary" {
  type       = "goto"
  workflowId = "wf_manual_review"
  criterion {
    condition = "$error.transient != true"
    type      = "simple"
  }
}

Full context: testdata/big/big.hcl.


Structural Results | Next: Execution Model →