The Question Protocol Data Model
The technical shape of a PingRoom Question: asker, responder, options, state, expiry, answer, and structured context.
The Question primitive is the general form of human-in-the-loop decision-making in PingRoom.
Approvals are the two-option case. A Question is broader: an asker sends a prompt with two to four predefined options, a human answers with one tap, and the answer returns to the asker with structured context.
This post describes the data model as a protocol shape.
The Object
A Question should include:
{
"id": "q_123",
"room": {
"id": "room_123",
"invite_code": "ABCD12",
"name": "Deploys"
},
"asker": {
"type": "agent",
"id": "agent_123",
"handle": "release-bot",
"display_name": "Release Bot"
},
"prompt": "Which environment should I deploy to?",
"context": "Commit abc123 passed CI",
"options": [
{ "value": "prod", "label": "Production", "style": "primary" },
{ "value": "staging", "label": "Staging" },
{ "value": "cancel", "label": "Cancel", "style": "cancel" }
],
"responder_scope": {
"type": "direct",
"user_id": "user_123"
},
"resolution_policy": "first",
"expires_at": "2026-06-17T18:30:00Z",
"state": "pending",
"answer": null,
"correlation_id": "deploy-abc123",
"reply_to": "workflow:release",
"data": {
"commit": "abc123",
"pipeline_id": "998812"
}
}
The exact ids and casing can follow the implementation, but the concepts should stay stable.

Prompt And Context
The prompt is what the human answers.
It should be short, direct, and decision-shaped. "Deploy production now?" is better than "Build notification." The optional context line explains why the question exists without crowding the prompt.
The protocol should cap both fields consistently with notification and in-app display limits.
Options
Options have two identities:
value is for machines. It must be stable, short, unique within the question, and round-trip exactly.
label is for humans. It should fit inside a notification action or button.
Two options are the fast path. Three or four are supported for real choice, but they may require expanded notification UI or an in-app answer sheet.
Responder Scope
Responder scope defines who can answer.
direct means one named person is the target. The UI can say the asker "asks you." Only that user may answer.
room means any eligible member in the room can answer. The UI can say the asker "asks the room." In v1, the resolution policy should be first: the first valid answer wins.
This scope is not just copy. It is server authorization.
State And Answer
The state machine has four states:
pending
answered
expired
cancelled
When answered, the answer object should include the chosen option value and label, responder identity, and timestamp:
{
"value": "prod",
"label": "Production",
"responder": {
"id": "user_123",
"display_name": "Mahdi"
},
"answered_at": "2026-06-17T18:21:11Z"
}
Expired and cancelled Questions should return the same envelope with no chosen option and a clear terminal reason.
Structured Context
data, correlation_id, and reply_to follow the structured-Ping model.
They let the asker match the answer to an outside workflow without making the human read machine state. That is the whole point of the protocol: human-readable prompt, machine-readable result.
The Design Rule
The data model should be boring, stable, and additive.
Question is not a place for clever naming. It is a contract agents and SDKs will depend on. The strongest protocol is the one a developer can guess correctly after reading it once.
Mahdi Salmanzade
The Ping that cuts through.


