dev.superpipeline.question.v2
An agent’s question in the decision envelope, beside the v1 card. Options say what they mean and may ask for input; a question with no options carries free_text. A strict decision or a board-dispatched harness permission carries its subject; a SuperToolkit approval request carries approval_request_id and belongs to no card, run or stage. Readers ignore properties they do not know. x-uniqueBy lists paths whose values must not repeat (JSON Schema cannot say so): a[].b is field b of each item of list a.
How it rides
Section titled “How it rides”An m.room.message whose content carries suite_event_type: "dev.superpipeline.question.v2".
Who sends it, who reads it
Section titled “Who sends it, who reads it”- Sent by AgentPod, SuperExchange.
- Read by SuperMessage.
The carrier is whichever service carries the board’s chat: AgentPod’s hub, or SuperExchange for a board that has moved to it.
Fields
Section titled “Fields”| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
msgtype |
"m.text" |
yes | ||
body |
string | yes | ||
suite_event_type |
"dev.superpipeline.question.v2" |
yes | ||
schema_version |
integer | yes | at least 1 | |
elicitation_id |
string | yes | at least 1 character | |
board_id |
string | yes | ||
card_id |
string | yes | ||
run_id |
string | yes | ||
stage_key |
string | yes | ||
card_title |
string | yes | ||
asked_by |
string | yes | ||
question |
string | yes | ||
options |
array of object | yes | at most 20 items | |
options[].id |
string | yes | at least 1 character; at most 200 characters | |
options[].label |
string | yes | at most 200 characters | |
options[].meaning |
one of "approve", "reject", "revise", "choose", "defer" |
yes | ||
options[].needs_comment |
boolean | yes | ||
options[].input |
object | no | ||
options[].input.kind |
one of "text", "url" |
yes | ||
options[].input.label |
string | yes | at most 200 characters | |
options[].input.required |
boolean | yes | ||
options[].input.max_length |
integer | yes | at least 1; at most 4000 | |
options[].scope |
one of "once", "run", "always" |
no | ||
options[].requires |
one of "workspace-admin" |
no | ||
free_text |
object | no | ||
free_text.max_length |
integer | yes | at least 1; at most 2000 | |
subject |
object | no | The exact thing an approving answer approves, re-bounded by the carrier. The sender still lists approving options when preview_complete is false; a client must not offer them, and the carrier refuses an approving answer to an incomplete preview. | |
subject.id |
string | yes | at least 1 character; at most 512 characters | |
subject.digest |
string | yes | at least 1 character; at most 512 characters | |
subject.schema |
string | yes | at least 1 character; at most 200 characters | |
subject.revision |
integer | yes | at least 0 | |
subject.expires_at |
string or null | yes | When the binding lapses: an RFC 3339 date-time with seconds and an explicit offset (2030-01-02T03:04:05Z, 2030-01-02T08:34:05.5+05:30), or null for none. The pattern states it for a validator that does not assert format. | format date-time; pattern ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$; at most 200 characters |
subject.preview |
array of object (type = “text”) or object (type = “field”) or object (type = “link”) | yes | at most 20 items | |
subject.preview[].type |
"text" |
yes | in the type = "text" shape |
|
subject.preview[].label |
string | no | in the type = "text" shape; at most 200 characters |
|
subject.preview[].text |
string | yes | in the type = "text" shape; at most 4000 characters |
|
subject.preview[].type |
"field" |
yes | in the type = "field" shape |
|
subject.preview[].label |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.preview[].value |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.preview[].type |
"link" |
yes | in the type = "link" shape |
|
subject.preview[].label |
string | yes | in the type = "link" shape; at most 200 characters |
|
subject.preview[].url |
string | yes | in the type = "link" shape; pattern ^https?://[^\s<>]+$; at most 4000 characters |
|
subject.preview_complete |
boolean | yes | ||
approval_request_id |
string | no | at least 1 character | |
deadline |
object | no | ||
deadline.remind_at |
string | no | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
deadline.escalate_at |
string | no | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
deep_link |
string | no |
The schema also states these rules across fields, as written:
{ "allOf": [ { "description": "free_text only on a question with no options: text alone answers only a question with nothing to choose. Without free_text, there is at least one option to answer with.", "if": { "required": [ "free_text" ] }, "then": { "properties": { "options": { "maxItems": 0 } } }, "else": { "properties": { "options": { "minItems": 1 } } } }, { "description": "A SuperToolkit approval request belongs to no card: it names its request, links nowhere, is bound to an stk-capability/v1 subject, and only a workspace owner or admin may approve it.", "if": { "required": [ "card_id" ], "properties": { "card_id": { "const": "" } } }, "then": { "required": [ "approval_request_id" ], "not": { "required": [ "deep_link" ] }, "properties": { "subject": { "properties": { "schema": { "const": "stk-capability/v1" } } }, "options": { "items": { "if": { "required": [ "meaning" ], "properties": { "meaning": { "const": "approve" } } }, "then": { "required": [ "requires" ], "properties": { "requires": { "const": "workspace-admin" } } } } } } } } ]}x-uniqueBy: the values at these paths must not repeat, the one rule JSON Schema cannot state. a[].b is field b of each item of list a.
options[].id
Example
Section titled “Example”From fixtures/matrix-events/examples.json, case “a question with options, one of which asks for text”:
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Upgrade the build image\" at stage `build`.\n\nThe tests need network access. May I run them?\n\n1. Run the tests\n2. Skip them\n3. Something else\n\nReply with the number, or the option's name. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_51d0)", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_7f3c", "board_id": "brd_7c1f", "card_id": "crd_51d0", "run_id": "run_12", "stage_key": "build", "card_title": "Upgrade the build image", "asked_by": "agt_31d0", "question": "The tests need network access. May I run them?", "options": [ { "id": "run_them", "label": "Run the tests", "meaning": "choose", "needs_comment": false }, { "id": "skip", "label": "Skip them", "meaning": "choose", "needs_comment": false }, { "id": "other", "label": "Something else", "meaning": "choose", "needs_comment": false, "input": { "kind": "text", "label": "What should I do instead?", "required": true, "max_length": 500 } } ], "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_51d0"}The corpus has 8 valid cases in all:
a question with no options, answered by typing
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Upgrade the build image\" at stage `build`.\n\nWhich branch should I base the fix on?\n\nAnswer this one on the board. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_51d0)", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_8a21", "board_id": "brd_7c1f", "card_id": "crd_51d0", "run_id": "run_12", "stage_key": "build", "card_title": "Upgrade the build image", "asked_by": "agt_31d0", "question": "Which branch should I base the fix on?", "options": [], "free_text": { "max_length": 2000 }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_51d0"}subject-bound: a strict decision with a complete preview
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Upgrade the build image\" at stage `build`.\n\nEdit app.js in the workspace?\n\n1. Approve\n2. Approve for this run\n3. Always allow\n4. Deny\n\nReply with the number, or the option's name. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_51d0)\n\nThis approves an exact operation. Approve it in an updated app, which shows what it does, or on the board. A reply here can only decline it.", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_9b44", "board_id": "brd_7c1f", "card_id": "crd_51d0", "run_id": "run_12", "stage_key": "build", "card_title": "Upgrade the build image", "asked_by": "agt_31d0", "question": "Edit app.js in the workspace?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false, "scope": "once" }, { "id": "approve-run", "label": "Approve for this run", "meaning": "approve", "needs_comment": false, "scope": "run" }, { "id": "always", "label": "Always allow", "meaning": "approve", "needs_comment": false, "scope": "always", "requires": "workspace-admin" }, { "id": "deny", "label": "Deny", "meaning": "reject", "needs_comment": false, "scope": "once" } ], "subject": { "id": "8f9a0d0e-4b2a-4c1e-9c55-1a2b3c4d5e6f", "digest": "0588c96c7eff47e1a83d9fc1d0ecda3cc3b72e559a5c402bb9da29d9851dbceb", "schema": "salaam-operation/v1", "revision": 1, "expires_at": "2026-11-07T10:30:00.000Z", "preview": [ { "type": "text", "text": "Edit app.js in the workspace" }, { "type": "field", "label": "File", "value": "app.js · edit · 16 bytes" }, { "type": "text", "text": "console.log(1);\n" } ], "preview_complete": true }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_51d0"}approval-request: an issues.create request with its preview complete
{ "msgtype": "m.text", "body": "A SuperToolkit approval request is waiting on a workspace owner or admin.\n\nAllow github issues.create on acme/site?\n\nService: github\n\nCapability: issues.create\n\nTarget: acme/site\n\nArguments:\n```\n{\n \"title\": \"Flaky login test\",\n \"labels\": [\"ci\"]\n}\n```\n\nStation: station-7\n\nRequested by: prn_agent_31d0\n\n1. Allow once\n2. Deny\n\nOnly workspace owners and admins can allow this. Allow it in an updated app, which shows exactly what it does. A reply here can only deny it.", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "apr_5d2e9c41", "board_id": "brd_7c1f", "card_id": "", "run_id": "", "stage_key": "", "card_title": "Approval request", "asked_by": "prn_agent_31d0", "question": "Allow github issues.create on acme/site?", "options": [ { "id": "allow_once", "label": "Allow once", "meaning": "approve", "needs_comment": false, "scope": "once", "requires": "workspace-admin" }, { "id": "deny", "label": "Deny", "meaning": "reject", "needs_comment": false, "scope": "once" } ], "subject": { "id": "stkreq_8f2c", "digest": "sha256:4be1c0de9a7f30b2", "schema": "stk-capability/v1", "revision": 1, "expires_at": "2026-11-08T10:30:00.000Z", "preview": [ { "type": "field", "label": "Service", "value": "github" }, { "type": "field", "label": "Capability", "value": "issues.create" }, { "type": "field", "label": "Target", "value": "acme/site" }, { "type": "text", "label": "Arguments", "text": "{\n \"title\": \"Flaky login test\",\n \"labels\": [\"ci\"]\n}" }, { "type": "field", "label": "Station", "value": "station-7" }, { "type": "field", "label": "Requested by", "value": "prn_agent_31d0" } ], "preview_complete": true }, "approval_request_id": "apr_5d2e9c41"}deadline: a question that only escalates
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Launch post\" at stage `draft`.\n\nWhich headline?\n\n1. Ship it today\n2. Ship it Monday\n\nReply with the number, or the option's name. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_5d21", "board_id": "brd_7c1f", "card_id": "crd_6b40", "run_id": "run_e074a2160c4b4f28", "stage_key": "draft", "card_title": "Launch post", "asked_by": "agt_31d0", "question": "Which headline?", "options": [ { "id": "a", "label": "Ship it today", "meaning": "choose", "needs_comment": false }, { "id": "b", "label": "Ship it Monday", "meaning": "choose", "needs_comment": false } ], "deadline": { "escalate_at": "2026-11-08T18:00:00.000Z" }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a question with two options
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Upgrade the build image\" at stage `build`.\n\nThe tests need network access. May I run them?\n\n1. Run the tests\n2. Skip them\n\nReply with the number, or the option's name. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_7f3c", "board_id": "brd_7c1f", "card_id": "crd_51d0", "run_id": "run_12", "stage_key": "build", "card_title": "Upgrade the build image", "asked_by": "agt_31d0", "question": "The tests need network access. May I run them?", "options": [ { "id": "run_them", "label": "Run the tests", "meaning": "choose", "needs_comment": false }, { "id": "skip", "label": "Skip them", "meaning": "choose", "needs_comment": false } ], "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a question answered by typing
{ "msgtype": "m.text", "body": "An agent is waiting on you — \"Upgrade the build image\" at stage `build`.\n\nThe tests need network access. May I run them?\n\nAnswer this one on the board. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "elc_7f3c", "board_id": "brd_7c1f", "card_id": "crd_51d0", "run_id": "run_12", "stage_key": "build", "card_title": "Upgrade the build image", "asked_by": "agt_31d0", "question": "The tests need network access. May I run them?", "options": [], "free_text": { "max_length": 500 }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a SuperToolkit approval request
{ "msgtype": "m.text", "body": "A SuperToolkit approval request is waiting on a workspace owner or admin.\n\nAllow github issues.create on acme/site?\n\nPost:\n```\nOur next release ships today.\n```\n\nAccount: @fixture_account on X\n\n1. Allow once\n2. Deny\n\nOnly workspace owners and admins can allow this. Allow it in an updated app, which shows exactly what it does. A reply here can only deny it.", "suite_event_type": "dev.superpipeline.question.v2", "schema_version": 1, "elicitation_id": "apr_5d2e9c41", "board_id": "brd_7c1f", "card_id": "", "run_id": "", "stage_key": "", "card_title": "Approval request", "asked_by": "agt_31d0", "question": "Allow github issues.create on acme/site?", "options": [ { "id": "allow_once", "label": "Allow once", "meaning": "approve", "needs_comment": false, "scope": "once", "requires": "workspace-admin" }, { "id": "deny", "label": "Deny", "meaning": "reject", "needs_comment": false, "scope": "once" } ], "subject": { "id": "stkreq_8f2c", "digest": "sha256:9a1e", "schema": "stk-capability/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" } ], "preview_complete": true }, "approval_request_id": "apr_5d2e9c41"}Refused
Section titled “Refused”Each of these must fail. The corpus says why:
- an option with no meaning. A sender must say what each option means. (refused by
schema) - camelCase on the Matrix wire.
maxLengthis the board’s push field; the Matrix field ismax_length. (refused byschema) - duplicate option ids. Answering is by id. (refused by
unique) - free_text beside options. Text alone answers only a question with nothing to choose. (refused by
schema) - no body. A stock client would show nothing. (refused by
schema) - subject-bound: the subject in camelCase. The Matrix wire is snake_case. (refused by
schema) - subject-bound: an option scope outside once | run | always (refused by
schema) - subject-bound: a subject with no digest: nothing to bind an answer to (refused by
schema) - approval-request: a deep link to a card that does not exist (refused by
schema) - approval-request: no approval_request_id (refused by
schema) - approval-request: allow_once without requires: workspace-admin (refused by
schema) - approval-request: a subject of another schema (refused by
schema) - a subject revision that is not a whole number (refused by
schema) - an expiry that is a date only (refused by
schema) - an expiry written as a person would (refused by
schema) - an expiry with no offset (refused by
schema) - an expiry with no seconds (refused by
schema) - an expiry with a space for the T (refused by
schema) - an expiry whose offset has no colon (refused by
schema) - an expiry in lower case (refused by
schema) - an expiry on a day the month does not have (refused by
schema) - no options: nothing to answer with (refused by
schema)
Source
Section titled “Source”- Schema:
schemas/matrix/dev.superpipeline.question.v2.json - In the package:
import schema from "@superjackfruitlabs/treaty-matrix-events/schemas/dev.superpipeline.question.v2.json" with { type: "json" };