Artifact 2434f4b93e2cc399162e6ebd66fe19e7eca9c89aa36d1f7159557832fec216ad:
- File docs/rfcs/0028-requests.md — part of check-in [a1e365cf5b] at 2026-11-09 00:48:28 on branch rfc-0028-requests — RFC 0028: Requests, plain actions, one email a burst, and plans (user: dmestas, size: 6443) [annotate] [blame] [check-ins using] [more...]
- Feature Name:
requests(an agent's requests to its person get a place of their own, read as plain actions, and a whole job can be asked for as one plan) - Start Date: 2026-11-08
- Status: Draft. Decisions settled by the owner on 2026-11-08 (see Decisions); options weighed on the design page "Sign-off Design" (A, B and C).
- Depends on: RFC 0027 (ask your person: the request, its approval, its answer and secrets)
- Amends: RFC 0027 Answering
(where requests are read and how the person is told), and the
sign-off section of
/me, which this replaces.
Summary
Requests leave the account page. They live at /me/requests, counted
in the header beside the inbox, waiting ones first and answered in
place; everything decided folds into History. Each request reads as the
action it takes ("Create agent rajeev"), not the op that runs it. A
burst from one agent is one email. And an agent may ask for a plan:
several calls under one title, approved with one tap, run in order as
the person, stopping at the first that fails.
Motivation
RFC 0027 shipped on 2026-11-08 and was used the same evening to set up
a QA agent. Four calls were needed (an agent, its token, a role, a
handover), so four cards, four emails and four approvals, named
agent.new for rajeev and agent.token.new for rajeev, in an order only
the agent knew, in a section between Password and Access that also kept
a four-day-old decided request beside them. The owner: "this will get
unmanageable fast".
Design
Where requests live
/me/requests, reached from a Requests entry in the header with a
count of waiting requests (hidden at zero, as the inbox's is). Two tabs:
Waiting, newest first, each row with Approve and Deny posted in
place; History, everything decided or expired, newest first, with a
filter by agent. The section on /me goes; /me/signoffs/{id} stays as
the one request's page and redirects from the list where needed.
Approving from a row needs the session, as now.
Requests read as actions
Each op may declare an Ask sentence, a template over its input:
agent.new reads "Create agent {name}", agent.token.new "Mint a token
for {agent} ({scopes}, {days} days)", agent.grant "Give {agent} {role}
on {repo}", repo.claim "Hand {repo} to {account}". An op with none
reads as its name and the account and repository it names, as today.
The sentence uses only fields an op marks safe to show; a field holding
a credential never appears.
From an email
Every button in a request's email opens exactly that request: its own
page, /me/requests/{id} (a plan's page for a plan), with Approve and
Deny on it, never the list (decision 6). The button itself cannot
approve: a mail scanner opens every link in a message, so a link that
acted on a GET would approve requests nobody read. Approval is the one
tap on the page the button opens. Signed out, the button goes through
sign-in and returns to that same request (/login?next=, as now). A
burst's email lists each request with its own button to its own page.
One email for a burst
The first request from an agent is told at once (inbox, push, email). Requests from the same agent within the next five minutes are added to the waiting list and the inbox but not emailed separately; at the end of the window one email lists everything still waiting, each with its link, and a link to the Waiting tab. A plan is one request and one email.
Plans
An agent asks for a plan with POST /api/v1/requests:
{"title": "Set up Rajeev as QA tester",
"reason": "Rajeev owns dantest-sandbox and tests the forge from outside",
"steps": [
{"op": "agent.new", "input": {"name": "rajeev"}},
{"op": "agent.token.new", "input": {"agent": "rajeev", "name": "qa", "scopes": "api,web,sync", "days": 365}},
{"op": "agent.grant", "input": {"agent": "rajeev", "repo": "dantest-sandbox", "role": "admin"}},
{"op": "repo.claim", "input": {"repo": "dantest-sandbox", "account": "rajeev"}}
]}
At most 20 steps. Each step must be askable and inside the agent's scope on its own, by RFC 0027's rules, or the plan is refused whole with the step that fails named. A plan is one request: one row, one email, one Approve.
Approval runs the steps in order, each as the person, through the
ordinary registry, each checked against the person's permissions as it
runs. The first that fails stops the plan: earlier steps stand (they
were each the person's act, and journalled as such), later ones do not
run, and the request reads failed at step N with that step's error.
Nothing is rolled back. A step's answer is kept per step; secret fields
from any step go to the asking agent once, as RFC 0027 says.
A plan is approved whole (decision 2). To change it, the person denies it and the agent asks again.
Standing approvals (not now)
Turning a request into a rule ("always allow this") was weighed and held: it changes who decides, not how requests read, and is worth revisiting only when real volume shows which asks recur.
Build order
/me/requestswith Waiting and History, the header count, rows answered in place, and the/mesection removed.- Ask sentences: the template field on ops, filled for the agent, token, grant, claim, delete, invite and role ops; rows, pages and emails use them.
- Plans:
POST /api/v1/requests, storage of steps and per-step answers, the in-order run that stops at the first failure, and the plan's page. - One email per burst: the five-minute window per agent and the listing email.
Decisions
- The place is called Requests (owner, 2026-11-08).
- A plan is approved whole; no step can be unticked (decided by the implementer, stated to the owner, 2026-11-08: approval must stay exactly what runs, and a narrower plan is one Deny and one re-ask).
- Build A and B (the Requests page and plans); hold C, standing approvals (the design page's recommendation).
- A failing step stops the plan without rolling back earlier ones, which were each the person's own act.
- A burst window of five minutes per agent; at most 20 steps a plan.
- An email's button goes exactly to its request, where approving is one tap; it never goes to a list (owner, 2026-11-08: "If I can't push the button in my email and have it work, then I should go exactly to the request in the email").