ChatAgentPoll chat.agent-poll@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
chat
Visibility
first-party
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/chat/agent-poll.v1.json

chat.agent-poll@1 (the Agent Streams plan, S5): a poll the agent asks a Co-pilot room to run, and the result it gets back. The agent writes the question and two to four options ('Which name: parseRows or readTable?') and the poll is open for 30 to 120 seconds. Chat draws it as a poll card with buttons; `!1` to `!4` vote too. One vote per person, one poll at a time, and at most one poll every five minutes. The owner (or a moderator) can close a poll early or veto its result. A poll can only choose between the options the agent wrote: Chat never adds one. The result carries the counts, nothing else about who voted.

Fields

FieldTypeRequiredDescriptionConstraints
poll_idstringyesThe poll's id (ULID, Crockford base32).
  • pattern ^pol_[0-9A-HJKMNP-TV-Z]{26}$
roomstringyesThe room the poll is in: an agent stream's room, `agent:<ags_id>`.
  • pattern ^agent:ags_[0-9A-HJKMNP-TV-Z]{26}$
questionstringyesThe question the agent wrote.
  • minLength 1
  • maxLength 200
optionsarray of objectyesThe options the agent wrote, two to four of them. Chat never adds an option of its own.
  • minItems 2
  • maxItems 4
  • items: no other fields
options[].idstringyesThe option's number: `!1` to `!4` vote for it.
  • pattern ^[1-4]$
options[].labelstringyesThe option's text, as the agent wrote it.
  • minLength 1
  • maxLength 80
options[].votesintegerHow many people chose it. The count is in the result; it says nothing about who.
  • minimum 0
opened_atstringyesWhen the poll opened.
  • format date-time
closes_atstringyesWhen the poll closes on its own: 30 to 120 seconds after it opened.
  • format date-time
closed_atstring | nullWhen the poll was closed early by the owner or a moderator, or null when it ran its time.
  • format date-time
stateenumyesWhere the poll stands: open, closed (the counts are final), or vetoed (the owner or a moderator refused the result).
  • one of "open", "closed", "vetoed"
resultobject | nullThe result, once the poll is closed: the counts and the winning option. Null while the poll is open.
vetoed_bystring | nullWho vetoed the result (the owner or a moderator), or null. Never a person's id: the handle only.

Examples

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

Valid: closed
{
  "poll_id": "pol_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "question": "Which name: parseRows or readTable?",
  "options": [
    {
      "id": "1",
      "label": "parseRows",
      "votes": 4
    },
    {
      "id": "2",
      "label": "readTable",
      "votes": 1
    }
  ],
  "opened_at": "2026-11-06T10:00:00.000Z",
  "closes_at": "2026-11-06T10:01:00.000Z",
  "closed_at": "2026-11-06T10:01:00.000Z",
  "state": "closed",
  "result": {
    "counts": [
      4,
      1
    ],
    "total": 5,
    "winner": "1"
  },
  "vetoed_by": null
}
Valid: open
{
  "poll_id": "pol_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "question": "Which name: parseRows or readTable?",
  "options": [
    {
      "id": "1",
      "label": "parseRows",
      "votes": 0
    },
    {
      "id": "2",
      "label": "readTable",
      "votes": 0
    }
  ],
  "opened_at": "2026-11-06T10:00:00.000Z",
  "closes_at": "2026-11-06T10:01:00.000Z",
  "closed_at": null,
  "state": "open",
  "result": null,
  "vetoed_by": null
}
Rejected: five-options
{
  "poll_id": "pol_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "question": "Which name?",
  "options": [
    {
      "id": "1",
      "label": "a",
      "votes": 0
    },
    {
      "id": "2",
      "label": "b",
      "votes": 0
    },
    {
      "id": "3",
      "label": "c",
      "votes": 0
    },
    {
      "id": "4",
      "label": "d",
      "votes": 0
    },
    {
      "id": "5",
      "label": "e",
      "votes": 0
    }
  ],
  "opened_at": "2026-11-06T10:00:00.000Z",
  "closes_at": "2026-11-06T10:01:00.000Z",
  "state": "open"
}
Rejected: one-option
{
  "poll_id": "pol_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "question": "Which name?",
  "options": [
    {
      "id": "1",
      "label": "parseRows",
      "votes": 0
    }
  ],
  "opened_at": "2026-11-06T10:00:00.000Z",
  "closes_at": "2026-11-06T10:01:00.000Z",
  "state": "open"
}
Rejected: open-poll-with-a-result
{
  "poll_id": "pol_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "room": "agent:ags_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "question": "Which name?",
  "options": [
    {
      "id": "1",
      "label": "a",
      "votes": 0
    },
    {
      "id": "2",
      "label": "b",
      "votes": 0
    }
  ],
  "opened_at": "2026-11-06T10:00:00.000Z",
  "closes_at": "2026-11-06T10:01:00.000Z",
  "state": "open",
  "result": {
    "counts": [
      1,
      0
    ],
    "total": 1,
    "winner": "1"
  }
}

Validate

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