HTTP Watch
Poll a remote HTTP endpoint until pass or fail conditions are met
Introduction HTTP Watch
The circuit.core.http_watch primitive lets you poll any HTTP(S) endpoint at a fixed interval, evaluate pass/fail conditions against the JSON response, and return when a condition is satisfied or throw an error after too many attempts.
When to use: long‑running jobs, external tasks or services where you need to wait for a status change (e.g. image/video generation, analysis pipelines).
Step Definition
"steps": [
{
"name": "wait_for_completion",
"function": "circuit.core.http_watch",
"input": {
"url": "https://api.example.com/jobs/${{ jobId }}",
"method": "GET",
"headers": {
"Authorization": "Bearer ${{ secrets.api_key }}"
},
"interval_seconds": 10,
"max_attempts": 30,
"timeout_seconds": 600
},
"conditions": {
"pass": [
{ "json_path": "${{ wait_for_completion.output.json_body.status }}", "equals": "SUCCEEDED" }
],
"fail": [
{ "json_path": "${{ wait_for_completion.output.json_body.status }}", "equals": "FAILED" },
{ "status_code": [400,404,500] }
]
},
"outputs": [
{
"name": "resultData",
"value": "${{ wait_for_completion.output.json_body }}"
}
]
}
]input Properties
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Endpoint URL (template selectors allowed). |
method | string | Yes | HTTP verb (GET,POST,PUT,DELETE,PATCH). |
headers | object<string,string> | No | Map of request headers (selectors allowed). |
interval_seconds | number | Yes | Seconds between each poll. |
max_attempts | number | Yes | How many times to retry before failing. |
timeout_seconds | number | Yes | Overall timeout for each HTTP call. |
conditions Block
Controls when to stop polling:
pass: array of conditions; all must evaluate totrueto succeed.fail: array of conditions; any singletruewill immediately fail the step.
Each condition object supports:
| Field | Type | Description |
|---|---|---|
json_path | string | Selector into the JSON response (e.g. ${{ step.output.json_body.status }}). |
equals | string or boolean | Pass/fail when the selected value equals this literal. |
not_equals | string or boolean | Pass/fail when the selected value does not equal this literal. |
status_code | array<number> | Fail if the HTTP status code matches any in the list. |
Outputs
When the step completes successfully or with an error, its output object includes:
// JSON-parsed response (if content-type application/json)
wait_for_completion.output.json_body
// Raw headers map
wait_for_completion.output.headers
// HTTP status code
wait_for_completion.output.status
// Total time taken (seconds)
wait_for_completion.output.time_takenUse selectors in later steps or top‑level outputs:
"outputs": [
{ "name": "jobResult", "value": "${{ wait_for_completion.output.json_body }}" }
]Example: Flux Image Generation
{
"steps": [
{
"name": "submit_job",
"function": "circuit.core.fetch",
/* submits image generation and sets flux_job_id */
},
{
"name": "wait_for_image",
"function": "circuit.core.http_watch",
"input": {
"url": "https://api.bfl.ml/v1/get_result?id=${{ flux_job_id }}",
"method": "GET",
"interval_seconds": 10,
"max_attempts": 30,
"timeout_seconds": 600
},
"conditions": {
"pass": [
{ "json_path": "${{ wait_for_image.output.json_body.status }}", "equals": "Ready" }
],
"fail": [
{ "json_path": "${{ wait_for_image.output.json_body.status }}", "equals": "Error" },
{ "status_code": [400,404,500,422] }
]
}
},
{
"name": "fetch_url",
"function": "circuit.core.fetch",
"input": { "url": "${{ wait_for_image.output.json_body.result.sample }}" }
}
],
"outputs": [
{
"name": "imageUrl",
"value": "${{ fetch_url.output.json_body }}"
}
]
}- Submit: POST to start the Flux job and capture
flux_job_id. - Watch: poll until
.status == "Ready", or error on.status == "Error"or HTTP 4xx/5xx. - Fetch URL: final GET to retrieve the generated image link.
Best Practices
- Choose sensible
interval_secondsandmax_attemptsto balance latency vs. load. - Always include a
failcondition for HTTP errors to prevent infinite loops. - Use templated selectors (
${{ … }}) to reference intermediate outputs.
Next: Adapters – wire SSE, Webhook, and custom streams directly into your circuits!