The docs explain sessions, claims and dependencies in a guide of their own: picking up an issue with get_work, starting, heartbeating, recording in and ending a session and what active, idle and ended mean, claiming, renewing, releasing and handing off an issue, setting blocked_by and what is refused, overlaps, the coordination events and who may do what. The MCP reference lists the session tool and the issue tool's new actions, the webhooks guide and the site's webhook form list the new events, and the agent guide and llms.txt start work with issue work and issue claim.
8 files+293−160/8 viewed
| 153 | 153 | label: 'Coding agents', | |
| 154 | 154 | items: [ | |
| 155 | 155 | { label: 'Connect a coding agent', slug: 'guides/bring-your-own-agent' }, | |
| 156 | + | { label: 'Sessions, claims and dependencies', slug: 'guides/sessions' }, | |
| 156 | 157 | { label: 'Sessions and why-blame', slug: 'guides/why-blame' }, | |
| 157 | 158 | { label: 'Memory', slug: 'guides/memory' }, | |
| 158 | 159 | ], |
| 15 | 15 | | Push code | git over HTTPS, with an [access token](/guides/authentication/#access-tokens) | | |
| 16 | 16 | | Start the agent when something happens | [Webhooks](/guides/webhooks/), or a [workflow](/guides/actions/) on `issues` or `issue_comment` | | |
| 17 | 17 | | Show people how a change was made | The pull request's [session](/guides/why-blame/#sessions) | | |
| 18 | + | | See who is working on what, and not collide | [Sessions, claims and dependencies](/guides/sessions/) | | |
| 18 | 19 | | Pass what one agent learned to the next | [Memory](/guides/memory/) | | |
| 19 | 20 | | Script anything else | The [REST API](/reference/api/), which has the same operations as the tools | | |
| 20 | 21 | ||
| ⋯ | |||
| 74 | 75 | ||
| 75 | 76 | ## How an agent works on an issue | |
| 76 | 77 | ||
| 77 | − | 1. `issue` with `get`, to read the description, including what done means | |
| 78 | − | if it says, and to see which pull requests already exist for it. | |
| 78 | + | 1. `issue` with `work`, to load everything about it in one call: what | |
| 79 | + | done means, who has claimed it, the pull requests already made for it, | |
| 80 | + | and what it is blocked by. Then `issue` with `claim`, which also says | |
| 81 | + | who else is on it. | |
| 79 | 82 | 2. `memory` with `recall`, to read what the project remembers: how to | |
| 80 | 83 | build, conventions and traps. | |
| 81 | 84 | 3. `pull_request` with `create` and the issue's number. This opens a draft | |
| ⋯ | |||
| 267 | 270 | | --- | --- | | |
| 268 | 271 | | `search` | Code, repositories, issues, pull requests and people across g1t; a tracker's ticket | | |
| 269 | 272 | | `repository` | Repositories, their settings, rulesets, branches, labels, milestones and releases | | |
| 270 | − | | `issue` | Issues, labels and comments | | |
| 273 | + | | `issue` | Issues, labels and comments; an issue's whole context, and claims | | |
| 271 | 274 | | `pull_request` | Pull requests: create, record and read sessions, review, merge, the merge queue | | |
| 275 | + | | `session` | Your harness's session: start, heartbeat, record, end; who else is working | | |
| 272 | 276 | | `memory` | `recall` and `remember` | | |
| 273 | 277 | | `workflow` | Workflow runs and logs, checks, deployments, environments and runners | | |
| 274 | 278 | | `observability` | A project's requests, logs, traces, errors and metrics in production | | |
| 1 | + | --- | |
| 2 | + | title: Sessions, claims and dependencies | |
| 3 | + | description: How agents and people on one repository see who is working on what, with sessions of their own harnesses, advisory claims on issues, what an issue is blocked by, and the one call that loads an issue's whole context. | |
| 4 | + | --- | |
| 5 | + | ||
| 6 | + | When several agents and people work on one repository at once, each needs | |
| 7 | + | to know what the others are doing. g1t keeps that around the issue, which | |
| 8 | + | is the unit of work: its description says what is wanted and what done | |
| 9 | + | means, its pull requests are the proposals, and around it g1t records: | |
| 10 | + | ||
| 11 | + | - **Sessions**: one run of your own harness (a Claude Code session, a | |
| 12 | + | Codex run) on the repository, attached to the issue and pull request it | |
| 13 | + | works on. | |
| 14 | + | - **Claims**: an advisory, expiring "I'm working on #12". Never a lock. | |
| 15 | + | - **Dependencies**: the issues that have to land before this one. | |
| 16 | + | ||
| 17 | + | Nothing here waits on a harness. A harness that crashes, loses its | |
| 18 | + | network or sends the same thing twice does no harm: sessions and claims | |
| 19 | + | that go quiet are read as idle, ended or expired the next time anyone | |
| 20 | + | looks, and starting a session or recording an entry again is a no-op. | |
| 21 | + | What git and g1t record (commits, pull requests, checks, merges) is the | |
| 22 | + | truth; sessions are the account of how it got there. | |
| 23 | + | ||
| 24 | + | ## Picking up an issue | |
| 25 | + | ||
| 26 | + | Before working on an issue, load its whole context in one call: `issue` | |
| 27 | + | with `"action": "work"` over MCP, or | |
| 28 | + | [`GET /repos/{owner}/{name}/issues/{number}/work`](/reference/api/claims-and-work/get-work/): | |
| 29 | + | ||
| 30 | + | ```sh | |
| 31 | + | curl https://api.g1t.sh/repos/acme/web/issues/12/work \ | |
| 32 | + | -H "Authorization: Bearer $G1T_TOKEN" | |
| 33 | + | ``` | |
| 34 | + | ||
| 35 | + | | Field | What it holds | | |
| 36 | + | | --- | --- | | |
| 37 | + | | `issue` | The issue, with its body. | | |
| 38 | + | | `definition_of_done` | The items under its **Definition of done** heading. | | |
| 39 | + | | `required_checks` | The checks every pull request into the default branch must pass. | | |
| 40 | + | | `claims` | Who says they are working on it now. | | |
| 41 | + | | `sessions` | Sessions on it or its pull requests, most recently heard from first. | | |
| 42 | + | | `pulls` | Its pull requests. Those still open or draft carry their `required_checks` as they stand on the head, `mergeable`, the other pull requests they `overlap`, and their place in the merge `queue`. | | |
| 43 | + | | `blocked_by` | Each issue it waits on, with that issue's claims and pull requests. | | |
| 44 | + | | `blocks` | The issues waiting on it. | | |
| 45 | + | | `decisions` | Decisions recorded about it and its pull requests. | | |
| 46 | + | | `last_integration_failure` | The latest `integration.failed` event about it, if any. | | |
| 47 | + | | `recent` | Its latest 20 coordination events, newest first. | | |
| 48 | + | ||
| 49 | + | Then claim it, and start (or attach) your session. | |
| 50 | + | ||
| 51 | + | ## Sessions | |
| 52 | + | ||
| 53 | + | A session is one run of your harness on a repository. Start one when the | |
| 54 | + | harness starts, keep it alive while it works, and end it when it stops. | |
| 55 | + | ||
| 56 | + | 1. **Start** it with `session` `start`, or | |
| 57 | + | [`POST /repos/{owner}/{name}/sessions`](/reference/api/sessions/start-session/), | |
| 58 | + | naming the `harness` (`claude_code`, `codex`, `cursor`, `copilot` or | |
| 59 | + | `other`) and the harness's own id for the session as | |
| 60 | + | `harness_session_id`. Starting again with the same id returns the | |
| 61 | + | session already started, so a hook can call it every time without | |
| 62 | + | checking first. Give `issue`, `pull` and `branch` when you know them. | |
| 63 | + | 2. **Heartbeat** with `session` `update`, or | |
| 64 | + | [`PATCH /repos/{owner}/{name}/sessions/{id}`](/reference/api/sessions/update-session/) | |
| 65 | + | with an empty body. The same call attaches the session to an issue or | |
| 66 | + | pull request, or records the `head_commit` it pushed. | |
| 67 | + | 3. **Record** what happens with `session` `record`, or | |
| 68 | + | [`POST /repos/{owner}/{name}/sessions/{id}/entries`](/reference/api/sessions/record-session-entries/): | |
| 69 | + | prompts, reasoning, tool calls and notes, up to 200 a request. Give each | |
| 70 | + | entry a `key`, and recording it again does nothing. | |
| 71 | + | 4. **End** it with `session` `end`, or | |
| 72 | + | [`POST /repos/{owner}/{name}/sessions/{id}/end`](/reference/api/sessions/end-session/). | |
| 73 | + | ||
| 74 | + | ```sh | |
| 75 | + | curl -X POST https://api.g1t.sh/repos/acme/web/sessions \ | |
| 76 | + | -H "Authorization: Bearer $G1T_TOKEN" \ | |
| 77 | + | -H "Content-Type: application/json" \ | |
| 78 | + | -d '{"harness": "claude_code", "harness_session_id": "5b0c1f9e-3d2a-4e8b-9f61-0c7d2a9e4b13", "issue": 12}' | |
| 79 | + | ``` | |
| 80 | + | ||
| 81 | + | A session's `state` is worked out from when it was last heard from. Every | |
| 82 | + | update and every batch of entries counts as a heartbeat: | |
| 83 | + | ||
| 84 | + | | State | Means | | |
| 85 | + | | --- | --- | | |
| 86 | + | | `active` | Heard from in the last 15 minutes. | | |
| 87 | + | | `idle` | Not heard from for 15 minutes. It may still come back. | | |
| 88 | + | | `ended` | Ended with `end_session`, or not heard from for 2 hours (`end_reason` `timed_out`). A heartbeat brings a timed-out session back; an ended one stays ended. | | |
| 89 | + | ||
| 90 | + | Entries of a session attached to a pull request show in that pull | |
| 91 | + | request's [session](/guides/why-blame/#sessions), beside what was recorded | |
| 92 | + | on it with `record_session`, so reviewers and why-blame see them. Entries | |
| 93 | + | recorded before the session named its pull request move onto it when it | |
| 94 | + | does. A session never records tool output unless you send it as a | |
| 95 | + | `tool_result` entry; a session is as visible as the repository, so keep | |
| 96 | + | secrets out of it. | |
| 97 | + | ||
| 98 | + | List a repository's sessions with `session` `list`, or | |
| 99 | + | [`GET /repos/{owner}/{name}/sessions`](/reference/api/sessions/list-sessions/) | |
| 100 | + | by `state`, `issue` or `pull`, and read one with its entries with | |
| 101 | + | `session` `get`. | |
| 102 | + | ||
| 103 | + | ## Claims | |
| 104 | + | ||
| 105 | + | A claim says you are working on an issue. It is advisory: anyone may claim | |
| 106 | + | an issue someone else has, and is told about them, so two agents can | |
| 107 | + | decide between themselves rather than collide. Nothing is refused because | |
| 108 | + | of a claim. | |
| 109 | + | ||
| 110 | + | - **Claim** an open issue with `issue` `claim`, or | |
| 111 | + | [`POST /repos/{owner}/{name}/issues/{number}/claim`](/reference/api/claims-and-work/claim-issue/). | |
| 112 | + | The answer has your `claim`, the `others` already on the issue, and | |
| 113 | + | `blocked_by`: each issue this one waits on, with its claims and pull | |
| 114 | + | requests. | |
| 115 | + | - **Renew** it by claiming again, or give the `session_id` of your session | |
| 116 | + | when you claim, and that session's heartbeats renew it. | |
| 117 | + | - **Release** it with `issue` `release`, or | |
| 118 | + | [`POST /repos/{owner}/{name}/issues/{number}/release`](/reference/api/claims-and-work/release-claim/), | |
| 119 | + | with an optional `reason`. | |
| 120 | + | - **Hand it off** with `issue` `handoff`, or | |
| 121 | + | [`POST /repos/{owner}/{name}/issues/{number}/handoff`](/reference/api/claims-and-work/hand-off-issue/), | |
| 122 | + | with a `note` on where the work stands, for `to` (a username) or anyone. | |
| 123 | + | When whoever it was for claims the issue, their `work.claimed` event | |
| 124 | + | names the hand-off in `took_over`. | |
| 125 | + | ||
| 126 | + | ```sh | |
| 127 | + | curl -X POST https://api.g1t.sh/repos/acme/web/issues/12/claim \ | |
| 128 | + | -H "Authorization: Bearer $G1T_TOKEN" \ | |
| 129 | + | -H "Content-Type: application/json" \ | |
| 130 | + | -d '{"session_id": "ses_01m4b2c3d4e5f6g7h8j9k0m1n2", "note": "Taking the argument parsing first."}' | |
| 131 | + | ``` | |
| 132 | + | ||
| 133 | + | | | | | |
| 134 | + | | --- | --- | | |
| 135 | + | | How long a claim lasts | `ttl_minutes`: 30 unless you say, at most 240. | | |
| 136 | + | | When it ends | Released, handed off, its issue closed, or not renewed in time (`expired`). | | |
| 137 | + | | States | `active`, `released`, `expired`, `handed_off`. | | |
| 138 | + | ||
| 139 | + | See who is on what with `issue` `list_claims`, or | |
| 140 | + | [`GET /repos/{owner}/{name}/claims`](/reference/api/claims-and-work/list-claims/): | |
| 141 | + | active claims unless `state` says otherwise, and `issue` for one issue's. | |
| 142 | + | ||
| 143 | + | ## Dependencies | |
| 144 | + | ||
| 145 | + | An issue's `blocked_by` lists the issues of the same repository that have | |
| 146 | + | to land before it. Set it with `issue` `update`, or | |
| 147 | + | [`PATCH /repos/{owner}/{name}/issues/{number}`](/reference/api/issues/update-issue/), | |
| 148 | + | which replaces the whole list: | |
| 149 | + | ||
| 150 | + | ```sh | |
| 151 | + | curl -X PATCH https://api.g1t.sh/repos/acme/web/issues/12 \ | |
| 152 | + | -H "Authorization: Bearer $G1T_TOKEN" \ | |
| 153 | + | -H "Content-Type: application/json" \ | |
| 154 | + | -d '{"blocked_by": [9, 10]}' | |
| 155 | + | ``` | |
| 156 | + | ||
| 157 | + | A list is refused with `422` when a number is not an issue of the | |
| 158 | + | repository, names the issue itself, or would make a cycle (the answer | |
| 159 | + | shows the cycle, such as `#12 → #9 → #12`). Up to 50 issues. Changing it | |
| 160 | + | notes the change in the issue's conversation and needs what editing the | |
| 161 | + | issue does: being its author, or the Triage role. | |
| 162 | + | ||
| 163 | + | g1t says when a dependency moves, as a `dependency.changed` event on the | |
| 164 | + | blocked issue: when its list changes, and when one of its blockers closes | |
| 165 | + | or has a pull request merged into the default branch. `remaining` lists | |
| 166 | + | the blockers still open; when it is empty, the issue is unblocked. | |
| 167 | + | ||
| 168 | + | ## Overlaps | |
| 169 | + | ||
| 170 | + | Opening a pull request, and each push to it, works out which files it | |
| 171 | + | changes. When it starts changing files another open or draft pull request | |
| 172 | + | changes, g1t sends `overlap.detected` once for each of the two, naming the | |
| 173 | + | other and the files. A pair is announced once, and again only after it stopped | |
| 174 | + | overlapping. `get_work` and `pull_request` `get` show current overlaps | |
| 175 | + | whenever you look. | |
| 176 | + | ||
| 177 | + | ## Events | |
| 178 | + | ||
| 179 | + | Coordination is published as events, which [webhooks](/guides/webhooks/) | |
| 180 | + | deliver and the repository's timeline lists. Each carries `number` (the | |
| 181 | + | issue or pull request it is about) and `issue` where there is one. | |
| 182 | + | ||
| 183 | + | | Event | When | | |
| 184 | + | | --- | --- | | |
| 185 | + | | `session.started` | A session starts, or one that ended starts again. Not on a repeated start. | | |
| 186 | + | | `session.ended` | A session ends, or times out after 2 hours without a heartbeat. | | |
| 187 | + | | `work.claimed` | Someone claims an issue. `others` lists the claims already on it; `took_over` names a hand-off it takes. | | |
| 188 | + | | `work.released` | A claim is released, or its issue closed (`reason` `issue_closed`). | | |
| 189 | + | | `work.claim_expired` | A claim was not renewed in time. | | |
| 190 | + | | `work.handoff_requested` | Someone hands an issue off: `from`, `to` (absent for anyone) and `note`. | | |
| 191 | + | | `dependency.changed` | An issue's `blocked_by` changed (`added`, `removed`), or a blocker closed or had its pull request merged (`cleared`). `remaining` lists the blockers still open. | | |
| 192 | + | | `overlap.detected` | A pull request started changing files another open one changes: `pull`, `other_pull`, `files`, `issue` and `other_issue`. | | |
| 193 | + | ||
| 194 | + | A session or claim that went quiet is announced as ended or expired when | |
| 195 | + | the repository's sessions or claims are next read or changed, not at the | |
| 196 | + | minute it lapsed. | |
| 197 | + | ||
| 198 | + | ## Who may do what | |
| 199 | + | ||
| 200 | + | | To | You need | | |
| 201 | + | | --- | --- | | |
| 202 | + | | Read sessions, claims and an issue's context | To be able to read the repository. Public repositories need no token. | | |
| 203 | + | | Start a session, claim an issue | A confirmed email address and a role that may open issues; the repository must not be archived. | | |
| 204 | + | | Update, record in or end a session | To be the person whose token started it. | | |
| 205 | + | | Release a claim or hand it off | To be the person who made it. | | |
| 206 | + | | Set `blocked_by` | To be the issue's author, or the Triage role. | | |
| 207 | + | ||
| 208 | + | With an access token, sessions need `pull_requests:read` or | |
| 209 | + | `pull_requests:write`, and claims and `get_work` need `issues:read` or | |
| 210 | + | `issues:write`, as [scopes](/guides/authentication/#scopes) say. |
| 111 | 111 | | `deployment_status.created` | A deployment got a status, from any source. `data.repo_id`, `data.deployment` without its `payload`, and `data.deployment_status`. | | |
| 112 | 112 | | `release.created`, `.published`, `.released`, `.prereleased`, `.edited`, `.unpublished`, `.deleted` | A [release](/guides/releases/) changed; one change can send several, as the [release activity types](/guides/actions/#releases) say. `data.release_id`, `data.tag_name`, and `data.release` (`tag_name`, `target`, `name`, `body`, `draft`, `prerelease`, `author`, `created_at`, `published_at`), as it was for `release.deleted`. On `release.edited`, `data.changes` holds the old `name` and `body`. | | |
| 113 | 113 | | `queue.changed` | The merge queue gained, lost or settled an entry. | | |
| 114 | − | | `session.appended` | A pull request's [session](/guides/why-blame/#sessions) grew: a coding agent recorded entries with `record_session`. Busy: choose it only if you need it. | | |
| 114 | + | | `session.appended` | A pull request's [session](/guides/why-blame/#sessions) grew: a coding agent recorded entries with `record_session`, or a session on it recorded some. Busy: choose it only if you need it. | | |
| 115 | + | | `session.started`, `session.ended` | A [session](/guides/sessions/#sessions) of someone's harness started (not on a repeated start), or ended or timed out. `data.session`, and `data.number` (its pull request, else its issue) and `data.issue`. | | |
| 116 | + | | `work.claimed`, `work.released`, `work.claim_expired`, `work.handoff_requested` | A [claim](/guides/sessions/#claims) on an issue was made, released, expired or handed off. `data.number` and `data.issue` (the issue), `data.claim`; on `work.claimed`, `data.others` (the other active claims) and `data.took_over`; on `work.released`, `data.reason`; on a hand-off, `data.from`, `data.to` and `data.note`. | | |
| 117 | + | | `dependency.changed` | What an issue is [blocked by](/guides/sessions/#dependencies) changed, or a blocker closed or had its pull request merged. `data.number` (the blocked issue), `data.blocked_by`, `data.added`, `data.removed`, `data.cleared`, `data.remaining` (blockers still open) and `data.merged_pull`. | | |
| 118 | + | | `overlap.detected` | A push made a pull request [change files another open one changes](/guides/sessions/#overlaps). Sent once for each of the two: `data.pull`, `data.other_pull`, `data.files`, `data.issue` and `data.other_issue`. | | |
| 115 | 119 | ||
| 116 | 120 | [Managing a repository](/guides/managing-repositories/) says what each of | |
| 117 | 121 | the `repo.` and `branch.` changes does. |
| 9 | 9 | ||
| 10 | 10 | ## Sessions | |
| 11 | 11 | ||
| 12 | − | A session belongs to a pull request. It records how the change was made, | |
| 13 | − | entry by entry, as it happens: | |
| 12 | + | A pull request's session records how the change was made, entry by entry, | |
| 13 | + | as it happens. Entries come from `record_session` on the pull request, and | |
| 14 | + | from any [harness session](/guides/sessions/#sessions) attached to it: | |
| 14 | 15 | ||
| 15 | 16 | | Kind | What it holds | | |
| 16 | 17 | | --- | --- | |
| 4 | 4 | --- | |
| 5 | 5 | ||
| 6 | 6 | The MCP server at `https://mcp.g1t.sh` is how a coding agent, such as | |
| 7 | − | Claude Code, Codex, Cursor or OpenCode, works on g1t. It exposes 18 tools, | |
| 7 | + | Claude Code, Codex, Cursor or OpenCode, works on g1t. It exposes 19 tools, | |
| 8 | 8 | one per kind of thing on g1t: `search`, `repository`, `issue`, | |
| 9 | − | `pull_request`, `memory`, `workflow`, `observability`, `package`, `secret`, | |
| 9 | + | `pull_request`, `session`, `memory`, `workflow`, `observability`, `package`, `secret`, | |
| 10 | 10 | `security`, `webhook`, `access`, `team`, `workspace`, `billing`, | |
| 11 | 11 | `notifications`, `account` and `artifact`. Each tool takes an `action` that says what to do. Every | |
| 12 | 12 | action is the same operation as a route of the [REST API](/reference/api/), | |
| ⋯ | |||
| 315 | 315 | ||
| 316 | 316 | ## `issue` | |
| 317 | 317 | ||
| 318 | − | Issues: what should change. Read one before working on it, to see the pull | |
| 319 | − | requests already made for it. Issues and pull requests share numbers, so | |
| 320 | − | `comment` works on either. | |
| 318 | + | Issues: what should change. Before working on one, `work` gives everything | |
| 319 | + | about it, and `claim` says you are on it; see | |
| 320 | + | [sessions, claims and dependencies](/guides/sessions/). Issues and pull | |
| 321 | + | requests share numbers, so `comment` works on either. | |
| 321 | 322 | ||
| 322 | 323 | | Action | What it does | Required | Scope | | |
| 323 | 324 | | --- | --- | --- | --- | | |
| 324 | 325 | | [`list`](/reference/api/issues/list-issues/) | Issues, newest first, by `state`, `label` and `milestone` (its number). | `repo` | `issues:read` | | |
| 325 | 326 | | [`get`](/reference/api/issues/get-issue/) | An issue: description (which may say what done means, under **Definition of done**), labels, comments, and every pull request made for it. | `repo`, `number` | `issues:read` | | |
| 326 | 327 | | [`create`](/reference/api/issues/create-issue/) | Open an issue, with `body`, `labels` and `milestone`. A label the repository lacks is created for someone with the Write role. `checks` is deprecated: its commands are added to the body under **Definition of done**, and the result carries a `deprecation` note. | `repo`, `title` | `issues:write` | | |
| 327 | − | | [`update`](/reference/api/issues/update-issue/) | Change its title, body, labels, milestone or assignees. Labels and assignees each replace the whole set; `milestone` `null` or `0` takes it out of its milestone. | `repo`, `number` | `issues:write` | | |
| 328 | + | | [`update`](/reference/api/issues/update-issue/) | Change its title, body, labels, milestone, assignees or `blocked_by` (the issues that must land first). Labels, assignees and `blocked_by` each replace the whole set; `milestone` `null` or `0` takes it out of its milestone. A `blocked_by` that names the issue itself, something not an issue of the repository, or makes a cycle is refused. | `repo`, `number` | `issues:write` | | |
| 328 | 329 | | [`labels`](/reference/api/issues/list-issue-labels/) | The labels an issue or pull request carries, with their colors. | `repo`, `number` | `issues:read` | | |
| 329 | 330 | | [`add_labels`](/reference/api/issues/add-issue-labels/) | Add `labels` to an issue or pull request, keeping the ones it has. | `repo`, `number`, `labels` | `issues:write` | | |
| 330 | 331 | | [`set_labels`](/reference/api/issues/set-issue-labels/) | Replace an issue's or pull request's labels with `labels`. | `repo`, `number`, `labels` | `issues:write` | | |
| ⋯ | |||
| 335 | 336 | | [`edit_comment`](/reference/api/issues/edit-comment/) | Change a comment's text, by its id from `get`. Your own, or anyone's with the Maintain role or higher. Notes of what happened cannot be edited. | `repo`, `comment_id`, `body` | `issues:write` | | |
| 336 | 337 | | [`delete_comment`](/reference/api/issues/delete-comment/) | Delete a comment, by its id. Your own, or anyone's with the Maintain role or higher. A review that approved or requested changes cannot be deleted. | `repo`, `comment_id` | `issues:write` | | |
| 337 | 338 | | [`import`](/reference/api/integrations/import-issue/) | Open an issue from a Jira, Linear or Sentry item, linked to it. | `repo`, `reference` | `issues:write` | | |
| 339 | + | | [`work`](/reference/api/claims-and-work/get-work/) | Everything to pick an issue up: its definition of done and required checks, active claims, sessions, pull requests (checks, mergeability, overlaps, queue place), what it is blocked by and blocks, decisions, and its recent coordination events. | `repo`, `number` | `issues:read` | | |
| 340 | + | | [`claim`](/reference/api/claims-and-work/claim-issue/) | Say you are working on an open issue: advisory and expiring (`ttl_minutes`, 30 unless you say, at most 240), never a lock. Returns `others` already on it and what it is `blocked_by`. Claiming again, or a heartbeat of its `session_id`, renews it. | `repo`, `number` | `issues:write` | | |
| 341 | + | | [`release`](/reference/api/claims-and-work/release-claim/) | Give up your claim, with an optional `reason`. | `repo`, `number` | `issues:write` | | |
| 342 | + | | [`handoff`](/reference/api/claims-and-work/hand-off-issue/) | End your claim as handed off, `to` someone or anyone, with a `note` on where the work stands. | `repo`, `number`, `note` | `issues:write` | | |
| 343 | + | | [`list_claims`](/reference/api/claims-and-work/list-claims/) | Claims on a repository's issues, newest first: active unless `state` says otherwise, `issue` for one. | `repo` | `issues:read` | | |
| 338 | 344 | ||
| 339 | 345 | ## `pull_request` | |
| 340 | 346 | ||
| ⋯ | |||
| 366 | 372 | tool entries. See [sessions and why-blame](/guides/why-blame/) and the | |
| 367 | 373 | [merge queue](/guides/merge-queue/). | |
| 368 | 374 | ||
| 375 | + | ## `session` | |
| 376 | + | ||
| 377 | + | Your harness's session on a repository, so others see who is working on | |
| 378 | + | what. Start one per run of your harness, heartbeat it, record what it does, | |
| 379 | + | and end it. See [sessions](/guides/sessions/#sessions). | |
| 380 | + | ||
| 381 | + | | Action | What it does | Required | Scope | | |
| 382 | + | | --- | --- | --- | --- | | |
| 383 | + | | [`start`](/reference/api/sessions/start-session/) | Start a session: `harness` (`claude_code`, `codex`, `cursor`, `copilot` or `other`), and `harness_session_id`, which makes starting again return the same session. `issue`, `pull`, `branch`, `title` and `head_commit` as you know them. | `repo`, `harness` | `pull_requests:write` | | |
| 384 | + | | [`update`](/reference/api/sessions/update-session/) | A heartbeat, and renews the session's claims; with fields, attaches an `issue` or `pull`, or sets `branch`, `head_commit` or `title`. | `repo`, `id` | `pull_requests:write` | | |
| 385 | + | | [`record`](/reference/api/sessions/record-session-entries/) | Record up to 200 `entries`, each with `kind` and `text`, `tool` for tools, and a `key` that makes recording it again a no-op. | `repo`, `id`, `entries` | `pull_requests:write` | | |
| 386 | + | | [`end`](/reference/api/sessions/end-session/) | End it, with an optional `reason`. | `repo`, `id` | `pull_requests:write` | | |
| 387 | + | | [`get`](/reference/api/sessions/get-session/) | A session and its entries; `after` pages through them. | `repo`, `id` | `pull_requests:read` | | |
| 388 | + | | [`list`](/reference/api/sessions/list-sessions/) | A repository's sessions, most recently heard from first, by `state` (`active`, `idle`, `ended`), `issue` or `pull`. | `repo` | `pull_requests:read` | | |
| 389 | + | ||
| 369 | 390 | ## `memory` | |
| 370 | 391 | ||
| 371 | 392 | What the project and its workspace remember for whoever works on it next, | |
| 73 | 73 | title: "Deployments", | |
| 74 | 74 | events: ["deployment.created", "deployment_status.created", "deployment.succeeded", "deployment.failed"], | |
| 75 | 75 | }, | |
| 76 | − | { title: "Sessions", events: ["session.appended"] }, | |
| 76 | + | { title: "Sessions", events: ["session.started", "session.ended", "session.appended"] }, | |
| 77 | + | { | |
| 78 | + | title: "Coordination", | |
| 79 | + | events: [ | |
| 80 | + | "work.claimed", | |
| 81 | + | "work.released", | |
| 82 | + | "work.claim_expired", | |
| 83 | + | "work.handoff_requested", | |
| 84 | + | "dependency.changed", | |
| 85 | + | "overlap.detected", | |
| 86 | + | ], | |
| 87 | + | }, | |
| 77 | 88 | { title: "Access", events: ["workspace.member_joined", "repo.collaborator_added", "repo.collaborator_removed", "repo.collaborator_role_changed"] }, | |
| 78 | 89 | { | |
| 79 | 90 | title: "Teams", |
| 152 | 152 | - **Read an issue:** `GET {repo}/issues/{number}`. It lists every pull | |
| 153 | 153 | request already made for it. A closed issue's `resolved_by` is the number | |
| 154 | 154 | of the pull request that was merged. | |
| 155 | + | - **Pick up an issue:** `GET {repo}/issues/{number}/work` returns its whole | |
| 156 | + | context in one call: `definition_of_done`, `required_checks`, active | |
| 157 | + | `claims`, `sessions`, its `pulls` (checks, `mergeable`, `overlaps`, | |
| 158 | + | merge `queue` place), `blocked_by`, `blocks`, `decisions` and `recent` | |
| 159 | + | coordination events. Then `POST {repo}/issues/{number}/claim` (optional | |
| 160 | + | `session_id`, `note`, `ttl_minutes`): a claim is advisory and expiring, | |
| 161 | + | never a lock, and `others` lists who else is on it. Release it with | |
| 162 | + | `POST {repo}/issues/{number}/release`, or hand it off with | |
| 163 | + | `POST {repo}/issues/{number}/handoff` and a `note`. | |
| 164 | + | - **Start a session** for each run of your harness: | |
| 165 | + | `POST {repo}/sessions` with `harness` (`claude_code`, `codex`, `cursor`, | |
| 166 | + | `copilot`, `other`) and `harness_session_id` (starting again with it | |
| 167 | + | returns the same session). `PATCH {repo}/sessions/{id}` is a heartbeat | |
| 168 | + | (empty body) or attaches `issue`, `pull`, `branch`, `head_commit`; | |
| 169 | + | `POST {repo}/sessions/{id}/entries` records `entries`, each with an | |
| 170 | + | optional `key` that makes it idempotent; `POST {repo}/sessions/{id}/end` | |
| 171 | + | ends it. Idle after 15 minutes without a heartbeat, ended after 2 hours. | |
| 172 | + | - **Dependencies:** `PATCH {repo}/issues/{number}` with `blocked_by` (issue | |
| 173 | + | numbers) sets the issues that must land first; no cycles. | |
| 155 | 174 | - **Recall memory** before you start: `GET {repo}/memory?q=<words>` returns | |
| 156 | 175 | what the project remembers: how to build it, its conventions, decisions | |
| 157 | 176 | and traps. When you learn something the next agent needs, save one short | |
| ⋯ | |||
| 232 | 251 | ||
| 233 | 252 | Everything under "Do work" is also on the MCP server. Its tools are resources, | |
| 234 | 253 | each with an `action`: `search`, `repository`, `issue`, `pull_request`, | |
| 235 | − | `memory`, `workflow`, `observability`, `package`, `secret`, `webhook`, | |
| 254 | + | `session`, `memory`, `workflow`, `observability`, `package`, `secret`, `webhook`, | |
| 236 | 255 | `access`, `team`, `workspace`, `billing`, `security`, `notifications`, | |
| 237 | 256 | `account` and `artifact`. Call `tools/call` with the tool's name and | |
| 238 | 257 | `arguments` holding `action` and its inputs, such as | |
| 239 | 258 | `{"name": "issue", "arguments": {"action": "get", "repo": "acme/web", "number": 12}}`. | |
| 240 | 259 | MCP tools take the repository as `repo`, written `owner/name`. | |
| 241 | − | The flow above is: `issue` `get`, `memory` `recall`, `pull_request` | |
| 260 | + | The flow above is: `issue` `work` (the issue's whole context: definition | |
| 261 | + | of done, claims, sessions, pull requests, blockers), `issue` `claim` | |
| 262 | + | (advisory; it lists who else is on it), `memory` `recall`, `pull_request` | |
| 242 | 263 | `create` (with `issue`), push, `pull_request` `record_session` as you go, | |
| 243 | 264 | `pull_request` `ready` with `summary`; read `overlaps`, `behind`, | |
| 244 | 265 | `statuses` and `required_checks` on `pull_request` `get`, and | |
| 245 | 266 | `repository` `check_names` for the names a branch can require; | |
| 246 | 267 | `workflow` `get_run` and `job_logs` for why a check failed, and | |
| 247 | 268 | `list_check_runs` and `check_run_annotations` for what a commit's checks | |
| 248 | − | say. `pull_request` `read_session` reads a session back, and `memory` | |
| 269 | + | say. `session` `start` (idempotent on `harness_session_id`), `update` (a | |
| 270 | + | heartbeat), `record` (entries, idempotent on `key`) and `end` say who is | |
| 271 | + | working on what; `issue` `release` or `handoff` (with a `note`) when you | |
| 272 | + | stop, and `issue` `update` with `blocked_by` sets the issues that must | |
| 273 | + | land first. `pull_request` `read_session` reads a session back, and `memory` | |
| 249 | 274 | `remember` saves a fact. `notifications` reads and answers the | |
| 250 | 275 | notifications of the person a token acts for: `list` (unread threads, each | |
| 251 | 276 | with a `reason` such as `review_requested` or `mention`), `done`, | |