Concurrency Limits
Understand and manage how many requests you can run simultaneously on Wiro.
Overview
Concurrency limits control how many tasks your account can process at the same time. When you reach your limit, the API returns an error response with code 96. You should wait for a running task to complete before submitting a new one, or add funds to increase your limit.
How It Works
Your concurrency limit is determined by your current account balance:
- When your balance is $250 or below, your limit is one unfinished task for each full $10 of balance, never less than 1. So $20 allows 2, $55 allows 5 and $250 allows 25.
- When your balance is above $250, there is no concurrency limit.
The balance is the credit that can pay for the model you run. Coupon credit that only works on other models is left out, so for those runs the limit can be lower than your wallet total would give.
For a team project's API key (or the team workspace in the dashboard), the limit uses the team wallet's balance, and every unfinished team task counts toward it, whichever member started it. Personal tasks count only against your personal balance. See Team Billing & Spending.
Examples
| Account Balance | Concurrent Task Limit |
|---|---|
| $10 | 1 concurrent task (minimum) |
| $50 | 5 concurrent tasks |
| $100 | 10 concurrent tasks |
| $150 | 15 concurrent tasks |
| $250 | 25 concurrent tasks |
| Above $250 | Unlimited (no limit applied) |
The formula: max(1, floor(balance_usd * 0.10)) while the balance is $250 or less. Above $250 there is no concurrency limit.
What Counts as Active
Every unfinished task counts toward your concurrency limit, from task_queue until it reaches one of these statuses:
task_postprocess_end: task completed (success or failure)task_cancel: task was cancelled or killed
Until then the task counts, including while it waits in the queue and while it is in task_error, which does not close a task. Once it reaches either of these statuses, it no longer counts toward your limit.
API Response
When you hit the concurrency limit, the POST /Run endpoint returns an error with code 96:
{
"result": false,
"errors": [
{
"code": 96,
"message": "You have reached your concurrent task limit. With your current balance of $50.00, you can run up to 5 tasks at the same time. Add funds to increase your limit."
}
]
}
The error message includes your current balance and the calculated limit, so you know exactly how many concurrent tasks you can run.
Error Codes
| Code | Meaning | Action |
|---|---|---|
96 |
Concurrent task limit reached | Wait for a running task to finish, or add funds |
97 |
Insufficient balance | Add funds to your account |
Handling Code 96
A refused request returns HTTP 200 with "result": false and an error with code 96. No task is created and nothing is charged. Handle it in one of these ways:
- Wait and retry: send the same request again after a growing wait, for example 2, 4, then 8 seconds, up to a minute. The code examples on this page do this: they look for the number
96inerrors[].code, retry only that code, treat"result": trueas success and stop after 8 attempts. - Queue on your side: keep at most as many unfinished tasks as your limit allows, and send the next request when a task reaches
task_postprocess_endortask_cancel(Task/Detail or the WebSocket). Tasks started on the website, by agents and by workflows, and in a team by other members, use the same slots. - Direct LLM Gateway: through the Direct LLM Gateway the refusal arrives as HTTP
429with error typerate_limit_errorand aretry-afterheader; wait that many seconds before you retry. A streamed Responses request has already answered200, so it ends withresponse.failedcarrying coderate_limit_exceededand has no such header; use a growing wait there. - Wiro MCP server: through the Wiro MCP server,
run_modelreturns the same message as its tool error.
Increasing Your Limit
To increase your concurrency limit, add credits to your account. Your limit is recalculated automatically based on your current balance at the time of each run request.
Best Practices
-
Check error code
96: if you get this error, wait for a running task to complete before submitting new ones. See Handling Code 96. -
Use WebSocket for monitoring: instead of polling
/Task/Detailrepeatedly, connect via WebSocket to get real-time updates without extra API calls. -
Use bounded MCP waits:
run_modelwaits up to 45 seconds by default and returns a recoverable token when the task is still active. Continue withwait_for_task; do not callrun_modelagain for the same request. Usewait=falseonly when you need the token immediately, andget_taskfor a one-time status check. - Implement exponential backoff: if polling task status, start at 3 seconds and increase the interval for longer tasks.