---
title: "Tasks: offered, never assigned"
url: https://services.dev/docs/people/pool/tasks
captured: [ask-the-client.txt, task-claim-tabs.txt, task-hold.txt, task-wire.txt]
---
# Tasks: offered, never assigned

URL: https://services.dev/docs/people/pool/tasks

> A role step posts a Task at a fee fixed when it posts. Members claim it, it holds for one of them on a clock, and it counts as done only when the gate accepts their act.

A Task answers one question: what does a person claim, and what becomes of it?

When a job reaches a step a role does, the step posts a Task to the role's Pool and the job waits `on: 'claim'`. No one is assigned. The Task is offered by its [dispatch](https://services.dev/docs/people/pool/dispatch.md), and the member who wants it claims it.

## The fee is fixed at post

The fee a Task posts at is the same whatever the member decides: attest, send back or decline, each [paid](https://services.dev/docs/people/pool/pay.md), or, in a [work register](https://services.dev/docs/people/pool/register.md), the completed Task. It is never lowered. Only the [fill ladder](https://services.dev/docs/people/pool/fill.md) moves it, and only up. A pass is free, and so is giving a held Task back.

## Its states

| Status | What it means |
|---|---|
| `open` | Offered to eligible members by its dispatch, as a teaser. |
| `claimed` | One member holds it until `held_until` and is clearing it. Every other feed has lost it. |
| `cleared` | The member attested the sheet's statements, and the packet is open to them alone. |
| `cleared`, waiting on the client | The member asked the client a question. The hold and the step's clock pause until the reply comes through the thread. |
| `on_site` | In a [work register](https://services.dev/docs/people/pool/register.md#where-and-when-a-check-in-counts), the member checked in at the site, inside the window. |
| `done` | The gate accepted the member's act: attested, sent back or declined, or in a work register `completed`, `party_absent` or `party_silent`. |
| `done`, withdrawn | The job ended before the act. A member who cleared the Task keeps the [kill share](https://services.dev/docs/people/pool/pay.md#other-lines-a-member-earns); one who only claimed it keeps nothing, and nothing is scored. |
| `open`, again | The hold ran out, or the member gave it back or stepped aside for a conflict. `reopened` counts up by one, and the dispatch runs on. |

A status is never a column. It is read off the Task's own appended acts, each named for the [worklists.dev](https://worklists.dev) verb it writes, so any client that speaks those verbs reads a Task the same way: [Task verbs](https://services.dev/docs/reference/task-verbs.md) maps every act. Each state is the same object on the wire, a [Task](https://services.dev/docs/reference/objects.md#task), here as the claim answered it:

```txt
→ POST /reviews/tsk_7Hq2/claim {}   # as mbr_eligible
```

```json title="200 · tsk_7Hq2 · claimed · magic values: applicant.email = signs@example.test, member = mbr_eligible"
{
  "id": "tsk_7Hq2",
  "object": "task",
  "livemode": false,
  "pool": "attorneys",
  "role": "practitioner",
  "status": "claimed",
  "fields": {
    "act": "sign",
    "region": "*",
    "fee_usd": 150,
    "signals": []
  },
  "est": {
    "minutes": 60,
    "from": "step"
  },
  "hourly_usd": 150,
  "due": "2026-10-30T14:02:11.000Z",
  "held_until": "2026-10-26T14:02:11.000Z",
  "simulated": true
}
```

A member's act counts only once the gate accepts it. A refused act keeps the Task claimed, showing the refusal, so the member can fix and resend it. The [gate](https://services.dev/docs/service/gate.md) holds AI and people to the same checks.

## Claim, on four surfaces

A claim is a person's own act: in the member CLI or the delivery portal, in their own session. MCP and the SDK carry no member act at all:

**CLI**

```bash title="CLI"
SERVICES_DEV_SESSION=ms_psNemolonFiaQz8kWxgxgQ npx services.dev reviews claim tsk_7Hq2
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
tsk_7Hq2 · claimed · attorney · advise · US-CA · $50.00 · 45 min · $66.67 an hour · due 2026-10-27 14:02
```

**API**

```txt title="API"
→ POST /reviews/tsk_7Hq2/claim   # as mbr_eligible, in their own session
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← 200 tsk_7Hq2 · claimed · attorney · advise · US-CA · $50.00 · 45 min · $66.67 an hour · due 2026-10-27 14:02
```

**MCP**

```txt title="MCP"
→ tools/list
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← 13 tools · none claims, clears or attests a review

→ tools/call claim_review {"id":"tsk_7Hq2"}
← {"code":-32602,"message":"No tool claim_review. tools/list names them."}
```

**SDK**

```ts title="SDK"
await legal.reviews?.claim?.("tsk_7Hq2")
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← undefined · the client has no member act: task.claim's SDK column is never, and its caller a member session
```

## Its clocks

A claim holds for the longer of a day and three times the step's estimate, and never past the Task's due date. At three-quarters of the hold the member is warned, and they may extend it once, by as long again and still never past the due date:

```txt
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-CA","max_usd":99,"key":"hold-extend"}
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← job_7Hq2 · waiting · on claim · $99.00 held · advise · tsk_7Hq2

→ POST /reviews/tsk_7Hq2/claim   # as mbr_eligible
← 200 tsk_7Hq2 · claimed · attorney · advise · US-CA · $50.00 · 45 min · $66.67 an hour · due 2026-10-27 14:02
  held_until 2026-10-26T14:02:11.000Z
→ POST /test_clocks/default/advance {"to":"18h"}
← 2026-10-26T08:02:11.000Z
→ POST /reviews/tsk_7Hq2/extend   # as mbr_eligible
← 200 tsk_7Hq2 · claimed · attorney · advise · US-CA · $50.00 · 45 min · $66.67 an hour · due 2026-10-27 14:02
  held_until 2026-10-27T14:02:11.000Z
→ POST /reviews/tsk_7Hq2/extend   # as mbr_eligible
← 422 input_invalid: tsk_7Hq2's hold was extended once already: it holds until 2026-10-27T14:02:11.000Z.

# the record's hold lines · tsk_7Hq2 claimed · reopened 0
  2026-10-25 14:02 · task.claimed
  2026-10-26 08:02 · task.hold_expiring · held until 2026-10-26 14:02
  2026-10-26 08:02 · task.extended · held until 2026-10-27 14:02
```

Work that lasts as long as the member works it, such as a sales cycle, holds by touches instead: `hold: { claim: '48h', then: 'touch' }` holds the claim 48 hours to a first touch with the party, and each touch on the thread renews it for as long again.

A hold that runs out opens the Task again, and the dispatch runs on:

```txt
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-CA","max_usd":99,"key":"hold-expire"}
```

```txt title="magic values: client.email = signs@example.test, member = mbr_eligible"
← job_7Hq2 · waiting · on claim · $99.00 held · advise · tsk_7Hq2

→ POST /reviews/tsk_7Hq2/claim   # as mbr_eligible
← 200 tsk_7Hq2 · claimed · attorney · advise · US-CA · $50.00 · 45 min · $66.67 an hour · due 2026-10-27 14:02
  held_until 2026-10-26T14:02:11.000Z
→ POST /test_clocks/default/advance {"to":"18h"}
← 2026-10-26T08:02:11.000Z
→ POST /test_clocks/default/advance {"to":"6h"}
← 2026-10-26T14:02:11.000Z

# the record's hold lines · tsk_7Hq2 open · reopened 1
  2026-10-25 14:02 · task.claimed
  2026-10-26 08:02 · task.hold_expiring · held until 2026-10-26 14:02
  2026-10-26 14:02 · job.paused · on claim · reopened 1 · expired
```

A `cascade` gives each member a window to themselves, and a sheet is one member's at a time. If the job ends after a member cleared their Task, they keep the kill share of its fee. In a work register, a claimed Task the client cancels inside `notice` accrues the kill share too, because the member held the window:

| Key | Written | Left out | Does |
|---|---|---|---|
| `hold` | `Within \| { claim: Within; then: 'touch' }` | max(24h, 3 × est) | How long a claim holds before it reopens: one span, or the default, three times the step's estimate and at least a day, never past its due. A member may extend it once. With `then: 'touch'`, each touch renews it. |
| `window` | `ShortSpan` | `'1h'` | How long one member has a `cascade`'s offer, or a first refusal, to themselves. |
| `sheet` | `ShortSpan` | `'10min'` | How long one member has a sheet to themselves. |
| `kill` | `Pct` | `'50%'` | What a member accrues when a Task they cleared is withdrawn because the job ended, or, in a work register, a claimed Task the client cancels inside `notice`: a share of its fee. [Pay](https://services.dev/docs/people/pool/pay.md) has every line a member earns. |

## Talking to the party inside a Task

A member who has cleared a Task reaches the job's party only through the job's thread: a question, a note, or a flag the owner sees. A question pauses the step's clock and the member's hold until the party answers, and contact details never cross. [Talk](https://services.dev/docs/service/talk.md) explains the thread:

```txt
→ POST /reviews/tsk_7Hq2/messages {"kind":"question","text":"Is the lease you sent the signed copy? Write me at grace@firm.example."}   # as mbr_7Hq2
```

```txt title="magic values: none"
← 200 msg_7Hq2 · the attorney · question · open: Is the lease you sent the signed copy? Write me at [email withheld: reply in this thread].
  14:02 · job.paused · on the client's reply · advise · tsk_7Hq2
```

## What it writes

| Event | Audience | Says |
|---|---|---|
| `task.posted` | member, owner | A role step posted a Task at its fee, fixed now and never lowered, to its dispatch: or to the one member a client's direct named. Its reach says who it can be offered to. |
| `task.offered` | member, owner | A Task was offered to a member, by its dispatch (`feed` or `cascade`), first refusal or the owner: its teaser, with its minutes, rate and due date, and never a party name. |
| `task.claimed` | member, owner | A member claimed a Task: it is held for them, gone from every other feed, until they clear it or the hold runs out. |
| `task.hold_expiring` | member, owner | Three-quarters of a member's hold on a Task has run: it reopens at held_until unless they finish, or extend it once. |
| `task.extended` | member, owner | The member extended their hold, once: by as long again as it first held, never past the due date. |
| `pay.accrued` | member, owner | A member's pay for a paid act accrued, at the Task's fee as it stood, with the raise the brand funds; or a kill share. [Pay](https://services.dev/docs/people/pool/pay.md#three-moments) says when it is theirs. |

---

- Up: [Pool(): your marketplace](https://services.dev/docs/people/pool.md)
- Previous: [Dispatch](https://services.dev/docs/people/pool/dispatch.md)
- Next: [Pay](https://services.dev/docs/people/pool/pay.md)
