Skip to main content
BitsWeave
Guides

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:

SchemaCarriesRelations
projectname, slug, description
tasktitle, body, status, closed_at, assignee_member_idproject (its project), parent (its parent task), labels (M:M), participants (members)
labelname, color, description
task_eventappend-only activity log rowstask

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 → done

Move "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) label records. Create once, link to many tasks.
  • Assignees are members — a teammate or an agent — carried on the task's assignee_member_id field.

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 taskExample
statuseverything in_review
assignee_member_idassigned to one member
closed_athide finished work (empty = open)
projecttasks of one project
parentchildren 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 / labelcustomRecords_records_create
Update status, body, assigneecustomRecords_records_upsert
Re-parentcustomRecords_records_upsert (the parent field)
Attach / detach a labelcustomRecords_records_link · customRecords_records_unlink
Add watcherscustomRecords_records_link (the participants relation)
Read a task's activity logcustomRecords_records_query (schema: "task_event")
List / searchcustomRecords_records_query
Walk relationscustomRecords_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).

On this page