On this page
SDKs
The TypeScript and Python SDKs are generated from the same operation registry as the API: one method per operation, typed requests, validated responses, and the idempotency and retry rules built in.
Getting the packages
The SDKs are not yet published to the public npm and PyPI registries. Your Cumulus contact provides the packages; until you have them, every operation works over plain HTTPS (see the curl samples).
One method per operation
An operation domain.method is client.domain.method(…) in both SDKs: runs.create is client.runs.create. Each call takes the request's parts by name: path, query, bodyand, for commands that take one, the idempotency key. The SDK sends Authorization, generates an Idempotency-Key when you pass none, and raises one error type carrying the API's code, retryable, outcome and the key it sent.
| TypeScript | Python | |
|---|---|---|
| Package | @cumulus/sdk | cumulus-sdk |
| Runtime | Node.js 20.3 or newer, ESM only | Python 3.10 or newer (httpx, pydantic 2); synchronous |
| Client | new Cumulus({ apiKey, baseUrl, timeoutMs, fetch }) | Cumulus(api_key, *, base_url, timeout, transport) |
| Defaults | CUMULUS_API_KEY, CUMULUS_BASE_URL, https://api.cumuluslabs.io, 30 s | CUMULUS_API_KEY, CUMULUS_BASE_URL, https://api.cumuluslabs.io, 30 s |
| A call | client.runs.get({ path: { run_id } }) | client.runs.get(path={"run_id": run_id}) |
| Idempotency | { …, idempotencyKey } | idempotency_key=… |
| Run events | client.events({ path: { run_id }, lastEventId }) | client.events(run_id, last_event_id=…) |
| Errors | PlatformError | PlatformError |
In Python, a method named by a keyword takes a trailing underscore (client.agents.import_), and responses are Pydantic models. Both SDKs can also call an operation by id: client.call("runs.get", …).
TypeScript
run.mjs
import { Cumulus } from "@cumulus/sdk";
const client = new Cumulus({ apiKey: process.env.CUMULUS_API_KEY });
const run = await client.runs.create({
body: { channel: "cloud", agent_id: "…", mode: "task", input: { ticket: "I was charged twice this month." } },
});
for await (const event of client.events({ path: { run_id: run.run_id } })) {
console.log(event.sequence, event.type);
if (event.type === "run.ended") break;
}
Python
run.py
from cumulus import Cumulus
with Cumulus() as client: # reads CUMULUS_API_KEY
run = client.runs.create(
body={"channel": "cloud", "agent_id": "…", "mode": "task", "input": {"ticket": "I was charged twice this month."}}
)
for event in client.events(str(run.run_id)):
payload = event.model_dump(mode="json")
print(payload["sequence"], payload["type"])
if payload["type"] == "run.ended":
break
Errors
When to retry
error.outcome === "unknown": the command may have happened (a timeout, a dropped connection). Retry with the same key:error.idempotencyKey/error.idempotency_key.error.retryablewith outcomenone: nothing happened; retry after a pause.- Anything else: fix the request.
error.codeanderror.detailssay what is wrong.
Every step of the main flows, in both SDKs, is in Using the API.