Coordinate everything. Keep a receipt.
Cascade is a REST API. Before an agent, a worker, a person, or a machine acts on something shared, it asks for it. Cascade answers yes — only you hold it now — or wait — someone else does. Every answer is signed into a tamper-evident record anyone can check later, even offline.
Get a key
Free to start, no card. A new key works immediately for 1,000 decisions; verifying your email unlocks the full free allowance and keeps everything so far.
- Create a workspace. Sign up at cascadedynamics.ai and copy your key — it starts with
csc_and is shown once. - Verify your email. Click the link we send. Until then, claims past the first 1,000 return
403 email_verification_required. - Set two environment variables. Never hard-code the key or commit it.
# the only two things Cascade needs export CASCADE_API="https://api.cascadedynamics.ai/v1" export CASCADE_API_KEY="csc_your_key_here"
A key is a secret, like a password. Put it in your CI secret store or a .env that is git-ignored — never in source.
Your first claim
Everything is claim → do the work → release. Here is a complete client in any language that speaks HTTP — this one is Node, no packages.
const API = process.env.CASCADE_API || "https://api.cascadedynamics.ai/v1"; async function cascade(path, body) { const res = await fetch(API + path, { method: "POST", headers: { Authorization: "Bearer " + process.env.CASCADE_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify(body), }); return res.json(); }
Now claim a cell, do the thing only one actor should do at a time, and release it. A cell is any name you choose for the shared thing — a file, a deploy, an order, a zone.
const cell = "deploy/payments-api/prod", me = "ci-run-4812"; const got = await cascade("/claim", { cell, agent: me, ttl_ms: 30000 }); if (!got.ok) { console.log("someone else has it:", got.behind); // held — try later return; } // ✅ you alone hold the cell. Do the thing. await runTheDeploy(); // hand it back, signing the outcome into the record await cascade("/release", { cell, agent: me, outcome: { status: "done" } });
That entry_hash is your receipt. If your process dies before it releases, the ttl_ms frees the cell on its own — no stuck locks.
Check it works
One command runs a self-test against your key — about a dozen decisions on throwaway cells — and confirms the record verifies.
curl -fsSO https://cascadedynamics.ai/recipes/check.mjs
node check.mjs # exit 0 = every check passedTo see two actors coordinate for real, open two terminals and claim the same cell from each — the first gets ok:true, the second gets ok:false with the first one's name in behind.
AI coding agents
Running Claude Code, Codex, Cursor, or VS Code — sometimes several at once on one repo? One command connects every tool you have, so each agent claims a file before it edits and two agents never overwrite each other.
npx cascade-setup # finds your tools, wires each to Cascade npx cascade-setup --project # also add the team rule to this repo
For a hard guarantee — not just an instruction a model might skip — add the file-lock hook: it claims the file on every edit and blocks an edit it can't lock. Steps for Claude Code, Codex and Cursor are on the setup page.
ChatGPT & Claude
Assistants connect by signing in, not with a key in a file. Add Cascade's hosted coordinator as a connector and approve it once; every chat session then coordinates under your account.
On the approve page, choose the same key your other tools use. Tools only see each other's claims when they share one key — pick the one your Codex or CI uses, not a dormant signup key.
LLM apps & agents
Building with LLMs — several agents on one goal, tool calls that must land exactly once, a plan many agents share? Cascade sits at the point where a plan turns into an action on something shared and decides who may act now. It runs no model and costs no tokens, so it never competes with your model budget — and a wait isn't a dead end: behind tells the planner who holds the thing, so it can branch, retry, or re-plan.
The client, in Python
Same three calls, no SDK — standard library only.
import os, json, urllib.request API = os.environ.get("CASCADE_API", "https://api.cascadedynamics.ai/v1") def cascade(path, body): req = urllib.request.Request( API + path, data=json.dumps(body).encode(), headers={"Authorization": "Bearer " + os.environ["CASCADE_API_KEY"], "Content-Type": "application/json"}, method="POST") with urllib.request.urlopen(req) as r: return json.load(r)
Many agents, one goal
Give your agents a shared list of work. Each one claims a task before it starts, so exactly one agent works each task — and a crashed agent's task reopens on its own when its lease lapses. Works across machines and across vendors, because they all name the cell the same way.
for task in board.open_tasks(): got = cascade("/claim", {"cell": f"task/build/{task.id}", "agent": me, "ttl_ms": 60000}) if not got["ok"]: continue # another agent already has it result = run_agent(task) # your LLM does the work cascade("/release", {"cell": f"task/build/{task.id}", "agent": me, "outcome": {"status": "done"}})
Want a hosted plan agents on different machines can read and add to? Use the board tools over the MCP connector above, or npx cascade-swarm for coding goals.
Tool calls that must happen once
When an agent fires a real action — a payment, an email, an order — a retried or re-planned tool call must not do it twice. Claim the action's key before running the tool; the record proves it ran once.
def run_tool(name, args, key): got = cascade("/claim", {"cell": f"once/{key}", "agent": me, "ttl_ms": 30000}) if not got["ok"]: return {"status": "already running or done"} try: return TOOLS[name](**args) # the one real call finally: cascade("/release", {"cell": f"once/{key}", "agent": me})
For retries that survive a crash, see Once-only actions and pair it with your provider's idempotency key. To cap how many model calls run at once across every agent, see Shared limits.
Drops into your framework
Keep whatever decides what to try — LangGraph, CrewAI, AutoGen, the Claude Agent SDK, or your own loop. Cascade only decides who may act on the shared thing now, so an LLM agent, a scheduled job, and a plain service can share one cell even though nothing else about them is shared.
Deploys & migrations
CI, people, and agents can all kick off the same deploy or terraform apply. Run it through one lock so only one goes at a time — and the run is signed into the record.
curl -fsSO https://cascadedynamics.ai/recipes/lock-run.mjs node lock-run.mjs deploy/payments-api/prod -- ./deploy.sh prod node lock-run.mjs migrate/orders-db --wait 600 -- npm run migrate
A lock gives exclusivity, not ordering. If "newest wins" matters, also reject a run whose CASCADE_FENCE is lower than the last one applied — the fence the command receives only ever grows.
Once-only actions
A payment, an email, a webhook — something that must happen exactly once even when many workers race or one dies mid-way and is retried.
import { onceOnly } from "./once.mjs"; await onceOnly(`order-${id}`, me, async () => { await chargeCard(id); // the side effect }, { alreadyDone: () => db.isCharged(id), // cheap check, stops late retries record: () => db.markCharged(id), });
The claim stops concurrent duplicates; pair it with your provider's idempotency key so a crash between "charged" and "recorded" can't double-charge either.
Worker & ticket queues
Several agents and a person work one queue. Whoever holds the ticket works it; nobody else can. If an agent gets stuck it hands off to a human; if it dies, the hold expires and someone else picks it up. The record shows who handled each ticket.
import { workQueue } from "./handoff.mjs"; await workQueue({ who: "agent-3", openTickets: () => inbox.open(), work: (id) => handle(id), save: (id, out) => inbox.save(id, out), });
Shared limits
Cap how many expensive calls run at once across every machine on one key — concurrent LLM calls, GPU jobs, or a rate-limited partner API.
import { withSlot } from "./slots.mjs"; await withSlot("llm", 3, me, async () => { return callTheModel(prompt); // never more than 3 at a time });
Robots & fleets
Robots, drones, humanoids and vehicles that share aisles, airspace, bays or charging docks. Reserve a whole route at once — all of it or none, no deadlock — and renew while you move.
import { reserve } from "./reserve.mjs"; const r = await reserve(path, "amr-07", { ttl_ms: 20000 }); if (!r.ok) return replan(r.cell, r.behind); r.keepAlive(); // renew every ttl/3 while moving await r.releaseBehind(passed); // free cells as you leave them
Cascade is coordination, not a safety system. Use it for who may enter a zone for the next seconds or minutes; keep collision avoidance and e-stop on the machine, in its rated safety controller.
Proof & audit
Every decision is hash-chained and signed, so later — in an audit, an incident, or a dispute — anyone can prove what happened and in what order, offline, with no account.
# pull this run's signed bundle, then check it from scratch npx cascade-verify@0.3 bundle.json --fetch-anchors # VERIFIED: every entry hashes to its successor, signatures valid, # no resource held twice, no model in the decision path.
Releasing with a digest — a SHA-256 of the artifact you produced (an inspection photo, a test report, a signed PDF) — lets anyone later prove that exact file is the one this agent reported, under this grant.
The beta program
Cascade is in early beta: stable to build on, free to start, and priced so that most projects stay inside the free tier for a long time. A decision is one claim or release that reaches the API; reads and repeat polls are free.
What "beta" means here
- The API, the recipes, and the signed record are stable — build on them today.
- You keep your records; signing is backed by a key held in a managed key service, with hourly tamper-evident anchors.
- We're actively adding integrations and want your feedback on what to build next.
Why it's worth wiring in
Each decision is refereed without a model, so it costs no LLM tokens — roughly 600 tokens saved versus asking a model to arbitrate, and it never double-acts or loses track of who's doing what. The signed receipt is there whether or not anything ever collides.
Get help
Recipes
cascadedynamics.ai/recipes — every pattern on this page, tested, with limits spelled out.
For your agents
Point any AI assistant at SKILL.md and it will read your project and tell you where Cascade fits.
Connect tools
agents.html — step-by-step for Claude Code, Codex, Cursor, ChatGPT and Claude.
Talk to us
Volume, on-prem, or just stuck? Email us — we read every message.