Guides
Generate a cascade with AI
Turn a plain-English screening policy into a valid cascade with POST /workflows/generate, preview before saving, and handle the busy and failure cases.
POST /workflows/generate takes a description of your screening policy and returns a cascade definition built by Claude, validated against the same node grammar the visual builder enforces. Use it to draft a cascade from a sentence, then refine in the builder or with PATCH /workflows/{id}.
What do I send?
A prompt describing the policy in the language you would use with a colleague. Be explicit about products, thresholds, and what happens on each outcome:
curl -X POST "https://cascades.crscreditapi.com/api/v1/workflows/generate" \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Pull an Equifax credit report. Approve if FICO is at least 650; otherwise send an adverse-action notice for review.",
"use_case": "tenant_screening"
}'const response = await fetch("https://cascades.crscreditapi.com/api/v1/workflows/generate", {
method: "POST",
headers: {
"Authorization": "Bearer {{API_KEY}}",
"Content-Type": "application/json"
},
body: JSON.stringify({
"prompt": "Pull an Equifax credit report. Approve if FICO is at least 650; otherwise send an adverse-action notice for review.",
"use_case": "tenant_screening"
})
});
const { data, meta } = await response.json();
console.log(response.status, data, meta.request_id);import requests
response = requests.post(
"https://cascades.crscreditapi.com/api/v1/workflows/generate",
headers={
"Authorization": "Bearer {{API_KEY}}",
},
json={
"prompt": "Pull an Equifax credit report. Approve if FICO is at least 650; otherwise send an adverse-action notice for review.",
"use_case": "tenant_screening"
},
)
response.raise_for_status()
payload = response.json()
print(payload["data"], payload["meta"]["request_id"])require "net/http"
require "json"
uri = URI("https://cascades.crscreditapi.com/api/v1/workflows/generate")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer {{API_KEY}}"
request["Content-Type"] = "application/json"
request.body = <<~JSON
{
"prompt": "Pull an Equifax credit report. Approve if FICO is at least 650; otherwise send an adverse-action notice for review.",
"use_case": "tenant_screening"
}
JSON
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
payload = JSON.parse(response.body)
puts payload["data"], payload.dig("meta", "request_id")package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
body := []byte(`{
"prompt": "Pull an Equifax credit report. Approve if FICO is at least 650; otherwise send an adverse-action notice for review.",
"use_case": "tenant_screening"
}`)
req, err := http.NewRequest("POST", "https://cascades.crscreditapi.com/api/v1/workflows/generate", bytes.NewBuffer(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer {{API_KEY}}")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}claude mcp add cascades \
-e CASCADES_API_KEY={{API_KEY}} \
-e CASCADES_PROD_BASE_URL=https://cascades.crscreditapi.com \
-- npx -y @crscreditapi/cascades-mcp-server
# Then ask your assistant:
# "Generate a workflow from a prompt and summarise the result."
# It will call the `cascades_generate_workflow` tool with your key.Optional fields: name (otherwise the generator names it), use_case (defaults to tenant_screening), active (subject to the activation gate), and create: false to preview the definition without saving anything.
{
"prompt": "Verify identity, pull a TransUnion credit report and a criminal search. Approve FICO 680 and above with no felonies. Send 620–679 to manual review. Decline below 620 or any felony, with an adverse-action notice.",
"create": false
}What comes back?
With create: false, 200 and a preview:
{
"data": {
"object": "cascade_generation",
"definition": [ { "id": "start", "type": "ApplicantSource", "next_step": ["identity"] }, "…" ],
"valid": true,
"name": "Tenant screening — FICO 680 gate",
"model": "claude-opus-4-8",
"repaired": false,
"warnings": []
},
"meta": { "request_id": "…" }
}By default the cascade is saved and the response is 201 with the workflow plus a generation block carrying the same model, repaired and warnings fields. repaired: true means the first draft failed validation and a cheaper model fixed it in one repair turn; read warnings — they list anything the generator could not express exactly (a product your account cannot use, an ambiguous threshold).
On a sandbox account the cascade is saved as a draft and the response carries a note saying so. It still runs in test mode.
Which errors should I handle?
| Code | Meaning | What to do |
|---|---|---|
422 validation_failed |
Empty prompt, or longer than the cap | Trim the prompt |
422 generation_failed |
The model could not produce a valid definition; details lists the validation errors |
Rephrase — name products and thresholds explicitly |
503 designer_busy |
The generator's concurrency cap is in use | Retry after a few seconds with backoff |
403 insufficient_scope |
Key lacks workflows:write |
Use a key with the scope |
Generation is not idempotent: two identical prompts create two cascades. Use create: false when exploring.
Iterating
The returned definition is ordinary JSON. Edit nodes, thresholds or edges and send the whole array back with PATCH /workflows/{id}; the same validator runs on every save. To test it, trigger it in test mode with a registered subject and read step_outputs to see which branch fired.
Related
- Cascades — the node grammar the generator targets
POST /workflows/generate