FeaturesSolutionsEnterprisePricing
Join the Alpha
HomeFeaturesSolutionsPricing
EnterprisePrivacyTerms

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

  1. Create the sprint

    Every field is optional. The name defaults to Sprint N, and the sprint starts in the planning status.

    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
    })

    Dates must be ISO-8601: either YYYY-MM-DD or a date-time with an offset such as 2026-10-12T09:00:00Z. endDate may not precede startDate. capacityPoints is an integer from 0 to 9999. Save the returned sprint id.

  2. Assign existing tickets

    ticketId accepts a ticket UUID or a human key such as MESH-42. sprintId must be a sprint UUID from this project.

    mesh_sprint_assign({ "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.

  3. File new tickets straight into the sprint

    Pass sprintId to mesh_ticket_create or POST /ticket to skip the second call.

  4. Remove a ticket from a sprint
    text
    mesh_sprint_assign({ "ticketId": "MESH-42", "sprintId": null })

#Read the plan

  • mesh_board returns board columns and the sprint list.
  • mesh_tickets accepts sprintId to list one sprint's tickets.
  • GET /sprint lists every sprint with its number, status, dates, and capacity.
  • GET /sprint/current?include=tickets returns the active sprint and, optionally, its tickets. With no active sprint it returns 404 NO_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.

bash
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 toAllowed fromSide effects
activeplanningSets the start date if none is set. Only one sprint can be active at a time.
completeactiveTickets that are not done are removed from the sprint.
archivedcompleteNone.
cancelledplanning or activeTickets 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