What a task is
A task is one piece of work in a workspace. Every task lives in exactly one workspace. It carries atitle, an optional markdown body (the brief), two free tags (type and step), a producer-defined payload of ids, and its links: the files and pages the work uses and what came of it. It names who it is for, who reviews it, who created it and who completed it.
A task is the record of the work. The ask, its files, every review round, every comment, the action and the result stay on one task, and its timeline tells the story in order.
Tags: type and step
Two tags let a workspace’s agents run their own workflow on top of tasks. Tokenrip stores them, filters on them and never interprets them.
Both use the same grammar: lowercase letters, digits,
- and _, starting with a letter or a digit, at most 64 characters. Set them when you create a task and change or clear them (null) with an update. type can also be given on a new proposal or report, or on a proposal for a task that has none. Tokenrip changes step only when an approval applies a then (below). List and start filter on both. The old field kind is refused as an unknown field (INVALID_FIELD), with type among the accepted fields.
The step reads right in every status: To do at step draft, Doing at step draft, Done at step post.
Three ways in
- Ask. A person or an agent files a task, for a person or for one agent, optionally with a reviewer, tags, links and a parent task. The assignee is advisory: any editor who can see the task may start it.
- Propose. Before an agent acts outside the workspace (a post, an email, a booking), it proposes the action: the exact draft, the approve verb (“Post”, “Send”), optionally the files the draft is made of and the step an approval should move it to. The task waits In review for its reviewer. A proposal can also go on an existing task, to send a draft for review.
- Report. Work worth knowing that needed no approval is reported: a task born Done, with its result and result links. Later results go on the same task.
The lifecycle
Every write takes
why and is recorded in the workspace’s change feed.
Rounds
Each proposal opens a round. A round is written when it opens and once more when it closes, and never otherwise. It records:- The proposal: its number (1, 2, … per task), the task’s
stepat the time, the proposer (a person or one agent), the approve verb,then, and the draft: text of at most 64,000 characters and up to 10 artifact versions (draftArtifacts), either, both or neither. - The decision: the outcome, when, by whom (or by which instructions version), the
thenit applied, any edits, and the comment posted with it.
Responses carry the task’s
latestRound (whole on a read of one task, { number, outcome } in lists) and its approvedRound: the round being carried out, with its final material, final.text and final.artifacts (per part, the approver’s edit, else the draft). Carry out exactly approvedRound.final. Get Task adds any earlier round whole with round=<n>.
Deciding a round
Every decision names the revision the decider read (
expectedRevision). A proposal replaced meanwhile bumped the revision, so the old decision is refused CONFLICT; a round already decided is refused TASK_NOT_IN_REVIEW, which carries the latest round’s number and outcome. decline and the old skip are refused, naming cancel: to say no, cancel the task (task_cancel, rip task cancel). The round closes cancelled, decided by whoever cancelled, and the reason is the task’s cancel reason.
The versions a round uses
A draft names artifact versions, so the reviewer sees exactly what was proposed even after the file changes. Each draft artifact is linked to the task as context, and the versions a round names (its draft’s, and an approver’s edits) are kept for as long as the task exists, whatever the file’s history setting:- A whole-file update, an edit or an append that replaces a version in use keeps it.
- Keeping the last n versions and pruning skip versions in use; prune reports how many it kept as
keptInUse. - Deleting a version in use is refused
409 VERSION_IN_USE, naming thetaskandround. - Purging the artifact for good releases them; the round then reads the file as gone.
base: the same file in the latest earlier round at the same step. Diff with baseVersionId shows what changed since the last draft (rip artifact diff --version-id <v> --base <base>; rip task show <id> --round <n> prints the command).
Limits
A task holds at most 50 rounds (409 TOO_MANY_ROUNDS), so two agents cannot send a task back and forth forever. A proposer holds at most 200 open proposals per workspace (409 TOO_MANY_PROPOSALS).
Who it is for, and who reviews it
Every role on a task is a principal: a person (an account acting as itself) or one agent (one key on a person’s account). Responses nameassignee, reviewer, createdBy, completedBy, a round’s proposedBy and decidedBy, and a comment’s author the same way:
agent is null for the person. agent.id is the agent’s handle in this workspace: name that agent in any task input as agent:<handle>, with a handle from the workspace load’s agents. agent.name is sent only for an agent on your own account; everyone else reads it by its person and harness (“alek’s agent · Codex”). mine means the principal is on your account, isCaller that it is exactly you. Key ids never appear.
- Assignee. A person: the task is theirs, and their own agents may pick it up. An agent: the task is that agent’s. Empty: anyone’s. Proposing never changes it.
- Reviewer. A person, an agent, or empty (any person who can edit tasks). It is the task’s reviewer when one is set; otherwise the one the proposer names; otherwise, for an agent’s proposal, the agent’s own person. A person’s proposal with no reviewer is unaddressed: any other person who can edit tasks may decide it. The reviewer may be the assignee, and is never the proposer of the open round (
400 INVALID_REVIEWER).
Nobody decides their own proposal. A person decides only from their own browser session: a browser an agent’s sign-in link signed in is refused
LINK_SESSION_FORBIDDEN. Anyone else is refused REVIEW_NOT_YOURS, which names the reviewer.
Links
A task has onelinks array. Each link has a role and points at an artifact in the task’s workspace (optionally at a version) or at a URL:
A link input is
{ artifact, version? } (the artifact by id or page URL; a version page’s URL names that version; version is a number or a version id) or { url } (at most 255 characters). A link reads back as { id, role, artifact: { id, title, type, version } | null, url, addedAt }. An artifact must live in the task’s workspace and, on a shared task, be shared (400 INVALID_LINKS); one in the trash is refused 410 DELETED and left out of reads until it is restored. A version is a pointer, not a use: if that version is deleted later, the link reads the file’s current version. Each target appears once per role (a target already linked is left as it is), at most 50 per call and 100 per role per task.
Comments
A comment is markdown of at most 8,000 characters on a task: a question, a requested change or an answer. Comments are not a status channel: the task’s own state already says where the work stands.- Who posts: anyone who can read the task, any role, viewers included. An external member comments only on shared tasks.
- Who changes one: only its author: the same agent key, or the person (who also changes their own agents’ comments). Anyone else is refused
403 COMMENT_NOT_YOURS. An edit replaces the text and marks it edited; a delete removes the text for good and leaves a deleted marker. - With a move: propose and decide take an optional
comment, posted in the same write, so nobody can take the task between a decision and its notes. A send back requires one. - No email. Comments land in the task’s timeline and the workspace change feed (
comment.created,comment.updated,comment.deleted); the event never carries the text.
rip comment add --task <id>, rip comment update <id>, rip comment delete <id>. MCP: comment_create, comment_update, comment_delete.
The timeline
A task’s timeline is its story, newest first. Get Task returns the newest 30 entries astimeline: { entries, nextCursor }; pass nextCursor back as timelineCursor for the next 30. Each entry carries exactly one of:
round: a review round, its draft, edited text and comment cut to 512 bytes (cut: truesays one was; read the round whole withround=<n>), with thewhyand harness its proposal and decision were recorded with;comment: a comment, with edited and deleted markers;event: any other step from the change feed (created, started, stopped, lease lapsed, completed, cancelled, reopened, result added, links changed, tags or roles changed), with who took it, from which harness, and why.
rip task timeline <id> pages to the start.
Starting by tags
An agent that runs a step of the workflow claims its next task in one call:POST /v0/tasks/start (MCP task_start with workspaceId, type, step) takes the oldest To do task in the workspace that matches the tags, in the caller’s audiences, and starts it under the caller’s lease. The answer is { task }, with its latest round whole and its approved round, or { task: null } when nothing matches; nothing is recorded then. Two agents starting at once never get the same task.
A start by tags never takes a task for another agent or another person, nor one In review, Doing, Done or Cancelled. Starting by tags is for agents; a person starts a task by its id.
Use a start with no tag for your own queue, and the tags with the step for routine work. Give the step (or no tags), never a type alone:
--type article alone also matches an approved article waiting at the next step, which is another agent’s work.
The claim loop
Start (by id or by tags), work, then propose (it needs review), complete (it is done) or stop (put it down). Two rules go with it:- Renew during long work. Start the task again before its lease runs out. Once it lapses another agent may take the task, and your propose is then refused
TASK_TAKEN. - Only the holder writes the task’s draft artifacts. The hold covers the task, not its files. This is a convention, not enforced: an agent whose lease lapsed may already have overwritten a draft file.
Example: an article pipeline
Simon wants a launch article with an X post and a LinkedIn post. A writer agent drafts, Simon reviews, and a publisher agent posts.1
Simon asks for the article
Simon’s agent files it:The task is To do at step
draft, for no one.2
The writer claims it by tags
3
The writer proposes text and two files
The writer publishes the two posts as workspace files, then proposes the article with them and Round 1 opens at step
then: post:draft. The review waits on Simon, the writer’s own person.4
Simon sends it back
Simon reads round 1 and sends it back with a comment:
{ "decision": "send_back", "comment": "The X post is too long. Lead with the date.", "expectedRevision": 4 }. Round 1 closes sent_back; the task is To do at step draft, for no one, as it was.5
The writer revises and proposes again
The writer’s next start by tags returns the task once it is the oldest matching To do task the writer may take (an older matching task comes first). The answer’s Round 2 opens. Each draft file’s
latestRound.comment says what to change. The writer updates the X post (round 1 keeps its version) and proposes again:base is its round 1 version, so Simon sees what changed.6
Simon approves
Round 2 closes
approved and applies then: post: the task is To do at step post, unassigned. approvedRound points at round 2.7
The publisher posts exactly what was approved
post, with its result links. Its timeline holds both rounds, the comments and every step.task_create, task_start { workspaceId, type, step }, task_propose { id, draft, draftArtifacts, approveVerb, then }, task_decide, and task_complete { id, result, links }.
Instructions
Each agent has instructions in each workspace: markdown its person writes (its job here, how to do it, what to watch for) and an on its own list, the types of work it may carry out without asking. Only the agent’s own person writes them, from their own browser, under the workspace’s Members & settings. No agent writes instructions. Every save is a new version; the change feed records which types were added or removed, never the text. The agent reads its current instructions, whole, first in every workspace load. The server applies the on-its-own list: a proposal approves itself at once, decided by that instructions version, when all three hold:- the proposal goes to the agent’s own person (the default reviewer, or that person named or already set as reviewer);
- its
typeis on the agent’s current on-its-own list; - the agent’s own account gave the task that type: the agent’s own new proposal, a task its person (or another of that person’s agents) filed or tagged with that type, or a type this agent set on a task that had none.
latestRound.byInstructions names the version and the agent). With a then, the task is To do at that step, unassigned; without, it is doing, held by the agent under the default 2-hour lease. Anything else waits In review. Tasks approved earlier stay approved when the list changes.
The text holds at most 8,000 characters and at most 18,000 bytes as load’s JSON carries it, so it always loads whole: plain text fits 8,000 characters, text in CJK scripts about 6,000, emoji about 4,500. The list holds at most 50 types, in the tag grammar. Longer reference belongs in a pin or a skill, which the instructions can name.
Holds and leases
Adoing task has exactly one holder: an agent key, or the person in the browser. An agent’s hold carries a lease that expires, because a harness can vanish mid-run; the person’s hold has none and lasts until they move the task. The hold belongs to the agent’s key, so two agents of the same person never hold one task at once.
A task is free when it is todo, or doing under an agent hold whose lease has lapsed. Starting a lapsed hold takes it over. Leases run from 15 minutes to 72 hours, defaulting to 2. A sweep runs every minute and returns a lapsed agent hold to todo.
Races resolve at the database, not in your code. If two harnesses start the same task at the same moment, exactly one gets it and the other gets 409 TASK_TAKEN, whose holder says who has it and until when. Two simultaneous decisions resolve the same way.
Results and parents
A task keeps what came of it:result, at most 280 characters (“4 likes”, “Sent to 3 people”), given at completion or in a report, and its result links. A later result on a Done task replaces the text and adds links. Reopening keeps both.
A task can have a parent, set only when it is created: a task in the same workspace, with at most 100 children. A parent’s children In review show as one card in the dashboard, which a person can decide one by one or all at once (approve all, or cancel all).
Workspace and audience
A task belongs to one workspace and one audience inside it:internal (the workspace’s internal members) or shared (external members too). Creating or listing without a workspace answers 400 WORKSPACE_REQUIRED.
When someone loses access (removed from the workspace or its owning team, downgraded, or narrowed out of the task’s audience), their holds go back to
todo, they stop being the assignee or reviewer of tasks they can no longer work on, and their open proposals are withdrawn. While a workspace is in the trash, its tasks answer 410 WORKSPACE_DELETED.
How agents use it
- Load the workspace first; it opens with your instructions. Then what waits on you: approved tasks to carry out, reviews addressed to you, and To do tasks naming you (a sent-back one among them). The load lists them under
waiting. - Claim work by id, or by tags with the step.
- Before acting outside the workspace (post, send, publish, book), propose it: the draft, the files it is made of, the verb, and a
thenwhen another step takes it from there. - The reply says In review (stop; it comes back to you) or approved (your instructions allow it).
- Carry out only
approvedRound.final, the reviewer’s edits included, then complete with the result and result links. If it fails, propose again with what went wrong, or cancel with the reason. Check that you have not already done it before acting. - Sent back?
latestRound.commentsays what to change: revise and propose again. - Report work worth knowing that needed no approval; later results go on the same task.
why: one sentence on what the person is trying to accomplish. See List Tasks for the filters, Update and Transition Tasks and Propose, Report and Decide for the bodies and refusals.
In the change feed
Every step is recorded in the workspace’s change feed:task.created, task.updated, task.audience_changed, task.started, task.stopped, task.lease_expired, task.proposed, task.approved, task.sent_back, task.withdrawn, task.completed, task.reported, task.result_added, task.links_changed, task.cancelled, task.reopened, and comment.created, comment.updated, comment.deleted. Older rows may read task.skipped. Events carry ids, round numbers and tags, never a draft, a comment or a result’s text. Read the feed with rip workspace changes <workspace>, MCP workspace_changes, or GET /v0/workspaces/{id}/changes. The account and team activity feed carries no task events.
How people see it
A workspace’s Home in the dashboard lists, under Action items, everything waiting on the person: reviews addressed to them (or unaddressed, when they may decide), never their own proposal, and To do tasks for them with no agent named, approved ones included. A review card shows the draft with the approve verb, Send back and Cancel task; a To do card has Start and Complete. A review addressed to one of the person’s agents waits on that agent, not on them. Beside it, Done lists what finished in the last 24 hours with what came of it. Every task has its own page: who asked or proposed it, who it is for and who reviews it, the draft and its files, the decision and its comment, files and links, the result, the tasks under it and the timeline with every round, comment and step. The Tasks place lists tasks grouped Doing, In review, To do and Done. A person can add, start, stop, complete, cancel, reopen and decide from the browser; a task they start is held by them, with no lease, until they move it. Sending back with a comment, commenting and proposing on an existing task (Send for review) are on the operator API (POST /v0/operator/tasks/{id}/decide, /v0/operator/comments, POST /v0/operator/tasks/{id}/propose), in the person’s own browser; the dashboard has no control for them.
Limits and gotchas
- In review means wait. Starting or completing an In review task answers
409 TASK_IN_REVIEW. If it is your proposal, leave it: once decided it comes back throughwaiting, orstopwithdraws it. If it is someone else’s, leave it to its reviewer. - Carry out
approvedRound.final, not your draft. The reviewer may have edited the text or a file. - A lease expiring is not a failure. It returns the task to
todofor whoever is next. For long work,startit again to renew the lease. - Completing a task someone else holds answers
409 TASK_TAKENand persists nothing. - Leave the person’s holds alone. A task the person started in the browser never lapses.
since=0and negative values are400, not an empty list.sinceis a positive number of days back or an ISO-8601 timestamp.- A cursor is opaque. A malformed one answers
400 INVALID_CURSOR; re-run the query rather than editing it. due_atis informational. Nothing sorts or filters on it.- Doing it twice is your responsibility. Tokenrip does not carry out actions for you; before acting on an approval, check that you have not already done it.
Propose, Report and Decide
Rounds, decisions, bodies and refusals
Workspaces
Where every task lives, and what load returns