List
The list plugin shows a set of items, grouped under headings, and asks for a verdict on each: accept or reject, with an optional note. It is the general-purpose plugin, and the one to reach for first. It comes with the app, and the setup installs it.
When to use it
Section titled “When to use it”- Triage. Errors, alerts or tickets the agent proposes to mute, fix, close or escalate.
- A plan. The steps an agent is about to take, so you can strike the ones you don’t want before it starts.
- Findings. Security or dependency audit results, lint findings, flaky tests to quarantine.
- Batch changes. Records to update, files to delete, branches to prune, invitations to send.
If the items need a richer view, such as a diff for each, look at Code review or build a plugin.
What you see
Section titled “What you see”- A summary from the agent, when it gives one, in a box you can fold away.
- Groups with their headings, and each item’s title, description and details.
- Severity, when the agent gives one.
blocker,major,minorandnithave colours of their own, and the agent can give other severities a colour too; anything else shows in grey. - A sidebar with each group’s items. An item’s circle fills once you accept it, and a rejected item is struck through. Click an item to go to it.
- Accept or Reject on each item, with a note. On an accepted item the note is a revision instruction; on a rejected one, the reason.
- Earlier verdicts. When the review is a new round, each item shows the verdict you gave it last time.
Anything you leave undecided is reported as undecided. When you hand over with items left, the list asks you to confirm first, and the hand-over button says how many go back undecided.
To see it before any agent asks with it, send its sample: pinrail submit list --sample, or Send a sample in its details in Settings › Plugins.
Asking from your agent
Section titled “Asking from your agent”Paste this into your agent’s instructions and adjust the first line to the moment you want it to ask:
## Before acting on a batch of changes
Before you close, mute or change more than one item, ask me with Pinrail's`list` plugin and wait for my decision:
1. Write the items to a JSON file: `{ "summary": "…", "groups": [{ "title": "…", "items": [{ "id": 1, "severity": "major", "title": "…", "body": "…" }] }] }`. Give each item a stable integer `id` and say in `body` what you will do.2. Run: `pinrail submit list --title "<what this is>" --data items.json --wait`3. Act only on items marked accepted, applying any note as an instruction. Rejected and undecided items are not approved: leave them.4. If the command exits 5, the review was discarded: stop and tell me why.See Instructing an agent for where these instructions go for each agent.
What the agent sends
Section titled “What the agent sends”{ "summary": "Sentry triage for **acme-api**, last 7 days.", "groups": [ { "title": "Mute", "items": [ { "id": 101, "severity": "minor", "title": "Mute NullPointer in /checkout for 7 days", "body": "Fires 40 times an hour since the 3.2 deploy; the fix is in review.", "meta": { "events": "1.2k" } } ] }, { "title": "Open an issue", "items": [ { "id": 103, "severity": "major", "title": "Timeout on /export past 50k rows", "body": "Nine users hit it this week. The query has no index on `exported_at`." } ] } ]}| Field | Meaning |
|---|---|
summary | Markdown shown above the list, in a box the person can fold away. Optional. |
groups[].title | The heading items are grouped under. |
items[].id | The agent’s own integer. Never renumbered, so verdicts from one round match the next. |
severities | The colour each severity this payload uses is shown in, such as { "critical": "danger", "low": "info" }. The colours are danger, warning, info, success and neutral. Optional. |
items[].severity | Free text. blocker, major, minor and nit have colours of their own, which severities can change. Any other severity is grey unless severities names it. |
items[].title, items[].body | What the item is. body is markdown. |
items[].meta | Extra details, shown as key: value chips. Each value is a string, a number or a boolean. |
What comes back
Section titled “What comes back”{ "decisions": [ { "id": 101, "action": "accept", "note": "mute it for 3 days, not 7" }, { "id": 103, "action": "reject", "note": "known, already scheduled" } ], "undecided": []}decisionshas one entry per item with a verdict.noteis a revision instruction onacceptand the reason onreject.undecidedlists every item left without a verdict. Treat those as not approved.
In Markdown, which is the default, the agent reads the same decision under each group’s heading: every item with its verdict and title, the person’s note below it, and the items without a verdict marked as not approved.
Reference
Section titled “Reference”The plugin’s manifest, and the schemas a payload and a decision are checked against, read from the plugin’s own files.
name | list |
|---|---|
version | 1.0.0 |
title | Action list |
description | Items grouped under headings, each accepted or rejected with an optional note. |
use_when | You have a list of findings, proposed changes or tasks and need a person to accept or reject each one before you act on them. |
{ "name": "list", "version": "1.0.0", "title": "Action list", "description": "Items grouped under headings, each accepted or rejected with an optional note.", "use_when": "You have a list of findings, proposed changes or tasks and need a person to accept or reject each one before you act on them.", "summary": { "request": { "counts": [ { "items": "/groups/*/items", "by": "severity", "values": { "blocker": { "tone": "danger" }, "major": { "tone": "warning" }, "minor": { "tone": "info" }, "nit": { "tone": "neutral" } } } ] }, "outcome": { "counts": [ { "items": "/decisions", "by": "action", "values": { "accept": { "label": "accepted", "tone": "success" }, "reject": { "label": "rejected", "tone": "danger" } }, "other": false }, { "items": "/undecided", "label": "undecided" } ] } }}- summarystring
markdown shown above the list, in a box the person can fold away
- severitiesobject
the tone each severity this payload uses is shown in, by name, over the built-in blocker, major, minor and nit; a severity named nowhere is neutral
groupsobject[]required
- titlestringrequired
itemsobject[]required
- idintegerrequired
the workflow's own id; never renumbered
- severitystring
- titlestringrequired
- bodystring
markdown
- metaobject
shown as key: value chips
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "list payload", "type": "object", "required": [ "groups" ], "additionalProperties": false, "properties": { "summary": { "type": "string", "description": "markdown shown above the list, in a box the person can fold away" }, "severities": { "type": "object", "description": "the tone each severity this payload uses is shown in, by name, over the built-in blocker, major, minor and nit; a severity named nowhere is neutral", "additionalProperties": { "enum": [ "danger", "warning", "info", "success", "neutral" ] } }, "groups": { "type": "array", "items": { "type": "object", "required": [ "title", "items" ], "additionalProperties": false, "properties": { "title": { "type": "string" }, "items": { "type": "array", "items": { "type": "object", "required": [ "id", "title" ], "additionalProperties": false, "properties": { "id": { "type": "integer", "description": "the workflow's own id; never renumbered" }, "severity": { "type": "string" }, "title": { "type": "string" }, "body": { "type": "string", "description": "markdown" }, "meta": { "type": "object", "description": "shown as key: value chips", "additionalProperties": { "type": [ "string", "number", "boolean" ] } } } } } } } } }}decisionsobject[]required
- idintegerrequired
- actionenumrequired
"accept""reject" - notestring
accept+note = revise before acting; reject+note = the reason
- undecidedinteger[]required
item ids the person left without a decision; the view computes this, the requester must treat it as not approved
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "list decision", "type": "object", "required": [ "decisions", "undecided" ], "additionalProperties": false, "properties": { "decisions": { "type": "array", "items": { "type": "object", "required": [ "id", "action" ], "additionalProperties": false, "properties": { "id": { "type": "integer" }, "action": { "enum": [ "accept", "reject" ] }, "note": { "type": "string", "description": "accept+note = revise before acting; reject+note = the reason" } } } }, "undecided": { "type": "array", "items": { "type": "integer" }, "description": "item ids the person left without a decision; the view computes this, the requester must treat it as not approved" } }}