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.