Skip to content
Filipe Soares edited this page Oct 9, 2026 · 5 revisions

Tasks

A task is a goal plus a checklist. It is how work reaches the next session: open tasks come first in every brief, and a task closes itself once its items are settled.

A task in the dashboard

Open one

made = task(
    title="Move billing webhooks to the idempotent handler",
    goal="Every billing webhook is deduplicated by event id.",
    items="Key charge.succeeded by event id\n"
          "Cover refunds and disputes\n"
          "Remove the charge-id lookup",
    domain="acme/checkout/billing",
)
uid = made["uid"]
charge, refunds, lookup = made["items"]     # each item's id

One item per line. Each item is a short label, verb first, at most 80 characters: lists, progress and every DEPENDS ON that names it show it whole, so its detail goes in the item's brief.

Every item has an id, which every tool takes. The number a list shows is only its place: it follows the order, and deleting an item moves no other id.

Free text — the goal, a brief's fields, a note on the whole task, a comment — cites an item as [[#id]], which reads back as the item's current number and label, and as a deleted item once it is gone. A label (the task's title, an item's text, a note's title) never carries one, and i3 in free text is refused. In the dashboard, typing # in a task's text opens a menu of its items and writes the token for you.

Work it

task_item(uid, charge, state="done", comment="Handler keys off the event id.",
          related=note_uid)                 # link the memory that explains it
task_item(uid, refunds, state="doing")
replay, = task_add(uid, "Document the replay queue")["items"]  # more items; reopens a closed task
task_comment(uid, f"Disputes need their own queue, like [[#{refunds}]]?")  # on the task
task_comment(uid, "Waiting on the provider's docs", item=refunds)        # on one item

Briefs that stay out of search

A task note belongs to the task, not to the memory set: it never comes back in a search, and only task_read returns it. It is where an item's brief goes — the context, the files, the steps, when it counts as done — or a rule several items share.

A note on items is a brief, given field by field: goal, context, steps, pitfalls, done_when and depends_on are required, extra_info is optional. depends_on is none, or the ids of the items this one waits for, each with an optional reason; it reads back as [[#id]] (reason).

task_note(uid, title="Replay queue", items=str(replay),
          goal="Replays are idempotent and survive a restart.",
          context="The queue lives in the webhook worker.",
          steps="Persist each event id before acting on it.",
          pitfalls="A restart mid-replay must not double-book.",
          done_when="The restart test passes.",
          depends_on=f"{charge} (the event-id handler)")
task_note(uid, title="Shared rule", body="Never call the provider twice.")  # whole task

A long task is read in pages. get_memory(uid) returns the goal and counts, and task_read returns one collection at a time:

task_read(uid, "items")                 # each item with its id, number, state and counts
task_read(uid, "notes", item=replay)    # the notes on one item
task_read(uid, "comments")              # the task's own comments

Follow next_offset until it is absent. A page of notes or comments that mentions items carries refs, what each [[#id]] on it names.

Correct it in place

A task that drifted is fixed where it stands, not filed again:

edit_memory(uid, goal="Every billing and refund webhook is deduplicated by event id.")
task_item(uid, lookup, text="Drop the charge-id lookup")   # rename; id, state and brief stay
task_item(uid, refunds, delete=True)                       # no other item moves

A delete stands alone in its call. A DEPENDS ON that named the deleted item keeps its text, marked deleted. Delete a mistake or a duplicate; mark work decided against dropped, which keeps it.

How it moves

Each item is todo, doing, done or dropped. The task follows its items:

stateDiagram-v2
    direction LR
    [*] --> open
    open --> completed: all items settled, one or more done
    open --> cancelled: every item dropped
    completed --> open: an item reopened or added
    cancelled --> open: an item reopened or added
Loading

A closed task is archived like any other memory. To list finished ones:

list_by_domain("acme/checkout", type="task", status="archived")

Finding and reminding

  • must_read(domain, type="task") lists the open tasks of a scope, with progress (done/total) and the items in progress.
  • The guard hook notes every domain a session names in its memai calls. At the end of a turn the stop hook asks the agent to update the open tasks of those domains — at most once every 30 minutes, and only when there are some. A session that named no domain is not asked.
  • The reminder can be turned off, and its interval changed, under Dashboard → Maintenance → Reminders.

In the dashboard a task opens as a checklist: change an item's state, add, rename or delete items, comment, link memories to a single item, and read or edit its notes.

Clone this wiki locally