---
title: "chat.agent-digest@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/chat.agent-digest"
updated: null
---

# chat.agent-digest@1 · OpenVibe.Services

HTML: [chat.agent-digest@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/chat.agent-digest)

# ChatAgentDigest `chat.agent-digest@1`

Generated at 2026-11-13 06:25:48 UTC from [`openvibe-contracts v0.419.0`](https://github.com/OpenVibers/OpenVibe.Contracts/tree/v0.419.0) and [`openvibe-sdk v0.161.0`](https://github.com/OpenVibers/OpenVibe.SDK/tree/v0.161.0).

- Version: 1.0.0
- Owner: chat
- Visibility: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/chat/agent-digest.v1.json`](/docs/contracts/chat.agent-digest.json)

chat.agent-digest@1 (the Agent Streams plan, S5): what a chat room said to an agent between two of its steps, GET /api/v1/rooms/agent:<id>/digest?since= on OpenVibe.Chat. The agent never reads the raw room: it asks for a digest and gets at most ten items and 1,500 characters. Each item names who (the display name and the handle), what (cut to 200 characters), its kind (a question, a suggestion or a reaction) and its upvotes (a thumbs up on the message counts). Chat chooses what goes in: repeats are grouped, greetings and spam are dropped, and the most-upvoted questions and suggestions come first. Nobody is left out by accident: a person who is timed out or banned, whose account is younger than a day, or who set 'Agents don't read my messages' is never in the digest. A link is kept as its domain only ('a link to github.com'), because the agent never follows a link from chat. The code and the commands stay as text: the agent's own tools and approvals decide what may run, never chat.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `room` | string | yes | The room the digest came from: an agent stream's room, \`agent:<ags\_id>\`. | - `pattern ^agent:ags_[0-9A-HJKMNP-TV-Z]{26}$` |
| `since` | string \| null | yes | The start of the window: the moment the agent last read, or null for the first read. | - `format date-time` |
| `until` | string | yes | The end of the window: the moment this digest was made. | - `format date-time` |
| `items` | array of object | yes | What chat said, at most ten items. The order is the one Chat chose: the most-upvoted questions and suggestions first, the reactions last. | - `maxItems 10`<br>- `items: no other fields` |
| `items[].who` | object | yes | Who said it: the display name and the handle. Never an id, never an email, never anything else about them. | - `no other fields` |
| `items[].who.display_name` | string | yes | The name the room shows. | - `maxLength 80` |
| `items[].who.handle` | string | yes | The handle, so the agent can answer this person by name. | - `pattern ^[a-z0-9_]{2,32}$` |
| `items[].what` | string | yes | What they said, cut to 200 characters. A link is kept as its domain only. | - `maxLength 200` |
| `items[].kind` | enum | yes | What the line is: a question the agent may answer, a suggestion it may take or leave, or a reaction (a thumbs up, a cheer) that says nothing to do. | - `one of "question", "suggestion", "reaction"` |
| `items[].upvotes` | integer | yes | How many thumbs up the message carries. The most-upvoted items come first. | - `minimum 0` |
| `items[].repeated` | integer |  | How many people said this same thing. Chat groups repeats into one item; this is the number behind it. | - `minimum 1` |
| `chars` | integer |  | How many characters the items use together, at most 1,500. | - `minimum 0`<br>- `maximum 1500` |
| `truncated` | boolean |  | True when Chat left something out because of the ten-item or 1,500-character cap. |  |

## Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

 Valid: empty

~~~~
{
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "since": null,
  "until": "2026-11-06T10:05:00.000Z",
  "chars": 0,
  "truncated": false,
  "items": []
}
~~~~

Valid: full

~~~~
{
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "since": "2026-11-06T10:00:00.000Z",
  "until": "2026-11-06T10:05:00.000Z",
  "chars": 120,
  "truncated": false,
  "items": [
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "why is the test flaky?",
      "kind": "question",
      "upvotes": 3
    },
    {
      "who": {
        "display_name": "Sam",
        "handle": "sam"
      },
      "what": "a link to github.com",
      "kind": "suggestion",
      "upvotes": 2,
      "repeated": 2
    }
  ]
}
~~~~

Rejected: eleven-items

~~~~
{
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "since": null,
  "until": "2026-11-06T10:05:00.000Z",
  "items": [
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    },
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "reaction",
      "upvotes": 0
    }
  ]
}
~~~~

Rejected: room-not-an-agent-room

~~~~
{
  "room": "chat:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "since": null,
  "until": "2026-11-06T10:05:00.000Z",
  "items": []
}
~~~~

Rejected: unknown-kind

~~~~
{
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "since": null,
  "until": "2026-11-06T10:05:00.000Z",
  "items": [
    {
      "who": {
        "display_name": "Mira",
        "handle": "mira"
      },
      "what": "hi",
      "kind": "greeting",
      "upvotes": 0
    }
  ]
}
~~~~

## Validate

~~~~
const contracts = require('openvibe-contracts');
contracts.validate('chat.agent-digest@1', value);   // { valid, errors: [{ path, message }] }
~~~~
