The queue and its holds
How the Borago Board queue picks the next task, why only one task runs per project, and every reason the queue can pause, with the banner each one shows.
Each project has its own queue. It runs the board-owned To Do tasks one at a time, in the order you arranged them, and it runs nothing while any task in the project is working. When it stops starting tasks it says why, in a banner at the top of the To Do column, and that banner is the subject of the second half of this page.
How the queue picks the next task
The queue looks again whenever something changes that could free work. A task enters To Do, a run ends, a question is answered, a review finishes, a hold is resumed, a task created on the browser or the phone arrives by sync, or the app starts. What it does is the same each time.
- One run at a time. While any task in the project is working, nothing else starts. A task parked on a declared background wait counts as working.
- Your order is the order. The candidates are the board-owned To Do tasks, in the order you arranged them in the column. The app does not reorder cards by similarity, cost or anything else. A user task, one a person is working on, is never picked.
- A task still being reviewed waits. The pre-run review runs after a task is saved and takes a second or two. A task dragged to To Do in that window starts once the review has finished, so a question the review asks is not lost to a run that has already begun.
- A task woken from a wait goes first. When a declared background wait ends, the woken task runs before any other, whatever its position.
- Declared prerequisites are honoured. A task that names another task with an
@#nmention in its title or description waits until that task is Done, Canceled or closed. Blocked does not satisfy a prerequisite. A mention of a task that does not exist counts for nothing rather than blocking for ever. Mentions in comments are not read as prerequisites. When every candidate is waiting on a prerequisite, the queue holds with the prerequisite reason. - Blocked work is not stepped on. A candidate whose text overlaps a Blocked task's in the same project is skipped, because it would likely touch work that task left half-done in the shared container. When every candidate overlaps, the queue holds with the blocked interference reason.
- The picked task's own checks run before anything is spent. The cost budget for the task's provider, a free check that the stored credential still works, and, with container management on, whether the container can reach the policy proxy. Each can hold the queue.
- Then the run starts. The task is marked working with its start time. From here How a run works takes over.
The task mentions that declare order are ordinary text. The picker inserts them, they render as a chip, and deleting the chip removes the dependency. When a run splits its work into new tasks and declares an order between them, the same @#n mention is written into each new task's description, so there is one mechanism and it is visible on the card. Writing tasks the agent can do covers how to write them.
One run per project
One task runs at a time per project, because every task in a project shares one container, one working tree, one index and one branch. The rule is enforced on the server, on every path a run can be asked for, and not by disabling a button, because the board is realtime and a card can start running between the moment a button is drawn and the moment it is pressed.
A press on Run with the provider's name while another task in the project is running gets a polite refusal, not a failed run. The board moves the pressed task to To Do, where the queue picks it up once the container is free, and shows a one-button dialog that names the running task by its title and says that one task runs at a time because they share the project container. The same happens when the queue claims the very task you pressed in the instant before your press landed. A manual run is also refused, and queued in the same way, while the container cannot reach the policy proxy with container management on.
Manual runs are otherwise not gated. Pressing Run with ignores position order, prerequisites, the interference check, the cost budget and a rate limit wait. Only the auto-queue honours those.
Guards on a task
| Situation | What the board does | Why |
|---|---|---|
| A task has an unanswered question from the agent | A board task cannot be moved to To Do or In Progress, by drag or otherwise. The refusal says the task is waiting on you and that it can still be closed or moved to Blocked | To Do is what the queue picks up. A fresh run would ask the same question again and the answer being typed would be lost |
| A task has the needs-action flag | Moving it to To Do or Planning is allowed and clears the flag | The move is the acknowledgement. "I have read the note, run it again" must stay one gesture |
| A board task moved to In Progress by hand | Refused. A board task enters In Progress only when a run starts. A user task can be moved there, since a person is its worker | In Progress on a board task means a run exists |
| A task parked on a declared wait | Keeps its claim. The queue starts nothing else in the project and a manual run is refused. Stop, a drag, a close or a delete end the wait within one poll interval | One container serves every task, and a run during the wait would disturb the state being waited on |
| A running card | Cannot be dragged. Dragging it opens the Stop confirm | A drag is a status change, and a status change on a live run is a Stop |
| A task moved to Done, Blocked or Canceled by hand | Always allowed, question or not | Closing a task must never require answering it first |
The holds
When the queue leaves work in To Do it records why, and the To Do column shows a banner with a short label, the number of tasks waiting, and a sentence built where the hold was decided. Every hold gates admission only. A task already running is never stopped by a hold, and several sentences say so.
The time shown, when there is one, is a deadline the queue honours on its own, worded "Resumes at". A Resume button appears in the column header for the holds where pressing it can work. It does not appear for a hold that would re-apply the instant the queue re-evaluates, because a button that cannot work is worse than none.
| Reason | What decides it | What the banner shows | Time shown | Resume |
|---|---|---|---|---|
| Blocked interference | Every To Do task overlaps a Blocked task in the project by the interference rule above | "Auto-run paused - blocked work", then a sentence naming the blocked task and saying to answer, retry or close it to continue | None | No. It would re-apply at once. Unblocking the named task moves the queue |
| Prerequisite | Every To Do task declares an @#n prerequisite that is not yet Done, Canceled or closed | "Auto-run paused - waiting on a prerequisite", then a sentence naming the task being waited on | None | No. The hold lifts on the next kick once the prerequisite is Done, Canceled or closed. A run finishing the prerequisite kicks the queue by itself |
| Rate limit | The provider answered a run with a rate limit. The task returns to To Do with no retry spent | "Auto-run paused - provider rate limit", then "The provider returned a rate limit. Tasks already running are not affected." After an app restart only the wait survives, and the sentence is "Waiting out a provider rate limit." | A deadline. The provider's stated reset plus 5 minutes, or 5 minutes doubling to a cap of 60 when it stated none | Yes. Resume runs the next task without waiting |
| Auth | The stored credential was rejected, either by the free check before the run or by the run itself. The task returns to To Do | "Auto-run paused - sign-in needed", then a sentence saying to sign in again, that the stored credential was rejected so nothing new will start, and that runs resume by themselves once the new sign-in verifies | None | Yes, and unnecessary. A successful sign-in under the project's AI Auth tab lifts the hold and resumes the To Do task on its own |
| Cost budget | This machine's estimated spend on the picked task's provider reached the budget set for that provider in the project's AI Auth tab. The task itself is untouched | "Auto-run paused - cost budget", then a sentence naming the provider, saying its spend has reached this machine's budget, giving the amount spent so far, and saying to reset the spend to resume | None | No. Reset spend on the provider's card in AI Auth, or a changed budget, re-kicks the queue. A self-hosted service has no budget |
| Retry exhausted | A task failed six consecutive attempts and is now Blocked. The whole project queue pauses, not only that task | "Auto-run paused - a task failed every retry", then a sentence naming the task, saying that pauses the whole project queue, and to resume to try again | None | Yes |
| Credits | The provider answered that the API key has no credit or quota left. The task is Blocked at once | "Auto-run paused - API credits exhausted", then a sentence naming the provider's API key, saying every run would fail the same way, and to top up the provider account and then resume | None | Yes. After topping up, move the blocked task back to To Do as well |
| Task failed | A run failed with an error a retry cannot fix, such as a rejected request or a model the key cannot use, and the task is Blocked on that first failure. Also the sixth consecutive failure to reach the provider at all | "Auto-run paused - a task hit an error a retry cannot fix", then a sentence naming the task and the error and saying to fix it on the task, then resume. For an unreachable provider it says either to restart the project's container, when the provider reports no incident, or to wait for the provider to recover | None | Yes |
| Model access | The provider's refusal says the plan does not include the chosen model. A model the API key cannot use usually blocks as task failed instead | "Auto-run paused - no access to the chosen model", then a sentence naming the model and saying to pick one your plan includes, then resume | None | Yes. Changing the project's model also clears it |
| Firewall blocked | Container management is on and, before the claim, the container tried to reach the policy proxy and this machine's firewall dropped the attempt | "Auto-run paused - allow Docker access through the firewall", then a sentence saying container management is on but this machine's firewall is blocking the container's access to Docker, with the port and the exact rule for this host | None | Yes. Resume tries again. The rule itself is applied from the project's Containers tab. Container management covers it |
A hold also raises a notification once, when it is new. A change of reason counts as new, so a rate limit that expires into a prerequisite hold announces itself again. When only a wait time survives an app restart and the reason does not, the banner says plainly that auto-run is paused until that time before starting anything new, and does not guess at a cause. Cost and usage covers setting a budget and reading spend.
What a browser or phone sees
A hold describes what the desktop's queue is doing right now. It is not project data and it does not sync, so a cloud project row on its own reads as never held. Instead the desktop reports its held projects to the cloud over the relay, alongside its Docker state, and the browser and the phone render the state of the machine that actually runs the tasks. The reason travels as sent, so a rate limit on the desktop reads as a rate limit on the phone.
The task a hold names is carried by its title, never by its number or id. Numbers and ids are assigned per device, so a hold recorded on the desktop and read on a phone would otherwise name a card that does not exist there.
Resume is relayed too. Pressing it on the browser or the phone resumes the queue on the desktop while the desktop is connected. With the desktop away the press fails with a message rather than doing nothing, and a disconnected desktop reports no holds at all, so the banner disappears rather than staying up with nothing to clear it. There is no Run with button on the browser or the phone. The way to run a task from there is to move it to To Do and let the desktop's queue pick it up. Cloud, browser and phone covers what else needs the desktop online.
Related: How a run works, States, The relay, When the agent asks a question or needs you, Cost and usage.