buildd
Features

Missions

Team-scoped goals that group tasks, track progress, and gate their own completion

Missions

A mission is a goal that tasks are linked to. It groups related work, tracks progress automatically, plans its own next step as work finishes, and can refuse to close until measurable criteria pass.

Missions were previously called objectives. The rename is complete: there is no manage_objectives action and no /api/objectives endpoint. If you pass objectiveId to create_task it will not be quietly ignored — create_task validates against a strict allowlist and hard-errors with Unknown create_task parameter(s): objectiveId. The field you want is missionId.

Creating Missions

Dashboard

Navigate to Missions, then fill in the title, optional description, priority, workspace, and schedule.

MCP

manage_missions is an admin-level action:

buildd action=manage_missions params={
  action: "create",
  title: "Improve API response times",
  description: "Target p99 under 200ms for all endpoints"
}

API

curl -X POST https://buildd.dev/api/missions \
  -H "Authorization: Bearer bld_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Improve API response times" }'

Linking Tasks

Tasks link to a mission on creation, by linking an existing task, or automatically via inheritance:

# Create a task under a mission
buildd action=create_task params={
  title: "Profile slow endpoints",
  description: "...",
  missionId: "<mission-id>"
}

# Link an existing task
buildd action=manage_missions params={
  action: "link_task",
  missionId: "<mission-id>",
  taskId: "<task-id>"
}

# Unlink a task
buildd action=manage_missions params={
  action: "unlink_task",
  taskId: "<task-id>"
}

IDs are full UUIDs. The dashboard displays 8-character prefixes, which the API rejects — take the full ID from the task URL or an API response.

Auto-Inheritance

When an agent working on a mission-linked task creates child tasks with create_task, those children inherit the caller's missionId automatically. All related work stays attached to the mission without manual linking.

Progress Tracking

Progress is computed from linked tasks and returned alongside the mission, with totalTasks, completedTasks, progress and per-status segments, plus activeAgents for work currently running.

Coordination and planning tasks are classified as housekeeping and excluded from the percentage, so a mission whose real work is done reads 100% even if an organizer run failed. See Autonomous Operation for the details of that distinction.

How a Mission Moves

An auto mission plans its next step as soon as work finishes. Each organizer run opens a planning-mode task that receives the mission's title, description, and task history, then decides what work is still needed and files it.

It also plans when a mission it depends on lands, when you resume it or raise its budget, when one of its PRs merges, and when you add a note or answer a question. New auto missions also get check-ins: an hourly stuck-check that starts the organizer only when the mission looks stuck. A manual mission does not plan on its own. You start each run.

Recurring Missions

To run the organizer on a fixed schedule whether or not anything changed, give the mission a cron expression and turn check-ins off:

buildd action=manage_missions params={
  action: "create",
  title: "Weekly code quality check",
  workspaceId: "<workspace-id>",
  cronExpression: "0 9 * * 1",
  isHeartbeat: false
}

That creates a schedule that opens an organizer run on every tick. With check-ins left on, cronExpression sets when check-ins run instead, and a check-in only starts the organizer when the mission is stuck.

Deferred and Held Starts

A mission can be created now but held inert:

  • startAt (future ISO 8601), startIn (45m, 3h, 2d), or startAfter: "budget_reset" defer the first cycle. The mission is active but produces nothing until the start resolves.
  • startMode: "held" blocks all task claims for the mission until you release it with action: "arm". Force-starting a single task from the dashboard bypasses the gate.
buildd action=manage_missions params={ action: "arm", missionId: "<mission-id>" }

Executor: Runner or Local

By default (executor: "runner"), a mission's tasks are picked up by whichever runner has a free slot. Set executor: "local" to run a mission's tasks yourself, from your own interactive session, instead — background runners skip them entirely:

buildd action=manage_missions params={
  action: "update",
  missionId: "<mission-id>",
  executor: "local"
}

With executor: "local":

  • Runners never auto-claim the mission's tasks.
  • You claim each one explicitly and interactively — claim_task { taskId: "<task-id>" } from your own session — which gives you a normal tracked worker: the same PR link and cost accounting a runner-claimed task gets. Finish it the usual way, with complete_task.
  • The dashboard tags the mission [LOCAL], and a task under it shows "Running in a local session" instead of offering to start it on a runner. "Force start" still hands that one task to a runner if you'd rather it ran there.
  • With the agent plugin installed, your session shows in buildd while it's open, and closing it releases any task you didn't finish back to the queue.

executor is independent of startMode: held is a pause that blocks every claim, interactive sessions included, and wins over executor when both are set. Use executor: "local" for work you intend to drive yourself, and startMode: "held" for work nobody should touch yet.

Goal Criteria

goalCriteria are completion gates that block the mission from closing until they pass. Prefer a mechanical criterion — one whose verdict is a command's exit code or a fact read from the database:

buildd action=manage_missions params={
  action: "update",
  missionId: "<mission-id>",
  goalCriteria: [
    { type: "command", command: "bun run test", label: "tests green" },
    { type: "all_prs_merged" }
  ]
}
TypeVerdict comes from
commandBuildd dispatches a verification task; the exit code is the result
all_prs_mergedDatabase state
no_open_tasksDatabase state
artifact_existsDatabase state
descriptionProse graded by a model
metricNothing — no evaluator exists yet

Two traps worth knowing:

  • description needs a model reachable at the moment a verdict is owed. When one isn't, it degrades to not evaluated, which never counts as a pass. Because of that it requires a notMechanizableReason of at least 10 characters explaining why no mechanical form fits; writes without it are rejected.
  • metric has no evaluator, so it stays unverified and blocks completion forever. Do not use it as a gate.

Criteria are evaluated automatically unless you set autoVerify: false, and evaluation also fires when all of a mission's tasks are done. You can also trigger it on demand, or read the last result without re-running:

buildd action=manage_missions params={ action: "evaluate", missionId: "<mission-id>" }
buildd action=manage_missions params={ action: "get_criteria_state", missionId: "<mission-id>" }

evaluate is rate-limited to 6 calls per hour. If completion is refused, the reason is posted to the mission feed.

Throughput and Budget

ParamEffect
maxConcurrentTasksMission-level parallel cap (1–20). Raises the effective workspace cap when larger, and can lower it for missions that need serialization.
pacingModeeager (default) starts every claimable task immediately; paced enforces a minimum interval between starts.
pacingMaxPerHourTask starts per hour when pacingMode: "paced". Defaults to 1.
costBudgetUsdPause the mission and notify when cumulative worker spend reaches this threshold.

Sequencing Missions

One mission can wait on another:

buildd action=manage_missions params={
  action: "update",
  missionId: "<downstream-mission-id>",
  dependsOnMission: "<upstream-mission-id>",
  gateCondition: "merged"
}

gateCondition is merged (upstream PRs landed) or completed (upstream mission status reached completed).

Mission Lifecycle

StatusDescription
activeDefault. Agents work on linked tasks.
pausedTemporarily suspended.
completedGoal achieved and any goal criteria passed.
archivedHidden from active views.
budget_exhaustedSet automatically when costBudgetUsd is reached.
buildd action=manage_missions params={
  action: "update",
  missionId: "<mission-id>",
  status: "completed"
}

Setting completed is a request, not a guarantee: Buildd counts open tasks and evaluates goal criteria, and refuses the transition if either does not clear.

Workspace Pinning

Missions are team-scoped by default. Pin one to a workspace to scope its work and schedule:

buildd action=manage_missions params={
  action: "create",
  title: "Fix CI pipeline",
  workspaceId: "<workspace-id>"
}

Model Routing

Prefer a tier so dispatch follows your team's model registry rather than a hardcoded model name:

TierUse case
budgetLightweight planning and triage
standardBalanced planning and execution
premiumComplex reasoning and execution

Exact model IDs still work for pinning, and legacy shorthands are still accepted, but tier-first routing survives model upgrades.

Missions can also carry skillSlugs to attach skills to every task they spawn, and backend (claude or codex) to set the default agent engine.

Managing via MCP

All actions belong to manage_missions, which is admin-level. isHeartbeat and heartbeatChecklist are the internal names for check-ins and the Organizer checklist.

ActionParamsDescription
listworkspaceId?, status?List missions
createtitle, description?, workspaceId?, initiativeId?, cronExpression?, isHeartbeat?, heartbeatChecklist?, priority?, skillSlugs?, model?, executor?Create a mission
getmissionIdGet a mission with tasks and progress
updatemissionId, title?, description?, status?, cronExpression?, isHeartbeat?, heartbeatChecklist?, priority?, skillSlugs?, model?, executor?Update a mission
deletemissionIdDelete a mission (tasks preserved)
link_taskmissionId, taskIdLink a task to a mission
unlink_tasktaskIdRemove a task from its mission
armmissionIdRelease a held mission so its tasks become claimable
evaluatemissionIdEvaluate goal criteria on demand (6/hour)
get_criteria_statemissionIdRead the last criteria result without re-evaluating

API Reference

MethodEndpointDescription
GET/api/missionsList missions with progress. Query: ?status=&workspaceId=
POST/api/missionsCreate a mission
GET/api/missions/{id}Get a mission with linked tasks and progress
PATCH/api/missions/{id}Update mission fields
DELETE/api/missions/{id}Delete a mission
POST/api/missions/{id}/linkLink a task to the mission
POST/api/missions/{id}/runStart an organizer run now
POST/api/missions/{id}/evaluateEvaluate goal criteria
GET/api/missions/{id}/evaluateRead the last criteria state
POST/api/missions/{id}/reconcileReconcile mission state against its tasks
GET/api/missions/{id}/artifactsList mission-level artifacts
POST/api/missions/{id}/artifactsAttach a mission-level artifact
GET/api/missions/{id}/notesRead the mission feed
POST/api/missions/{id}/notesPost to the mission feed

Example

# Create a mission
curl -X POST https://buildd.dev/api/missions \
  -H "Authorization: Bearer bld_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Ship v2.0",
    "description": "Complete all v2 features",
    "priority": 10,
    "cronExpression": "0 9 * * 1",
    "workspaceId": "<workspace-id>"
  }'

# Read it back with progress
curl https://buildd.dev/api/missions/{id} \
  -H "Authorization: Bearer bld_xxx"

Requires session auth or an admin-level API key.

On this page