You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add fire + list_claimable + claim + claim_next (#23)
Brings the Python SDK toward parity with the @cueapi/mcp 0.3.0 + 0.4.0
surface. Adds four new methods covering the SEND side (fire) and the
RECEIVE side (claimable list, claim, claim-next). Heartbeat signature
fix is held for a follow-up commit pending technical review.
CuesResource:
- fire(cue_id, payload_override=None, merge_strategy=None)
POST /v1/cues/{id}/fire. For ad-hoc one-shot triggers and for using
cues as a messaging channel between agents (carry message, instruction,
task, reply_cue_id in payload_override).
ExecutionsResource:
- list_claimable(task=None, agent=None)
GET /v1/executions/claimable?task=&agent=
Filters server-side via query params (NOT client-side). Required for
single-purpose workers; client-side filter after fetch hits the LIMIT
50 starvation bug fixed in the 2026-04-25 prod incident.
- claim(execution_id, worker_id=...)
POST /v1/executions/{id}/claim
Atomic; returns 409 if already claimed.
- claim_next(worker_id=..., task=None)
POST /v1/executions/claim (no task) OR list+claim chain (with task).
Server's claim endpoint does not accept a task filter today; with task
the SDK fans out (list_claimable filtered, pick oldest, claim by ID).
Tiny race window between list and claim is bounded by the atomic claim
returning 409, in which case the caller retries.
Version: 0.1.3 -> 0.2.0. Aligned cueapi/__init__.py (had drifted to
0.1.2) with pyproject.toml at the same time.
Tests: 42 unit tests pass (was 30; +12 net). Mirrors the existing
MagicMock pattern in tests/test_executions_resource.py.
Pending follow-up:
- ExecutionsResource.heartbeat(execution_id) currently sends an empty
body and does not include worker_id via the X-Worker-Id request
header that the server reads from. Worker-id is what the server uses
to enforce ownership on heartbeat (returns 403 on mismatch); without
it the race-protection check is silently bypassed. A signature change
to add worker_id is held pending technical review of the deprecation
cadence (additive kwarg-only with default-warn-on-omit vs hard
signature change in a major bump).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,20 @@
2
2
3
3
All notable changes to cueapi-sdk will be documented here.
4
4
5
+
## [0.2.0] - 2026-05-01
6
+
7
+
### Added
8
+
-`client.cues.fire(cue_id, payload_override=None, merge_strategy=None)` for ad-hoc one-shot triggers and for using cues as a messaging channel between agents. Wraps `POST /v1/cues/{id}/fire`.
9
+
-`client.executions.list_claimable(task=None, agent=None)` for unclaimed worker-transport executions ready for processing. Filters server-side via task / agent query params; required for single-purpose workers.
10
+
-`client.executions.claim(execution_id, worker_id=...)` for atomic claim of a specific execution. Returns 409 if already claimed.
11
+
-`client.executions.claim_next(worker_id=..., task=None)` for the next available execution. Without task the server picks the oldest pending; with task the SDK fans out internally (list_claimable filtered, pick oldest, claim by ID) since the server's claim endpoint does not accept a task filter today.
12
+
13
+
### Changed
14
+
-`__version__` in `cueapi/__init__.py` had drifted to 0.1.2 while `pyproject.toml` was at 0.1.3. Both now aligned at 0.2.0.
15
+
16
+
### Pending follow-up
17
+
-`client.executions.heartbeat(execution_id)` currently sends an empty body and does NOT include `worker_id` via the `X-Worker-Id` request header that the server reads from. Worker-id is what the server uses to enforce ownership on the heartbeat (returns 403 on mismatch); without it the race-protection check is silently bypassed. A signature change to add `worker_id` is held pending technical review of the deprecation cadence.
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,5 @@
1
1
<!-- Pipeline validation: 2026-04-04 -->
2
-
> **For AI agents:** This is the official Python SDK for CueAPI. Run `pip install cueapi-sdk`. Your API key is in `CUEAPI_API_KEY`. Create a client: `client = CueAPI(os.environ["CUEAPI_API_KEY"])`. Schedule a task: `client.cues.create(name="task-name", cron="0 9 * * *", callback="https://your-handler.com", payload={})`. For agents without a public URL: set `transport="worker"` and run `pip install cueapi-worker`, then define a handler with `@worker.handler("task-name")` returning `{"success": true}` or `{"success": false, "error": "reason"}`. List executions: `client.executions.list()`. Get one: `client.executions.get("exec_id")`. Do not retry on `AuthenticationError` or `CueLimitExceededError`. Wait `e.retry_after` seconds on `RateLimitError`.
2
+
> **For AI agents:** This is the official Python SDK for CueAPI. Run `pip install cueapi-sdk`. Your API key is in `CUEAPI_API_KEY`. Create a client: `client = CueAPI(os.environ["CUEAPI_API_KEY"])`. Schedule a task: `client.cues.create(name="task-name", cron="0 9 * * *", callback="https://your-handler.com", payload={})`. For agents without a public URL: set `transport="worker"` and run `pip install cueapi-worker`, then define a handler with `@worker.handler("task-name")` returning `{"success": true}` or `{"success": false, "error": "reason"}`. Fire an existing cue immediately: `client.cues.fire("cue_id", payload_override={"task": "x"})`. List unclaimed worker executions: `client.executions.list_claimable(task="task-name")`. Claim one: `client.executions.claim("exec_id", worker_id="my-worker")`. List executions: `client.executions.list()`. Get one: `client.executions.get("exec_id")`. Do not retry on `AuthenticationError` or `CueLimitExceededError`. Wait `e.retry_after` seconds on `RateLimitError`.
0 commit comments