dev.agentpod.permission.v2
A harness permission prompt in AgentPod’s decision envelope, on the station room’s prose message beside the v1 card: options with what they mean and how far they reach, and a harness-permission/v1 subject whose preview shows what the agent would do. 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.agentpod.permission.v2".
Who sends it, who reads it
Section titled “Who sends it, who reads it”- Sent by AgentPod.
- Read by SuperMessage.
Fields
Section titled “Fields”| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
msgtype |
"m.text" |
no | ||
body |
string | no | ||
suite_event_type |
"dev.agentpod.permission.v2" |
yes | ||
schema_version |
integer | yes | at least 1 | |
request_id |
string | yes | at least 1 character | |
session_id |
string | yes | at least 1 character | |
request_seq |
integer | yes | at least 0 | |
title |
string | yes | ||
tool_kind |
string | no | at least 1 character | |
options |
array of object | yes | at least 1 item; 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", "choose" |
yes | ||
options[].scope |
one of "once", "always" |
no | ||
subject |
yes |
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 command, with all four ACP option kinds”:
{ "msgtype": "m.text", "body": "Permission needed: Run the test suite\n\n1. Allow once\n2. Always allow\n3. Reject\n4. Never allow\n\nReply with the number, or the option's name.", "suite_event_type": "dev.agentpod.permission.v2", "schema_version": 1, "request_id": "acps_3f0c:12", "session_id": "acps_3f0c", "request_seq": 12, "title": "Run the test suite", "tool_kind": "execute", "options": [ { "id": "allow_once", "label": "Allow once", "meaning": "approve", "scope": "once" }, { "id": "allow_always", "label": "Always allow", "meaning": "approve", "scope": "always" }, { "id": "reject_once", "label": "Reject", "meaning": "reject", "scope": "once" }, { "id": "reject_always", "label": "Never allow", "meaning": "reject", "scope": "always" } ], "subject": { "id": "acps_3f0c:12", "digest": "bb03bfd8ee6d757e6957d029cd6a7b8e004f16386755ce672e3f97f445563878", "schema": "harness-permission/v1", "revision": 1, "expires_at": "2026-11-07T10:30:00.000Z", "preview": [ { "type": "field", "label": "Tool", "value": "Run the test suite" }, { "type": "field", "label": "Kind", "value": "execute" }, { "type": "text", "label": "Command", "text": "bun test" }, { "type": "field", "label": "Location", "value": "apps/hub" } ], "preview_complete": true }, "dev.agentpod.permission": { "schema_version": 1, "session_id": "acps_3f0c", "request_seq": 12, "title": "Run the test suite", "options": [ { "option_id": "allow_once", "name": "Allow once" }, { "option_id": "allow_always", "name": "Always allow" }, { "option_id": "reject_once", "name": "Reject" }, { "option_id": "reject_always", "name": "Never allow" } ] }}The corpus has 2 valid cases in all:
built: a harness asks to run a command
{ "msgtype": "m.text", "body": "The agent wants to run a command.", "suite_event_type": "dev.agentpod.permission.v2", "schema_version": 1, "request_id": "acps_1:4", "session_id": "acps_1", "request_seq": 4, "title": "Run bun test", "tool_kind": "execute", "options": [ { "id": "allow", "label": "Allow once", "meaning": "approve", "scope": "once" }, { "id": "reject", "label": "Reject", "meaning": "reject", "scope": "once" } ], "subject": { "id": "acps_1:4", "digest": "c0ffee", "schema": "harness-permission/v1", "revision": 1, "expires_at": "2030-01-01T09:30:00.000Z", "preview": [ { "type": "text", "label": "Command", "text": "bun test" } ], "preview_complete": true }}Refused
Section titled “Refused”Each of these must fail. The corpus says why:
- an option with no meaning (refused by
schema) - a subject of another schema (refused by
schema) - no request_id: nothing an answer can name (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) - twenty-one options: more than any decision card carries (refused by
schema)
Source
Section titled “Source”- Schema:
schemas/matrix/dev.agentpod.permission.v2.json - In the package:
import schema from "@superjackfruitlabs/treaty-matrix-events/schemas/dev.agentpod.permission.v2.json" with { type: "json" };