{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"success-criteria-and-failure-handling","__idx":0},"children":["Success criteria and failure handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Time travel with the Warp API is thrilling, but it's not all smooth jumps and perfect landings. In Arazzo, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["successCriteria"]}," let you define what \"success\" means and what to do when the timeline goes sideways. Whether it's a paradox, a timeout, or an unauthorized hop, these tools keep your workflows on track. Let's explore how to set them up, with Warp examples to guide us through the chaos of time manipulation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"defining-successcriteria","__idx":1},"children":["Defining ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["successCriteria"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["successCriteria"]}," field in a step is your checkpoint—it tells Arazzo how to confirm a step worked as expected. It's a list of conditions, typically runtime expressions, that must all pass for the step to succeed. Think of it as your time-travel log: \"Did we land in 1889? Is the timeline stable?\""]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a basic check for Warp's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["timeTravel"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"steps:\n  - stepId: \"jumpTo1889\"\n    operationId: \"warpApi.timeTravel\"\n    requestBody:\n      payload:\n        destination: \"tml_tesla_mission_1\"\n    successCriteria:\n      - condition: \"$statusCode == 200\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-it-works","__idx":2},"children":["How it works"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["$statusCode"]},": A runtime expression grabbing the HTTP response code."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["== 200"]},": Ensures the jump returned a 200 OK—mission accomplished!"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can layer conditions for precision. Let's verify the arrival time too:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"successCriteria:\n  - condition: \"$statusCode == 200\"\n  - condition: \"$response.body#/arrival_time == '1889-03-10T23:50:00Z'\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Both must be true—or the step fails, triggering ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFailure"]},". You can also use JSONPath for deeper checks:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"successCriteria:\n  - condition: \"$statusCode == 200\"\n  - condition: \"$.items_transported.length > 0\"\n    context: \"$response.body\"\n    type: \"jsonpath\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This confirms we brought back Tesla's blueprint (items_transported isn't empty)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"configuring-onfailure","__idx":3},"children":["Configuring ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFailure"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When a step fails—maybe Warp's servers are overloaded or your token expired—",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFailure"]}," steps in."," ","It's an optional field that decides the next move."," ","Your options are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["end"]},": Abort the workflow immediately."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["retry"]},": Try the step again, with limits."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["goto"]},": Jump to another step or workflow as a backup plan."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"configuring-onsuccess","__idx":4},"children":["Configuring ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When a step passed—",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," steps in."," ","It's an optional field that decides the next move."," ","Your options are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["end"]},": Abort the workflow immediately."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["goto"]},": Jump to another step or workflow as a backup plan."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"exit-on-failure","__idx":5},"children":["Exit on failure"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a must-succeed step like setting an anchor:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"- stepId: \"setHomeAnchor\"\n  operationId: \"warpApi.setAnchor\"\n  requestBody:\n    payload:\n      timestamp: \"2025-02-19T12:00:00Z\"\n      description: \"Home base\"\n  successCriteria:\n    - condition: \"$statusCode == 201\"\n  onFailure:\n    - name: \"exitOnFailure\"\n      type: \"end\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the anchor doesn't set (not a 201 Created), the workflow stops—because traveling without a return point is a bad idea."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"retry-on-failure","__idx":6},"children":["Retry on failure"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a flaky jump that might timeout (e.g., 503):"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"- stepId: \"jumpTo1889\"\n  operationId: \"warpApi.timeTravel\"\n  requestBody:\n    payload:\n      destination: \"tml_tesla_mission_1\"\n  successCriteria:\n    - condition: \"$statusCode == 200\"\n  onFailure:\n    - name: \"retryOnTimeout\"\n      type: \"retry\"\n      retryLimit: 3\n      retryAfter: 5\n      criteria:\n        - condition: \"$statusCode == 503\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This retries up to 3 times, waiting 5 seconds between tries—perfect for temporary glitches in the time stream."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"goto-another-step","__idx":7},"children":["Goto another step"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For an unauthorized jump (401), go to a re-authentication step:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"- stepId: \"jumpTo1889\"\n  operationId: \"warpApi.timeTravel\"\n  requestBody:\n    payload:\n      destination: \"tml_tesla_mission_1\"\n  successCriteria:\n    - condition: \"$statusCode == 200\"\n  onFailure:\n    - name: \"reAuthOn401\"\n      type: \"goto\"\n      stepId: \"reAuth\"\n      criteria:\n        - condition: \"$statusCode == 401\"\n- stepId: \"reAuth\"\n  operationId: \"warpApi.someAuthOperation\"  # Hypothetical endpoint\n  outputs:\n    newToken: $response.body#/token\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the jump fails with a 401, it skips to reAuth to refresh the token, then you'd loop back manually or adjust the workflow."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"practical-examples","__idx":8},"children":["Practical examples"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"handling-timeouts","__idx":9},"children":["Handling timeouts"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Warp's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["monitorTimeline"]}," might timeout (503). Retry, then give up:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"- stepId: \"monitorJump\"\n  operationId: \"warpApi.monitorTimeline\"\n  parameters:\n    - in: query\n      name: timeline_id\n      value: \"tml_tesla_mission_1\"\n  successCriteria:\n    - condition: \"$statusCode == 200\"\n  onFailure:\n    - name: \"retryOnTimeout\"\n      type: \"retry\"\n      retryLimit: 3\n      retryAfter: 10\n      criteria:\n        - condition: \"$statusCode == 503\"\n    - name: \"exitOnMaxRetries\"\n      type: \"end\"\n      criteria:\n        - condition: \"$retryCount >= 3\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After 3 failed attempts, it exits—better to abort than risk a corrupted timeline."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"unauthorized-responses","__idx":10},"children":["Unauthorized responses"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a 401 on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkParadox"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"- stepId: \"checkStability\"\n  operationId: \"warpApi.checkParadox\"\n  requestBody:\n    payload:\n      timeline_id: \"tml_tesla_mission_1\"\n      proposed_changes:\n        - event: \"Retrieve Tesla's blueprint\"\n          time: \"1889-03-10T23:50:00Z\"\n  successCriteria:\n    - condition: \"$statusCode == 200\"\n    - condition: \"$.adam_stable == true\"\n      context: \"$response.body\"\n      type: \"jsonpath\"\n  onFailure:\n    - name: \"logOn401\"\n      type: \"goto\"\n      stepId: \"logIssue\"\n      criteria:\n        - condition: \"$statusCode == 401\"\n- stepId: \"logIssue\"\n  operationId: \"warpApi.someLogOperation\"  # Hypothetical logging endpoint\n  requestBody:\n    payload:\n      message: \"Unauthorized paradox check\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If authorization fails, it logs the issue—great for auditing time-travel mishaps."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"tips-for-success","__idx":11},"children":["Tips for success"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Start simple"]},": Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["$statusCode"]}," checks first, then add response body conditions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Match reality"]},": Test successCriteria against actual Warp API responses (e.g., does ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["adam_stable"]}," exist?)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Plan B matters"]},": Add ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFailure"]}," for critical steps—time travel's too wild to wing it."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Tune retries"]},": Set retryLimit and retryAfter based on your API's behavior (Warp's docs suggest timeouts are rare but possible)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"why-it-matters","__idx":12},"children":["Why it matters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With the Warp API, a failed step could leave you stranded in 1889 or unravel reality itself. Success criteria ensures your jumps, checks, and anchors hit their marks, while ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFailure"]}," offers a safety net for the unexpected. Together, they turn risky time-travel workflows into reliable missions."]}]},"frontmatter":{},"tagList":[],"title":"Success criteria and failure handling","lastModified":"2025-05-28T16:01:32.000Z"}