# Agent sessions

Source: https://amolfi.com/docs#api--sessions

A session is a durable conversation in your workspace. The same sessions you see in the app are readable and startable by a workspace token, so an outside agent works in the conversation rather than beside it.

### Scopes

```
sessions.sessions.read    list sessions, read one, page its events
sessions.sessions.write   start a turn, rename, pin, archive, fork
```

A token acts for the member who minted it. A session your token starts is owned by that person, appears in their rail in the app, and is visible to owners and admins exactly like one they started themselves. A token is not a new member and never becomes one.

### Start a turn and follow it

```
POST /v1/tools/agent_session_turn_start   { "message": "close the books for July" }
  -> { "session_id": "…", "run_id": "…", "seq": "2" }

POST /v1/tools/agent_session_events_list  { "session_id": "…", "after_seq": "2" }
```

Events arrive in ascending sequence with a `next_after_seq` cursor. Poll from the last sequence you stored. A turn started this way is a cloud turn: it keeps running after your process exits, and anything that sends, spends, signs, or publishes still stops at an approval card.

### What a session read withholds

Session events are projected field by field before they leave the workspace, so a read gives you the conversation without becoming a side door into everything the conversation touched.

- Assistant and user text, tool names, run status, and route arrive in full.
- A tool result arrives only when its result policy is `durable_summary`. A private or opaque result arrives as coordinates with `content_withheld`, the same content the API refuses to return if you call that tool directly.
- Reasoning summaries and model protocol state do not cross. They arrive as coordinates with `payload_withheld`.

An event kind that does not have a published projection yet arrives as coordinates rather than as its raw payload. Absence in a payload always means withheld, never empty.

### What has no machine verb

Approvals settle in the app. There is no endpoint that approves a card, and no scope that could be granted to do it.

Local turns are also first-party. A local turn runs a model on your own machine and reports its progress from that client, so a workspace token cannot start one or append to one. Ask for a cloud turn and the workspace runs it for you.

### Use the CLI

```
amolfi sessions                       # the rail, pinned first
amolfi sessions get <session_id>
amolfi sessions events <session_id> --after 12
amolfi sessions start "close the books for July"
amolfi sessions start "and now August" --session <session_id>
amolfi sessions rename <session_id> "July close"
amolfi sessions pin <session_id>
amolfi sessions fork <session_id> 42 --title "What if we delay"
```

Forking copies a session up to a sequence you choose. Both sessions continue independently from there, which is how you try a second approach without losing the first.

[Runs](https://amolfi.com/docs/api/runs)[Authentication](https://amolfi.com/docs/api/authentication)[The CLI](https://amolfi.com/docs/api/the-cli)

### Continue a conversation

The `message` input is required for a new task or follow-up. Include the optional `session_id` to continue an existing conversation; omit it to start a new session.

```
curl https://api.amolfi.com/v1/tools/agent_session_turn_start \
  -H "Authorization: Bearer $AMOLFI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $REQUEST_ID" \
  --data '{"message":"Summarize my open invoices."}'
```

200 OK · example data excerpt

```
{
  "session_id": "11111111-1111-4111-8111-111111111111",
  "run_id": "22222222-2222-4222-8222-222222222222",
  "seq": "1",
  "route": "cloud",
  "replayed": false
}
```

Set REQUEST\_ID to a unique value for each new request. Reuse it only when retrying that same request.
