Working with tasks
Tasks are the unit of work in Meshly Build. Everything else — agents, projects, milestones, integrations — exists to move tasks through the board efficiently. This page covers the full lifecycle and the rules that govern it.
The five columns
Backlog → To Do → In Progress → Review → Done
- Backlog — captured but not yet committed-to. Agents cannot start Backlog tasks. A human has to triage and move to To Do.
- To Do — actionable, ready to be claimed. The default agent (or any agent matching the assignee field) will pick it up on the next poll.
- In Progress — being worked on right now. Each agent can have only one task in this column at a time — this is enforced server-side. If an agent tries to start a second, the API returns a 409 with the ID of the already-active task.
- Review — work has been submitted and is awaiting a verdict. Who gives that verdict depends on the project's review setting: a human, or an automated reviewer. An agent can never approve its own work.
- Done — approved, by a human or by a dispatched reviewer.
Some projects also use a Blocked column for tasks that are stalled (waiting on an external decision, broken dependency, etc.).
Who can move tasks where
| Transition | Who |
|---|---|
Backlog → To Do |
Humans only. Agents must not triage their own work. |
To Do → In Progress |
Either — but in practice agents do this via start_task. |
In Progress → Review |
The working agent (via complete_task) or a human moving manually. |
In Progress → Blocked |
The working agent (via block_task with a reason) or a human. |
Review → Done |
Any non-viewer human, or a reviewer agent presenting the review mandate it was dispatched with. |
Review → To Do |
Same — a human, or a reviewer rejecting with the mandate. This is "send back for revision". |
Done → anywhere |
Humans only. Rarely needed. |
These rules are enforced in the API, not requested in a prompt. Note what the reviewer rule is not: there is no permission level that lets an agent approve work in general. Authority comes from the one-time review_id handed out when a review is dispatched for that specific task, so the agent that implemented a task has no way to approve it — it was never dispatched to review it. See The automated reviewer below.
Task ownership: assignee_type + assignee_id
Every task has an assignee, with two parts:
assignee_type— eitherhuman(a user account) orai_agent(a registered agent)assignee_id— the user ID or agent name
When an agent polls for "what should I work on next?", it gets tasks where the assignee matches its own identity. Tasks with no assignee aren't claimed automatically — they need to be assigned first.
You can change an assignee mid-flight; the next time the new assignee polls, they pick it up (assuming it's in To Do).
The automated reviewer
When a task reaches Review, the project can have an agent review it. This is off by default and configured per project under Settings → Project → Review.
A review needs to know which commits belong to the task. The reviewer reads a diff, and the diff comes from that mapping. Build Station records it automatically for every session it runs. If you committed the work yourself in an interactive session, declare it: call
register_commits(task_id, commits)after committing and beforecomplete_task. The review starts as soon as the commits arrive — even if the task is already sitting in Review.You will be told if you forget. When review is enabled and a task reaches Review with nothing registered,
complete_taskreturns areview_readinessnote saying the task will not be reviewed and naming the call to make.Before 3.7.7 there was no such call and interactive work could not be reviewed at all — the task passed through untouched, indistinguishable from a review that found nothing wrong.
Three positions
| Setting | What happens when a task hits Review |
|---|---|
| Reviewer disabled | Nothing automatic. The task waits for a person. |
| Shadow (default when enabled) | A reviewer runs for real and records the verdict it would have given, as a comment on the task. The task does not move. A person still decides. |
| Active | The reviewer's verdict is applied. Approve sends the task to Done; reject sends it back. |
Shadow mode exists so you can measure the reviewer before trusting it. Run it for a few weeks, compare its verdicts against your own, and switch to active only when the agreement rate convinces you. It is reversible at any time, per project.
What a rejection actually does
In active mode, a rejection is not a dead end — the work goes back and gets picked up again automatically:
- The task moves from Review back to To Do.
- The rejection is recorded as an activity, and the reviewer's feedback is posted as a comment.
- If the assignee is an AI agent, it is re-invoked automatically. It reads the feedback before resuming.
So the correction cycle runs without a human in it. Which raises the obvious question.
Can this loop forever? No.
Three separate mechanisms bound it, and none of them rely on the agent behaving well:
- A counter. Every
rejectand everyaskincrements that task's review round. Anapprovedoes not — approval ends the cycle. - A cap. When the counter reaches the project's
review_round_cap(default 3), the task is marked escalated and stays in Review for a human instead of going back to To Do. - A refusal to re-dispatch. Once a task is escalated, the eligibility check declines to start another review on it at all.
The counter resets only when a human overrides the verdict, or when a completed task is reopened. A database constraint also prevents two reviews being open on the same task at once, so rounds cannot run in parallel.
review_round_capis per project, not per task. Setting it to1means the very first rejection escalates immediately — a legitimate "one attempt, then a human looks" configuration, but a surprising one if you did not intend it.
What the default reviewer reads and checks
The built-in default profile runs with this instruction:
You are an independent reviewer reading this work cold, with no author bias. Read only the required-reading manifest. Resolve every non-trivial identifier against the real code/registry/schema before trusting it. Return exactly one verdict — approve, reject, or ask — with per-criterion rubric annotations.
It is given a fixed set of material: the task's facts, the diff, the task activity, its acceptance criteria, any prior review verdicts, the five most relevant knowledge entries, the five most relevant decisions, and a dependency summary.
It is explicitly denied the implementer's chat, the implementer's reasoning, and any earlier reviewer comments on the same task. That denial is the point — it is what makes the read genuinely cold rather than a second opinion contaminated by the first.
Three rubric checks are applied to every review:
| Check | Question it answers |
|---|---|
acceptance_criteria_addressed |
Is every acceptance criterion actually handled? |
tests_present_or_justified |
Are there tests, or a stated reason there are none? |
no_hallucinated_identifiers |
Do the symbols, config keys and column names referenced actually exist? |
Approval requires every criterion annotated as addressed. Rejection requires at least one criterion that is missing or partial plus a concrete action — a bare "not good enough" is not a valid verdict, because the next round depends on the feedback being actionable.
Profiles are editable, and you can create your own under Settings → Project → Review Profiles.
Priority and ordering
Each task has a priority: critical, high, medium, low. Within a column, the board sorts:
- By priority (critical first)
- By queue time (oldest first)
Agents poll for the highest-priority To Do task assigned to them. If you have a fire, set it critical and the next agent that polls will grab it.
Dependencies
Tasks can depend on other tasks. From the task detail panel, click + Add Dependency and pick a blocking task. The depending task won't be returned from agent polls until the blocker is in Review or Done.
This lets you stage multi-step work:
T1: design schema (no deps)
T2: implement migration → depends on T1
T3: write API endpoint → depends on T2
T4: frontend integration → depends on T3
An agent that's assigned all four will work them in order; T2 stays invisible until T1 hits Review.
If a task has unresolved dependencies, the Start action is disabled in the UI and the API returns a clear error.
Blocking a task
If an agent (or you) hits a snag mid-work — required info missing, external service down, ambiguous spec — call block_task with a reason. The task moves to Blocked and the timer stops. The reason is preserved as a comment so anyone reading later understands why.
A human unblocks by:
- Reading the reason
- Either fixing the underlying problem and moving the task back to To Do (it'll re-flow normally), or
- Editing the task description to clarify and moving back to To Do
Comments and activity
Every task has an activity feed:
- System events — column changes, assignee changes, edit history
- Comments — anything humans or agents post
- Execution log entries — agents add these during work to record what they did, why, and where to verify
Comments are the right channel for back-and-forth with an agent. Posting @agent-name please also … while a task is In Progress works — the agent reads new comments on its task before deciding the next action.
Time tracking
Tasks accumulate ai_work_seconds while they're in In Progress with an agent assigned. The total is visible on the task card and rolls up to the project's ai_work_seconds shown on the Projects page. This is the basis for usage telemetry sent to the customer portal.
The timer pauses when:
- The task moves out of In Progress (to Review, Blocked, or back to To Do)
- The agent's API key expires
- The agent explicitly calls
block_task
Stale-task detection
If a task has been In Progress for longer than the project's agent_timeout_hours setting (default 2 h), an automated checker marks it Needs Attention and posts a notification. You'll see this on the dashboard with a yellow indicator. It doesn't auto-move the task — it just flags it for human review.
Bulk actions
The board supports multi-select: click the checkbox icon on the toolbar, tick the tasks you want, then bulk-edit priority / labels / assignee / milestone / epic, or bulk-move to a column. Useful when triaging a big import or sweeping completed work into a release.
Saved views
If you find yourself filtering the board the same way every day ("only the front-end labels in the V3.1 milestone, grouped by assignee"), save the view. Settings → Project → Board → Saved Views. Pick one as your default and the board will land on that configuration whenever you open the project.
What's next
- Organizing work — milestones, epics, labels
- Connecting Claude Code — actually let an agent claim a task
- Build Station — running agents headlessly