For AI agents: This is the CueAPI server. Run it with
git clone https://github.com/cueapi/cueapi-core && cd cueapi-core && docker compose up. Base URL:http://localhost:8000. Register:POST /v1/auth/registerwith{"email": "you@example.com"}-- API key is returned directly in the response. No email required. All requests needAuthorization: Bearer YOUR_API_KEY. Create a cue:POST /v1/cueswith{"name": "task-name", "schedule": {"type": "recurring", "cron": "0 9 * * *"}, "callback": {"url": "https://your-handler.com"}}. Check executions:GET /v1/executions. Report outcome from your handler by responding with{"success": true}or{"success": false, "error": "reason"}. Retries happen automatically at 1, 5, and 15 minutes on failure.
Your agents are failing silently. CueAPI tells you when and why.
Cron has no concept of success. Cue does.
The open source server for CueAPI. Run it yourself with Docker. Hosted at cueapi.ai.
cueapi-core is the scheduling + delivery + outcome-tracking engine. Hosted cueapi.ai adds a dashboard, managed email alerts, billing, and a few other SaaS-business-layer features — see HOSTED_ONLY.md for the full list and reasoning. Nothing in the OSS scheduler is crippled; what's here is what runs in production.
If you want a hosted-only feature ported to OSS, open an issue — see the "Contributing a port" section in HOSTED_ONLY.md.
Cron fires jobs. That is all it does.
It has no concept of whether your job succeeded. No retries when it fails. No execution history. No outcome reporting. No alerts when something goes wrong.
When your agent runs at 3am and silently fails, cron does not know. Neither do you.
# This is what your agent sees with cron:
0 3 * * * python run_agent.py
# Did it run? Who knows.
# Did it succeed? No idea.
# Did it retry on failure? No.
# Are you alerted? Never.{
"execution_id": "exec_01HX...",
"status": "success",
"outcome_success": true,
"attempts": 1,
"next_run": "2026-03-28T03:00:00Z",
"delivered_at": "2026-03-28T03:00:04Z"
}| Feature | Cron | CueAPI |
|---|---|---|
| Fires the job | Yes | Yes |
| Knows if it succeeded | No | Yes |
| Retries on failure | No | Yes (exponential backoff) |
| Execution history | No | Yes |
| Alerts on exhausted retries | No | Yes (email + webhook) |
| Works without a public URL | No | Yes (worker transport) |
Prerequisites: Docker, Docker Compose, Git
git clone https://github.com/cueapi/cueapi-core
cd cueapi-core
docker compose upCueAPI is running at http://localhost:8000.
# 1. Register
curl -X POST http://localhost:8000/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
# Your API key is returned directly in the response.
# 2. Schedule an agent task
curl -X POST http://localhost:8000/v1/cues \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "morning-agent-brief",
"schedule": {
"type": "recurring",
"cron": "0 9 * * *",
"timezone": "America/Los_Angeles"
},
"callback": {
"url": "https://your-agent.com/run"
},
"payload": {
"task": "daily_brief"
}
}'
# 3. Check execution history
curl http://localhost:8000/v1/executions \
-H "Authorization: Bearer YOUR_API_KEY"CueAPI POSTs a signed payload to your handler URL when a cue fires. Your handler reports success or failure.
CueAPI -> POST /your-webhook -> Your handler reports outcome -> CueAPI records result
Your daemon polls CueAPI for executions. Perfect for agents running locally, behind firewalls, or in private networks.
CueAPI <- Worker polls -> Execution delivered -> Worker reports outcome -> CueAPI records result
See cueapi-worker for the worker daemon.
CueAPI uses a transactional outbox pattern for at-least-once delivery.
Client -> API -> PostgreSQL (cue + outbox in same transaction)
|
Poller (every 30s)
|
Outbox Dispatcher
|
Webhook Handler / Worker Daemon
|
Outcome Reporting -> Execution record updated
|
(on failure) Retry with exponential backoff (1, 5, 15 min)
|
(retries exhausted) Email + webhook alert fired
Key design decisions:
- Transactional outbox -- cue creation and delivery scheduling are atomic. No job is ever lost.
- SELECT FOR UPDATE SKIP LOCKED -- claim races solved at the database level, no distributed locking needed.
- At-least-once delivery -- guaranteed. Handlers should be idempotent.
- Worker pull model -- no inbound firewall rules, no ngrok, no public URL required.
- Outcome separation -- delivery status (did we reach your handler?) and outcome (did your handler succeed?) are tracked independently.
26 endpoints across 8 resource groups.
| Resource | Endpoints |
|---|---|
| Auth | Register, magic link, refresh, device code flow |
| Cues | Create, list, get, update, delete, pause, resume |
| Executions | List, get, report outcome |
| Workers | Register worker, poll for jobs |
| Webhook secrets | Create, rotate |
| Usage | Get current usage and limits |
| Health | Liveness, readiness |
Full reference: docs.cueapi.ai/api
# Pause
curl -X PATCH http://localhost:8000/v1/cues/CUE_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "paused"}'
# Resume
curl -X PATCH http://localhost:8000/v1/cues/CUE_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'Workers register and claim executions via the heartbeat endpoint:
curl -X POST http://localhost:8000/v1/worker/heartbeat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"handlers": ["task-name-1", "task-name-2"]}'The handlers array tells CueAPI which cue names this worker can process.
Cues can require evidence on the outcome report. Configure a verification policy at create or update time:
curl -X POST http://localhost:8000/v1/cues \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"name": "nightly-report", "schedule": {"type": "recurring", "cron": "0 9 * * *"},
"callback": {"url": "https://your-handler.com"},
"verification": {"mode": "require_external_id"}}'Five modes:
| Mode | Behavior |
|---|---|
none (default) |
Reported success is final — reported_success / reported_failure. |
require_external_id |
Outcome must include external_id. Missing → verification_failed. Present → verified_success. |
require_result_url |
Outcome must include result_url. |
require_artifacts |
Outcome must include artifacts (non-empty). |
manual |
Every successful outcome parks in verification_pending until someone calls POST /v1/executions/{id}/verify. |
Report outcomes with evidence inline on the existing endpoint:
curl -X POST http://localhost:8000/v1/executions/EXEC_ID/outcome \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"success": true, "external_id": "stripe_ch_abc123",
"result_url": "https://dashboard.stripe.com/payments/ch_abc123",
"summary": "Charged customer 42"}'Manually verify or reject a parked outcome:
# Approve
curl -X POST http://localhost:8000/v1/executions/EXEC_ID/verify \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"valid": true}'
# Reject (e.g. after audit)
curl -X POST http://localhost:8000/v1/executions/EXEC_ID/verify \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"valid": false, "reason": "invoice number does not match"}'Backward-compat paths still work: POST /outcome with just {success: true} behaves identically to before, and PATCH /v1/executions/{id}/evidence remains available as a two-step alternative.
Worker-transport cues can currently use
noneormanualonly. Evidence-requiring modes (require_external_id,require_result_url,require_artifacts) are rejected at create/update time with400 unsupported_verification_for_transport. This restriction will be lifted once cueapi-worker 0.3.0 ships to PyPI with evidence reporting viaCUEAPI_OUTCOME_FILE.
cueapi-core persists alerts when outcomes go wrong and — if you configure a webhook URL — POSTs them to you with an HMAC signature. Three alert types today:
| Type | When it fires |
|---|---|
consecutive_failures |
Same cue reports success=false three runs in a row |
verification_failed |
Outcome is missing evidence required by the cue's verification mode (see "Verification modes") |
outcome_timeout |
Handler never reports an outcome before the deadline (not yet wired in OSS — coming with the deadline-checking poller) |
Alerts are deduplicated per (user, alert_type, execution_id) within a 5-minute window so flapping executions don't flood your inbox.
curl http://localhost:8000/v1/alerts \
-H "Authorization: Bearer YOUR_API_KEY"
# Optional filters: ?alert_type=consecutive_failures&since=2026-01-01T00:00:00Z&limit=20-
Set your webhook URL:
curl -X PATCH http://localhost:8000/v1/auth/me \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"alert_webhook_url": "https://your-server.example.com/cueapi-alerts"}'
-
Retrieve your signing secret (generated lazily on first call, 64 hex chars):
curl http://localhost:8000/v1/auth/alert-webhook-secret \ -H "Authorization: Bearer YOUR_API_KEY"Rotate with
POST /v1/auth/alert-webhook-secret/regenerate(requiresX-Confirm-Destructive: true). -
Verify incoming alerts on your end. See
examples/alert_webhook_receiver.pyfor a 30-line Flask receiver. Each POST carriesX-CueAPI-Signature: v1=<hex>,X-CueAPI-Timestamp,X-CueAPI-Alert-Id, andX-CueAPI-Alert-Type.
Delivery path is HTTP only. cueapi-core ships alert persistence + webhook delivery and nothing else. For email / SMS / Slack, point your
alert_webhook_urlat a forwarder you control, or use hosted cueapi.ai which includes managed email delivery via SendGrid. See HOSTED_ONLY.md for the full open-core policy.
- Not a workflow orchestrator
- Not a DAG engine
- Not an agent runtime
- Not a replacement for task queues like Celery or RQ
CueAPI does one thing: schedules tasks and tells you whether they succeeded.
| Guide | Description |
|---|---|
| Quick start | Clone, configure, run |
| Configuration | Every environment variable documented |
| Workers | Worker transport setup and scaling |
| Production | PostgreSQL, Redis, reverse proxy, monitoring |
| FAQ | Common self-hosting questions |
Stack: FastAPI, PostgreSQL 16, Redis 7, Docker
Don't want to manage the infrastructure? cueapi.ai is the hosted version.
Free tier: 10 cues, 300 executions/month. No credit card required.
- cueapi-python -- Official Python SDK (
pip install cueapi-sdk)
CueAPI is open source under Apache 2.0. Contributions welcome.
git clone https://github.com/cueapi/cueapi-core
cd cueapi-core
docker compose upThe test suite has 367 tests run by Argus, our QA agent. All PRs must pass.
Good first issues are labeled good first issue on GitHub.
See CONTRIBUTING.md for full contribution guidelines.
CueAPI was independently security-audited with 50+ penetration tests covering SSRF bypass (19 vectors), authentication and authorization, input validation, rate limiting, and information disclosure. Automated scanning performed with OWASP ZAP and Nuclei.
- API keys hashed with SHA-256 - never stored in plaintext
- SSRF protection with dual-time DNS validation (creation + delivery)
- Stripe-style webhook signing (HMAC-SHA256 with replay protection)
- Sliding-window rate limiting per API key and per IP
- Zero sensitive data in logs or error responses
See SECURITY.md for responsible disclosure, architecture details, and self-hosting hardening guide.
Apache 2.0. See LICENSE.
Built by Vector Apps · Hosted at cueapi.ai · Docs at docs.cueapi.ai · Changelog
