# click.aligned.chat.message

> Published by [aligned.click](https://lexicon.garden/identity/did:plc:kdnkzvtg6nugup477ev22xfa)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:kdnkzvtg6nugup477ev22xfa/click.aligned.chat.message)
- [Documentation](https://lexicon.garden/lexicon/did:plc:kdnkzvtg6nugup477ev22xfa/click.aligned.chat.message/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:kdnkzvtg6nugup477ev22xfa/click.aligned.chat.message/examples)

## Definitions

### `click.aligned.chat.message`

**Type**: `record`

One turn of a published conversation with an agent. Records exist only for a conversation somebody published; within one, every turn has a record, in order, so the record key's TID ordering is the reading order.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `refs` | `array` | No | Records this turn is about, as strong references. Pointed at, never copied: a copy would survive the author deleting the original, and it should not. A strongRef pins the CID, so a reader gets the version that was actually discussed and can tell when it has since changed — which is what you want for a post, whose text is the thing. |
| `role` | `string` | Yes | Who is speaking. |
| `text` | `string` | Yes | What was said. The assistant's own words, so they are stored rather than referenced — there is nowhere else they exist. Runs of █ are redactions: spans the author covered rather than withhold the whole turn over, of a fixed width so the bar does not say how long the words were. The covered words were never published and are not recoverable from this record; a viewer that does nothing special shows the bars as text, which is the honest reading. |
| `model` | `string` | No | The model that produced an assistant turn, e.g. 'greenpt/minimax-m2.5'. Present on assistant turns so a reader never has to guess whether they are reading a person or a machine, and can tell which machine. |
| `steps` | `array` | No | The tools the agent called on this turn, in order. Published because the point of a conversation like this is usually *how* the answer was reached; a reply with the working removed is the least interesting part of it. |
| `session` | `string` (at-uri) | Yes | The click.aligned.chat.session this turn belongs to. A plain at-uri, deliberately not a strongRef: the session may be retitled later, and a strongRef would pin a CID that then no longer exists. |
| `mentions` | `array` | No | atproto accounts this turn is about, as DIDs. Deliberately not strongRefs to their profile records: a person is not a version of their bio, and pinning one would make a turn about someone go stale the next time they change their avatar. A DID is the identity, and it is the identity that was being discussed. |
| `withheld` | `boolean` | No | This turn happened and its content was not published. Every turn of a published conversation gets a record, so one published in part has visible holes rather than invisible ones — an answer to a question that was held back would otherwise read as an answer to whatever came before it. A conversation nobody published has no records at all, withheld ones included: a record saying only that somebody spoke at a time is a hole in nothing. Stated rather than inferred from an empty `text`, so a reader never has to guess whether a turn was withheld or simply empty. Absent means published. |
| `createdAt` | `string` (datetime) | Yes | When the turn happened. |

### `click.aligned.chat.message#step`

**Type**: `object`

One tool call. The name and a short summary of what it was for — never the output, which is often large, often private, and reproducible by anyone holding the same tools.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `tool` | `string` | Yes | Tool name as the agent called it, e.g. 'search-posts'. |
| `failed` | `boolean` | No | Whether the call errored. Published rather than hidden: a workflow that shows only the calls that worked is a misleading picture of working with an agent. |
| `summary` | `string` | No | One line on what it was called for or what came back. |

## Raw Schema

```json
{
  "id": "click.aligned.chat.message",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "session",
          "role",
          "text",
          "createdAt"
        ],
        "properties": {
          "refs": {
            "type": "array",
            "items": {
              "ref": "com.atproto.repo.strongRef",
              "type": "ref"
            },
            "maxLength": 50,
            "description": "Records this turn is about, as strong references. Pointed at, never copied: a copy would survive the author deleting the original, and it should not. A strongRef pins the CID, so a reader gets the version that was actually discussed and can tell when it has since changed — which is what you want for a post, whose text is the thing."
          },
          "role": {
            "type": "string",
            "description": "Who is speaking.",
            "knownValues": [
              "user",
              "assistant"
            ]
          },
          "text": {
            "type": "string",
            "maxLength": 60000,
            "description": "What was said. The assistant's own words, so they are stored rather than referenced — there is nowhere else they exist. Runs of █ are redactions: spans the author covered rather than withhold the whole turn over, of a fixed width so the bar does not say how long the words were. The covered words were never published and are not recoverable from this record; a viewer that does nothing special shows the bars as text, which is the honest reading.",
            "maxGraphemes": 15000
          },
          "model": {
            "type": "string",
            "description": "The model that produced an assistant turn, e.g. 'greenpt/minimax-m2.5'. Present on assistant turns so a reader never has to guess whether they are reading a person or a machine, and can tell which machine."
          },
          "steps": {
            "type": "array",
            "items": {
              "ref": "#step",
              "type": "ref"
            },
            "maxLength": 100,
            "description": "The tools the agent called on this turn, in order. Published because the point of a conversation like this is usually *how* the answer was reached; a reply with the working removed is the least interesting part of it."
          },
          "session": {
            "type": "string",
            "format": "at-uri",
            "description": "The click.aligned.chat.session this turn belongs to. A plain at-uri, deliberately not a strongRef: the session may be retitled later, and a strongRef would pin a CID that then no longer exists."
          },
          "mentions": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "did"
            },
            "maxLength": 50,
            "description": "atproto accounts this turn is about, as DIDs. Deliberately not strongRefs to their profile records: a person is not a version of their bio, and pinning one would make a turn about someone go stale the next time they change their avatar. A DID is the identity, and it is the identity that was being discussed."
          },
          "withheld": {
            "type": "boolean",
            "description": "This turn happened and its content was not published. Every turn of a published conversation gets a record, so one published in part has visible holes rather than invisible ones — an answer to a question that was held back would otherwise read as an answer to whatever came before it. A conversation nobody published has no records at all, withheld ones included: a record saying only that somebody spoke at a time is a hole in nothing. Stated rather than inferred from an empty `text`, so a reader never has to guess whether a turn was withheld or simply empty. Absent means published."
          },
          "createdAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the turn happened."
          }
        },
        "description": "One turn of a conversation, in the repo of the person who had it. Written when they publish some part of that conversation, carrying its content only if this turn was one of the parts — so within a conversation that is public at all, the shape is public and the words are by decision."
      },
      "description": "One turn of a published conversation with an agent. Records exist only for a conversation somebody published; within one, every turn has a record, in order, so the record key's TID ordering is the reading order."
    },
    "step": {
      "type": "object",
      "required": [
        "tool"
      ],
      "properties": {
        "tool": {
          "type": "string",
          "maxLength": 320,
          "description": "Tool name as the agent called it, e.g. 'search-posts'.",
          "maxGraphemes": 64
        },
        "failed": {
          "type": "boolean",
          "description": "Whether the call errored. Published rather than hidden: a workflow that shows only the calls that worked is a misleading picture of working with an agent."
        },
        "summary": {
          "type": "string",
          "maxLength": 1000,
          "description": "One line on what it was called for or what came back.",
          "maxGraphemes": 250
        }
      },
      "description": "One tool call. The name and a short summary of what it was for — never the output, which is often large, often private, and reproducible by anyone holding the same tools."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
