> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sidecars.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Comments

> Read, start, reply to and resolve comment threads on a document or page, with anchored quotes and agent mentions.

Read, start, reply to and resolve the comment threads on a document or page.

| Tool                                  | Scope             | Kind              |
| ------------------------------------- | ----------------- | ----------------- |
| [`read_comments`](#read-comments)     | `documents:read`  | read-only         |
| [`add_comment`](#add-comment)         | `documents:write` | write             |
| [`resolve_comment`](#resolve-comment) | `documents:write` | write, idempotent |

## read\_comments

**Scope:** `documents:read` (step-up) · **Kind:** read-only · **Annotations:** `readOnlyHint: true`, `destructiveHint: false`, `openWorldHint: false`

> The comment threads on a document or page: each thread's id, status (open
> \| resolved), the quoted passage it is anchored to (if any), the author and
> body, and its replies. Open threads only unless `include_resolved` is
> true. Returns your `role` — a viewer can read threads but not add to them.

### Parameters

<ParamField body="document_id" type="string" required>
  The artifact id of a document or page.
</ParamField>

<ParamField body="include_resolved" type="boolean" default="false">
  Include resolved threads.
</ParamField>

### Returns

<ResponseField name="role" type="'owner' | 'editor' | 'commenter' | 'viewer'">Your effective role on the artifact.</ResponseField>

<ResponseField name="threads" type="array">
  <Expandable title="thread">
    <ResponseField name="thread_id" type="string">Pass to `add_comment` (reply) and `resolve_comment`.</ResponseField>

    <ResponseField name="status" type="'open' | 'resolved'" />

    <ResponseField name="anchor_excerpt" type="string">The quoted passage the thread is attached to, when anchored.</ResponseField>

    <ResponseField name="author_label" type="string" />

    <ResponseField name="body" type="string">The opening comment, markdown.</ResponseField>
    <ResponseField name="created_at" type="number">Milliseconds since epoch.</ResponseField>
    <ResponseField name="replies" type="array">Each with `author_label`, `body` and `deleted`.</ResponseField>
    <ResponseField name="more_replies" type="boolean">`true` when the thread has more replies than were listed.</ResponseField>
  </Expandable>
</ResponseField>

Text, per thread:

```text theme={null}
- [open] thread_id: <id> · <author> · <ISO time> · on "<anchor excerpt>"
  <body>
  ↳ <author>: <reply>
  ↳ […more replies not listed]
```

or `No open comment threads.` / `No comment threads.`

### Permissions and side effects

* Needs `documents:read` and any role on the artifact.
* Reads only. Recorded in the agent activity history.

### Errors

| Text                                | Cause                                      |
| ----------------------------------- | ------------------------------------------ |
| `Tool failed: … Artifact not found` | Not visible, wrong workspace or no such id |

### Limitations

* The number of replies listed per thread is capped; `more_replies` tells
  you when some were left out. There is no way to page through them over
  MCP.

### Example

**Request**

```json theme={null}
{ "name": "read_comments", "arguments": { "document_id": "k97fq2example000000000000000000" } }
```

**Response (structuredContent)**

```json theme={null}
{
  "role": "editor",
  "threads": [
    {
      "thread_id": "m7thread0example00000000000000000",
      "status": "open",
      "anchor_excerpt": "Vendor SDK still in beta",
      "author_label": "Jordan Lee",
      "body": "Do we have a GA date from the vendor?",
      "created_at": 1757150000000,
      "replies": [
        { "author_label": "Priya Raman", "body": "Asking them today.", "deleted": false }
      ],
      "more_replies": false
    }
  ]
}
```

## add\_comment

**Scope:** `documents:write` (step-up) · **Kind:** write · **Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

> Start a comment thread on a document or page, or reply in one (`thread_id`
> from read\_comments). A new thread is attached to the whole artifact unless
> `anchor_excerpt` quotes a passage the document contains exactly once —
> then the thread quotes that passage. Mention `@Assistant` in the body to
> have the workspace assistant reply in the thread; a mention is never
> required. Needs the commenter role or higher; a viewer is refused.

### Parameters

<ParamField body="document_id" type="string" required />

<ParamField body="body_markdown" type="string" required>
  The comment, markdown. Must be non-empty. Mentions fan out exactly as they do in the app: `@Priya` notifies a
  person, and `@Assistant` makes the workspace assistant reply in the
  thread. `@Assistant` exists in every workspace; other installed agents
  (for example `@Builder`) are the handles the app's mention picker
  offers. Retired handles (`@PM`, `@Research`, `@GTM`) still reach the
  assistant. There is no generic `@Agent` handle; any other unrecognised
  handle is plain text, and a comment needs no mention at all.
</ParamField>

<ParamField body="thread_id" type="string">
  Reply in this thread instead of starting a new one. `anchor_excerpt` is
  ignored when replying.
</ParamField>

<ParamField body="anchor_excerpt" type="string">
  New threads only. An exact passage from `read_document`. If the document
  contains it exactly once, the thread is anchored to it; otherwise the
  thread is created unanchored and the result says so.
</ParamField>

### Returns

New thread:

<ResponseField name="thread_id" type="string" />

<ResponseField name="anchored" type="boolean">Whether the excerpt matched exactly once.</ResponseField>

Reply:

<ResponseField name="thread_id" type="string" />

<ResponseField name="comment_id" type="string" />

Text: `Started thread <id> on the quoted passage.` /
`Started thread <id> on the whole document — the quoted passage was not found exactly once, so the thread is unanchored.` /
`Started thread <id>.` / `Replied in thread <id> (comment_id: <id>).`

### Permissions and side effects

* Needs `documents:write` and the `commenter`, `editor` or `owner` role.
* The comment is posted as you via the host, in the same thread the app's
  Comments tab shows. Mentions notify people; an installed agent's handle (for example
  `@Assistant`) makes that agent reply in-thread.
* An unmatched anchor does **not** fail the call; check `anchored`.

### Errors

| Text                                                | Cause                                                               |
| --------------------------------------------------- | ------------------------------------------------------------------- |
| `Tool failed: … This document is read-only for you` | You are a viewer                                                    |
| `Tool failed: … This document is archived`          | Archived artifact                                                   |
| `Tool failed: … Artifact not found`                 | Not visible, wrong workspace or no such id                          |
| `Tool failed: <message>`                            | `thread_id` does not belong to this artifact, or the thread is gone |

<Note>
  The exact wording for an invalid `thread_id` comes from the comment backend
  and was not verified for this page. Treat any `Tool failed:` result on a
  reply as "the thread is not there" and re-read the threads.
</Note>

### Example

**Request**

```json theme={null}
{
  "name": "add_comment",
  "arguments": {
    "document_id": "k97fq2example000000000000000000",
    "anchor_excerpt": "Onboard three design partners",
    "body_markdown": "Two are signed; the third (Northwind) is still in legal. @Priya can you confirm timing?"
  }
}
```

**Response (structuredContent)**

```json theme={null}
{ "thread_id": "m8thread0example00000000000000000", "anchored": true }
```

## resolve\_comment

**Scope:** `documents:write` (step-up) · **Kind:** write, idempotent · **Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`

> Mark a comment thread resolved (`resolved: true`) or reopen it
> (`resolved: false`). Idempotent. Needs the commenter role or higher.

### Parameters

<ParamField body="document_id" type="string" required />

<ParamField body="thread_id" type="string" required>From `read_comments` or `add_comment`.</ParamField>
<ParamField body="resolved" type="boolean" required>`true` to resolve, `false` to reopen.</ParamField>

### Returns

<ResponseField name="thread_id" type="string" />

<ResponseField name="status" type="'resolved' | 'open'" />

Text: `Thread <id> is now resolved.` or `Thread <id> is now open.`

### Permissions and side effects

* Needs `documents:write` and the `commenter`, `editor` or `owner` role.
* Changes the thread's status as you via the host. Repeating the call with
  the same value has no further effect.

### Errors

| Text                                                | Cause                                        |
| --------------------------------------------------- | -------------------------------------------- |
| `Tool failed: \`resolved\` must be a boolean\`      | Missing or non-boolean `resolved`            |
| `Tool failed: … This document is read-only for you` | You are a viewer                             |
| `Tool failed: … This document is archived`          | Archived artifact                            |
| `Tool failed: … Artifact not found`                 | Not visible, wrong workspace or no such id   |
| `Tool failed: <message>`                            | `thread_id` does not belong to this artifact |

### Example

**Request**

```json theme={null}
{
  "name": "resolve_comment",
  "arguments": {
    "document_id": "k97fq2example000000000000000000",
    "thread_id": "m7thread0example00000000000000000",
    "resolved": true
  }
}
```

**Response (structuredContent)**

```json theme={null}
{ "thread_id": "m7thread0example00000000000000000", "status": "resolved" }
```
