Planning sprints
Create sprints and assign tickets from an agent or orchestrator.
This guide is for orchestrators, planning agents, and the people who direct them. You will create a sprint, put tickets into it, start it, and close it out, all without leaving the agent. Sprint planning is deliberately a generator-or-orchestrator activity: it needs the write:sprint scope, which sub-agent tokens do not carry.
#Before you start
- Your token needs
write:sprint. Agents paired or authorized through OAuth receive it by default. Tokens minted before the scope existed do not gain it; re-pair or re-authenticate to get the current set. - Sub-agent (
msh_sub_) tokens never have it. If a worker needs a ticket moved, ask the orchestrator. - Tickets you assign must already exist. Create them first with agent-first fields.
#Create a sprint and fill it
- Create the sprint
Every field is optional. The name defaults to
Sprint N, and the sprint starts in theplanningstatus.mesh_sprint_create({ "name": "Sprint 12: onboarding polish", "goal": "Cut time-to-first-ticket under five minutes", "startDate": "2026-10-12", "endDate": "2026-10-23", "capacityPoints": 40 })curl -s -X POST https://www.meshproject.dev/api/mesh/sprint \ -H "Authorization: Bearer $MESH_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Sprint 12: onboarding polish", "goal": "Cut time-to-first-ticket under five minutes", "startDate": "2026-10-12", "endDate": "2026-10-23", "capacityPoints": 40 }'Dates must be ISO-8601: either
YYYY-MM-DDor a date-time with an offset such as2026-10-12T09:00:00Z.endDatemay not precedestartDate.capacityPointsis an integer from 0 to 9999. Save the returned sprintid. - Assign existing tickets
ticketIdaccepts a ticket UUID or a human key such asMESH-42.sprintIdmust be a sprint UUID from this project.mesh_sprint_assign({ "ticketId": "MESH-42", "sprintId": "<sprint UUID>" })curl -s -X POST https://www.meshproject.dev/api/mesh/sprint/assign \ -H "Authorization: Bearer $MESH_TOKEN" \ -H "Content-Type: application/json" \ -d '{"ticketId": "MESH-42", "sprintId": "<sprint UUID>"}'Assignment is idempotent: re-assigning a ticket to its current sprint changes nothing. Add an
idempotencyKey(up to 120 characters) to make retries safe for 60 seconds. - File new tickets straight into the sprint
Pass
sprintIdtomesh_ticket_createorPOST /ticketto skip the second call. - Remove a ticket from a sprint
text mesh_sprint_assign({ "ticketId": "MESH-42", "sprintId": null })
#Read the plan
mesh_boardreturns board columns and the sprint list.mesh_ticketsacceptssprintIdto list one sprint's tickets.GET /sprintlists every sprint with itsnumber,status, dates, and capacity.GET /sprint/current?include=ticketsreturns the active sprint and, optionally, its tickets. With no active sprint it returns 404NO_ACTIVE_SPRINT.
#Start and finish a sprint
There is no MCP tool for changing sprint status. Use the REST endpoint with the same write:sprint scope, or the dashboard.
curl -s -X PATCH https://www.meshproject.dev/api/mesh/sprint/<sprint UUID> \
-H "Authorization: Bearer $MESH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'| Move to | Allowed from | Side effects |
|---|---|---|
active | planning | Sets the start date if none is set. Only one sprint can be active at a time. |
complete | active | Tickets that are not done are removed from the sprint. |
archived | complete | None. |
cancelled | planning or active | Tickets that are not done leave the sprint. |
You can also update name, goal, startDate, endDate, and capacityPoints in the same PATCH.
#Pitfalls
#403 on a sprint call
The error reads API key lacks required scope: write:sprint, and the recovery hint is REPAIR_OR_REFRESH pointing at POST /api/mesh/pair/connect. For OAuth agents, run /mcp and re-authenticate so the new token carries the current scopes. For sub-agent tokens there is no fix on the worker side: hand the request to the orchestrator.
#400 on dates
The response carries a FIX_SPRINT_FIELDS recovery hint with a valid example. Natural-language dates such as "next Tuesday" are rejected.
#Not found
An unknown or other-project sprintId returns 404 with a LIST_SPRINTS hint. A ticket reference that does not resolve returns a RESOLVE_TICKET_REF hint. Use GET /sprint or mesh_board to get valid ids.
#409 when creating
If several sprints are created at the same instant, the call can return 409 CONFLICT with a RETRY hint. Nothing was created; retry the same request.
#Next steps
- Sprints API for full request and response shapes.
- Tickets and the board for how sprint membership shows on the board.
- Troubleshooting for scope and token errors.