Plans and quotas
What you get on each plan, how the limits are enforced, and what happens when you hit one.
Three plans, three sets of limits. Everything is enforced server-side — your code doesn't have to track quotas.
Plan matrix
| | Free | Pro | Scale | | --- | --- | --- | --- | | Price | $0 | $99 / mo | $499 / mo | | Agent-hours / month | 50 | 1,000 | Unlimited | | Concurrent agents | 1 | 3 | 20 | | Max duration / run | 30 min | 2 hr | 4 hr | | Container CPU | 0.5 vCPU | 1 vCPU | 2 vCPU | | Container memory | 512 MB | 1 GB | 2 GB | | Spawns / minute | 5 | 30 | 100 | | Spawns / hour | 30 | 500 | 5,000 | | Memory pool | 100 | 10,000 | 100,000 |
How quotas reset
- Agent-hours reset on the first of each calendar month (UTC).
- Spawn rate limits are rolling windows — 1 minute and 1 hour from each spawn.
- Memory quota is a hard ceiling on live memories; it doesn't reset, but
dedupeanddeletereduce the count. - Concurrent agents is real-time; finishing a run immediately frees a slot.
What happens when you hit a limit
The API returns a structured error and a recommended action:
| Limit hit | HTTP | Error code | Recommended action |
| --- | --- | --- | --- |
| Spawn rate | 429 | rate_limited | Honor the Retry-After header; back off |
| Concurrent agents | 429 | concurrent_limit_reached | Wait for one to finish, or stop one |
| Monthly agent-hours | 402 | monthly_quota_exceeded | Upgrade, or wait for the next month |
| Memory pool | 402 | memory_quota_exceeded | POST /api/v1/memory/dedupe, or upgrade |
| Max duration (in-flight) | n/a | agent transitions to error with reason max_duration_exceeded |
The error response always includes a details block telling you the current usage and the limit, so you can render a useful UI on top.
{
"error": {
"code": "concurrent_limit_reached",
"message": "You've reached your concurrent agent limit (3)...",
"details": {
"plan": "pro",
"currentConcurrent": 3,
"maxConcurrent": 3
}
}
}Upgrading
The Console at /console/billing handles plan changes through Stripe Checkout. Upgrades take effect immediately — your next spawn is on the new tier. Downgrades take effect at the end of the current billing period (you keep what you paid for).
Edge cases worth knowing
past_duesubscriptions keep their paid tier through Stripe's smart-retry window. We don't downgrade until retries exhaust.canceledsubscriptions drop back to Free at the next call — your stored data (agents, memory) is preserved.- Free overage is hard-cut. The 51st agent-hour on Free returns
monthly_quota_exceeded; we don't soft-fail. - Spawn rate limits are per API key, not per account. Multiple keys on the same account get separate buckets.
Related
- Rate limits — header reference and back-off recipes
- Errors — every error code and how to react to it
- Billing in the Console — upgrade, change card, view invoices