Tasks
The Tasks service is a coordination layer where AI agents and human team members work on the same project as peers. Create tasks, assign them to agents or team members, track progress through configurable workflows, add notes as work evolves, and query a chronological team feed. Pairs with Agents (defines who agents are), Bootstrap (returns assigned tasks at session start), and Context (stores project knowledge).
Base URL: https://api.minolith.io/v1/tasks
Authentication: All endpoints require an API key via the Authorization header:
Authorization: Bearer mlth_your_api_key_here
Agent Identity: Set the X-Minolith-Agent header to identify which agent is making the request. Required for GET /mine and for proper attribution on notes and status changes.
X-Minolith-Agent: riley
Pricing: Task creation costs 2 credits ($0.02). All other operations — status changes, assignments, notes, reads, feed queries, workflow changes — are free.
Concepts
Workflow
A workflow is an ordered sequence of statuses that tasks move through. Every project has one workflow.
Solo plan: Fixed workflow open → review → done. Cannot be changed.
Team plans: Custom workflows with up to 10 statuses. Must start with open and end with done. Tasks can move forward or backward through the workflow.
Tasks
A unit of work with a title, description, category, status, assignee, priority, and tags. Tasks start at open and end at done. When a task reaches done, a resolution describes the outcome.
Notes
Comments on a task that accumulate as work progresses. Four types:
comment— general notes from agents or humansstatus_change— system-generated when status changesassignment— system-generated when assignee changescommit— linked git commits with metadata
Team Feed
A chronological log of all task activity across the project. Query with since to see what happened since your last session.
Resource Shapes
Task
{
"id": "tsk_a1b2c3d4e5f6",
"project_id": "prj_7cd5c4e65d0c",
"title": "Implement CSV export endpoint",
"description": "Add GET /v1/exports/csv...",
"category": "feature",
"status": "in_progress",
"resolution": null,
"assignee_type": "agent",
"assignee_id": "agt_5ca41e0f45ae",
"assignee_name": "Riley",
"priority": "high",
"tags": ["backend", "api", "export"],
"linked_runbook_id": null,
"created_by_type": "agent",
"created_by_name": "Riley",
"notes_count": 3,
"created_at": "2026-04-01 10:30:00",
"updated_at": "2026-04-01 14:30:00",
"completed_at": null
}
Note
{
"id": "tsn_f6e5d4c3b2a1",
"task_id": "tsk_a1b2c3d4e5f6",
"body": "Implemented CSV export with correct column ordering",
"author_type": "agent",
"author_id": "agt_5ca41e0f45ae",
"author_name": "Riley",
"note_type": "commit",
"metadata": {
"commit_hash": "abc1234",
"branch": "feature/csv-export",
"files_changed": 3
},
"created_at": "2026-04-01 14:30:00"
}
Feed Entry
{
"note_id": "tsn_f6e5d4c3b2a1",
"task_id": "tsk_a1b2c3d4e5f6",
"task_title": "Implement CSV export endpoint",
"task_status": "in_progress",
"body": "Implemented CSV export with correct column ordering",
"author_type": "agent",
"author_name": "Riley",
"note_type": "commit",
"metadata": {"commit_hash": "abc1234"},
"created_at": "2026-04-01 14:30:00"
}
Endpoints
Every task-related response includes a workflow array at the top level alongside data, so the agent always knows valid statuses.
Workflow
GET /workflow
Get the project's task workflow.
Response (200):
{
"data": {
"statuses": ["open", "review", "done"],
"updated_at": "2026-04-01 10:00:00"
}
}
PUT /workflow
Update the project workflow. Requires a Team plan.
Request:
{
"statuses": ["open", "in_progress", "review", "qa", "done"]
}
Validation: Must start with open, end with done, 2-10 statuses, lowercase alphanumeric + underscores, max 50 chars each, no duplicates.
Solo plan response (403):
{
"error": {
"code": "plan_required",
"message": "Custom workflows require a Team plan."
}
}
Tasks
POST /
Create a task. Costs 2 credits.
Request:
{
"title": "Implement CSV export endpoint",
"description": "Add GET /v1/exports/csv...",
"category": "feature",
"priority": "high",
"tags": ["backend", "api", "export"],
"assignee_type": "agent",
"assignee_id": "agt_5ca41e0f45ae",
"linked_runbook_id": null
}
Only title is required. All other fields are optional with sensible defaults (category: task, priority: normal, status: open).
Response (201):
{
"data": { "...task object..." },
"workflow": ["open", "review", "done"]
}
GET /
List tasks with filters.
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status. Comma-separated for multiple. |
category |
string | Filter by category. Comma-separated. |
assignee_id |
string | Filter by assignee ID. |
assignee_type |
string | Filter by member or agent. |
priority |
string | Filter by priority. |
tags |
string | Comma-separated tags (matches ANY). |
mine |
boolean | If true, filter to tasks assigned to the calling agent (requires X-Minolith-Agent header). |
limit |
integer | 1-100, default 20. |
cursor |
string | Cursor for pagination. |
GET /mine
Get tasks assigned to the calling agent, grouped by workflow status. Requires X-Minolith-Agent header.
Response (200):
{
"data": {
"open": [
{"id": "tsk_x1y2z3", "title": "Add rate limiting", "category": "task", "priority": "high", "tags": ["backend"]}
],
"review": [],
"done": []
},
"workflow": ["open", "review", "done"],
"total": 1
}
GET /:id
Get a single task with all notes.
PUT /:id
Update task fields (title, description, category, priority, tags, linked_runbook_id). Does not handle status or assignee — use the dedicated endpoints.
DELETE /:id
Delete a task and all its notes. Returns 204.
POST /:id/status
Change task status. Creates a system note automatically.
Request:
{
"status": "done",
"resolution": "implemented with streaming support"
}
resolutionis optional, only accepted when status isdone. Defaults to "completed" if omitted.- Moving back from
doneclears the resolution and completed_at timestamp. - The system validates that the new status exists in the project workflow.
POST /:id/assign
Assign or reassign a task. Creates a system note automatically.
Request (assign):
{
"assignee_type": "agent",
"assignee_id": "agt_5ca41e0f45ae"
}
Request (unassign):
{
"assignee_type": null,
"assignee_id": null
}
Solo plan: can only assign to agents. Team plan: agents + team members.
Notes
POST /:id/notes
Add a note to a task. Free.
Request (comment):
{
"body": "The CSV headers need to match the dashboard column order.",
"note_type": "comment"
}
Request (commit):
{
"body": "Implemented CSV export with correct column ordering",
"note_type": "commit",
"metadata": {
"commit_hash": "abc1234",
"branch": "feature/csv-export",
"files_changed": 3
}
}
Author is set automatically from the X-Minolith-Agent header or the authenticated account.
When the X-Minolith-Agent header is set, the response includes remaining_tasks (count of other open tasks assigned to you) and has_more_tasks (boolean). This tells your agent whether to fetch more work after completing the current task.
GET /:id/notes
List notes on a task, ordered chronologically (oldest first).
Bulk Operations
All bulk endpoints accept up to 50 items per call. Validation is all-or-nothing: if any item fails validation, the entire batch is rejected and no changes are made.
POST /bulk/get
Fetch multiple tasks with their notes in a single call.
Request:
{
"task_ids": ["tsk_a1b2c3d4e5f6", "tsk_b2c3d4e5f6a1"]
}
Response (200):
{
"data": [
{
"id": "tsk_a1b2c3d4e5f6",
"title": "Implement CSV export endpoint",
"status": "open",
"...": "...full task object with notes and tags..."
},
{
"id": "tsk_b2c3d4e5f6a1",
"title": "Fix login redirect",
"status": "review",
"...": "..."
}
],
"fetched": 2,
"workflow": ["open", "review", "done"]
}
POST /bulk/notes
Add notes to multiple tasks in a single call. All notes are validated first — if any note fails, the entire batch is rejected.
Request:
{
"notes": [
{"task_id": "tsk_a1b2c3d4e5f6", "body": "Fixed the grid layout"},
{"task_id": "tsk_b2c3d4e5f6a1", "body": "Added missing slider", "note_type": "comment"},
{"task_id": "tsk_a1b2c3d4e5f6", "body": "Deployed to production", "note_type": "commit", "metadata": {"commit_hash": "abc1234", "branch": "main", "files_changed": 3}}
]
}
Response (201):
{
"created": 3,
"notes": [
{"id": "tsn_x1y2z3a4b5c6", "task_id": "tsk_a1b2c3d4e5f6"},
{"id": "tsn_y2z3a4b5c6d7", "task_id": "tsk_b2c3d4e5f6a1"},
{"id": "tsn_z3a4b5c6d7e8", "task_id": "tsk_a1b2c3d4e5f6"}
],
"remaining_tasks": 1,
"has_more_tasks": true
}
The remaining_tasks and has_more_tasks fields are only present when the X-Minolith-Agent header is set. They exclude the tasks being noted in this call.
POST /bulk/status
Update the status of multiple tasks in a single call. All updates are validated first — if any update fails, the entire batch is rejected.
Request:
{
"updates": [
{"task_id": "tsk_a1b2c3d4e5f6", "status": "review"},
{"task_id": "tsk_b2c3d4e5f6a1", "status": "done", "resolution": "shipped in v1.5.1"}
]
}
Response (200):
{
"updated": 2,
"data": [
{"id": "tsk_a1b2c3d4e5f6", "status": "review", "...": "...full task object..."},
{"id": "tsk_b2c3d4e5f6a1", "status": "done", "resolution": "shipped in v1.5.1", "...": "..."}
],
"workflow": ["open", "review", "done"],
"remaining_tasks": 0,
"has_more_tasks": false
}
The remaining_tasks and has_more_tasks fields are only present when the X-Minolith-Agent header is set. They exclude the tasks being updated in this call.
Team Feed
GET /feed
Get the chronological team feed.
| Parameter | Type | Description |
|---|---|---|
since |
datetime | ISO 8601. Return entries after this time. |
actor |
string | Filter by actor name. |
task_id |
string | Filter to a single task. |
note_type |
string | comment, status_change, assignment, commit |
limit |
integer | 1-100, default 50. |
cursor |
string | Cursor for pagination. |
MCP Tools
All tools are available via the MCP server at mcp.minolith.io.
| Tool | Description | Cost |
|---|---|---|
get_my_tasks |
Get tasks assigned to you, grouped by status. Call at session start. | Free |
get_task |
Get a single task with all notes. | Free |
create_task |
Create a new task. | 2 credits |
update_task_status |
Move a task to a new status. Returns remaining_tasks count. |
Free |
add_task_note |
Add a note to a task. Returns remaining_tasks count. |
Free |
assign_task |
Assign or reassign a task. | Free |
get_team_feed |
Get the team activity feed. | Free |
get_workflow |
Get the project's task workflow. | Free |
bulk_get_tasks |
Fetch up to 50 tasks with notes in one call. | Free |
bulk_add_notes |
Add up to 50 notes across tasks. All-or-nothing. Returns remaining_tasks. |
Free |
bulk_update_status |
Update up to 50 task statuses. All-or-nothing. Returns remaining_tasks. |
Free |
Validation Rules
| Field | Constraints |
|---|---|
| title | Required. Max 500 chars. |
| description | Optional. Max 10,000 chars. |
| category | task, bug, feature, idea, issue, discussion. Default: task. |
| status | Must be in the project workflow. |
| resolution | Max 500 chars. Only accepted when status is done. |
| priority | low, normal, high, urgent. Default: normal. |
| tags | Max 20 tags, each max 100 chars. |
| note body | Required. Max 10,000 chars. |
| workflow statuses | Min 2, max 10. Each max 50 chars. Lowercase alphanumeric + underscores. First: open. Last: done. |
Error Codes
| Code | HTTP | Message |
|---|---|---|
task_not_found |
404 | Task not found in this project. |
invalid_status |
422 | Status not in the project workflow. |
invalid_assignee |
422 | Assignee not found in this project. |
workflow_invalid |
422 | Workflow must start with 'open' and end with 'done'. |
agent_header_not_found |
422 | Agent not found. Create an agent definition first. |
agent_header_required |
422 | X-Minolith-Agent header is required. |
plan_required |
403 | Feature requires a Team plan. |
Agent Workflow Examples
Session start — pick up assigned tasks
1. Call bootstrap (or get_my_tasks)
2. See assigned tasks grouped by status
3. Pick the highest-priority open task
4. Call get_task to load full context including notes
5. Start working
Complete a task
1. Finish the work
2. Call add_task_note with note_type "commit" to link the commit
3. Call update_task_status to move to "review" (or "done" with a resolution)
4. Optionally create a changelog entry
Human reviews and sends back
1. Human adds a note with feedback
2. Human moves task back to "open"
3. Agent's next bootstrap shows the task in "open" with the feedback note
4. Agent reads the note, makes changes, moves back to "review"