Groom a project
Shape a project's task tree — create tasks, move them through status, label and assign — by asking your connected agent. Projects and tasks live on the custom-records substrate.
A project holds a tree of tasks. You groom it from your connected agent (Claude Code + the af-api MCP) — speak in plain language; the agent drives the customRecords_* tools against the org's built-in project / task / label schemas, scoped to your org.
Before you start
- A connected agent with the af-api MCP added.
- You're a member of the org (every action here needs
record:write— no admin role required).
The built-in schemas
Every org ships with four record schemas that model project work — inspect them with customRecords_schemas_list:
| Schema | Carries | Relations |
|---|---|---|
project | name, slug, description | — |
task | title, body, status, closed_at, assignee_member_id | project (its project), parent (its parent task), labels (M:M), participants (members) |
label | name, color, description | — |
task_event | append-only activity log rows | task |
Create the project
Create a project "Checkout revamp" (slug
checkout-revamp).
Calls customRecords_records_create with schema: "project" and a payload of name, slug, description.
Build the task tree
Add tasks top-down. An epic has no parent; everything else points at its parent via the parent reference field.
In Checkout revamp, add an epic "Guest checkout", then a task "Address form" under it, then a sub-task "Validate postal code" under that.
Each task has a title and a markdown body; its project field references the project record, and parent references the parent task. Calls customRecords_records_create with schema: "task".
Move work through status
status is a free-form label — new tasks default to backlog. There's no fixed enum; pick a vocabulary and stay consistent. A common one:
backlog → in_progress → in_review → doneMove "Address form" to in_progress.
Closing is separate from status: a task has a closed_at timestamp, so you can filter open vs. closed regardless of the status label. Calls customRecords_records_upsert on the task record. Every status / assignee / label change also lands as an append-only task_event record automatically.
Label and assign
- Labels are org-wide (name + color)
labelrecords. Create once, link to many tasks. - Assignees are members — a teammate or an agent — carried on the task's
assignee_member_idfield.
Create a red label "blocker". Tag "Validate postal code" with it and assign it to @data-agent.
Calls customRecords_records_create (schema: "label"), then customRecords_records_link on the task's labels relation, and customRecords_records_upsert for the assignee. Watchers go through the participants relation (customRecords_records_link); @mentions in a task body add them automatically.
Find anything
Query records with combinable field filters.
Filter on task | Example |
|---|---|
status | everything in_review |
assignee_member_id | assigned to one member |
closed_at | hide finished work (empty = open) |
project | tasks of one project |
parent | children of one epic |
Show open tasks in Checkout revamp labelled blocker.
Calls customRecords_records_query (paginated); label membership resolves via customRecords_records_listLinks on the labels relation.
Tool cheat sheet
| You want to… | Tool |
|---|---|
| Create a project / task / label | customRecords_records_create |
| Update status, body, assignee | customRecords_records_upsert |
| Re-parent | customRecords_records_upsert (the parent field) |
| Attach / detach a label | customRecords_records_link · customRecords_records_unlink |
| Add watchers | customRecords_records_link (the participants relation) |
| Read a task's activity log | customRecords_records_query (schema: "task_event") |
| List / search | customRecords_records_query |
| Walk relations | customRecords_records_traverse |
The schemas are ordinary custom-record schemas — the same record:write
surface your own schemas use — so everything here composes with the rest of
the records platform (context graph, search, derived fields).