Artifact 86c336fcedbfea656a523e14d60c089b7b0ff9d899eaf7f270caaff95a1def16:
- File docs/rfcs/0027-ask-your-person.md — part of check-in [b69494aa55] at 2026-11-08 21:39:33 on branch rfc-0027-ask — RFC 0027: an agent asks its person for what it may not do (user: dmestas, size: 7562) [annotate] [blame] [check-ins using] [more...]
- Feature Name:
ask-your-person(an agent refused for want of authority its person holds asks them instead; one approval runs the call as that person) - Start Date: 2026-11-08
- Status: Draft. Decisions settled by the owner on 2026-11-08 (see Decisions).
- Depends on: RFC 0021 (agent accounts, the operator, forge agents and their guards); RFC 0026 (an agent inherits its person within its scope); RFC 0011 (notifications: in-app, push, email)
- Amends: the sign-off of 2026-10-21 (RFC 0021, deed acts), which this generalises: its three deed operations become ordinary cases and its allowlist goes. RFC 0021 Forge agents: Guards ("a machine cannot multiply machines"), which now yields to a person's signed approval.
- Terms: an agent's person is who answers for it: a personal agent's operator, a forge agent's answerable site admin, or, for a dedicated team or repository agent, that scope's admins (any one of them may answer).
Summary
Whatever a person may do, their agent may ask them to do. When an agent's call is refused because it lacks authority its person holds, the agent can ask instead of stopping. The person is told at once (inbox, phone push, email), approves or denies with one tap, and an approval runs exactly the call the agent made, as the person, under the person's own permissions at that moment. The result goes back to the agent, a secret in it readable once and by that agent only. Every zeitforge user has this for every agent they register, with nothing to set up.
Motivation
On 2026-11-08 a QA agent needed an account. Creating it was the only step a machine could not take, and it cost the owner three manual steps on a phone: a page to find, a token to copy, a vault to paste it into. The forge already had the right shape for three deed acts (delete, un-serve, hand on a repository): the agent asks, the owner approves, the call runs as the owner. It stopped there for three reasons: an allowlist of three operations, an approver found through a repository's deed (so nothing forge-wide could be asked), and a replay that discarded its result (so a minted token would be lost). This RFC removes all three.
Design
Asking
An agent asks by sending the call it wants with Quarry-Ask: <reason>.
The reason is one line in the agent's words, shown to the person beside
the forge's own description of the call. Without the header nothing
changes: a refusal is a refusal, so no agent queues requests by
accident.
The router decides before the operation runs:
- the caller is an agent with a person;
- the call is refused for authority only, not because its input is invalid, its target does not exist for this agent, or the forge is unavailable;
- the person holds that authority now (the same check the call would meet as them);
- the call is inside the agent's own scope (below).
When all hold, the answer is 202 Accepted with the request (id,
summary, state pending), and nothing else happens. Otherwise the
ordinary refusal stands, and the agent learns no more than it would
have without asking: a repository it may not see is still answered as
one that does not exist.
What may be asked
Anything the person may do themselves (decision 1), except:
- the person's own credentials and sessions: password, email, sign-in links, their own tokens and sync token;
- deciding sign-offs, and changing who answers for an agent;
- deleting, disabling or suspending the person's own account.
Everything else the person can do is askable, forge-wide operations included: creating an agent, granting a role, changing a repository setting, handing a repository on.
Scope
A request must fall inside the agent's scope as its token states it: an agent whose token names repositories can ask only about those, and a token's letter ceiling bounds what it may ask for there. A forge-wide operation needs a token with no repository list. The person's own permissions bound the rest, checked again at approval, so an agent can never obtain through a request what its person could not do.
Answering
The request goes to the agent's person. For a dedicated team or repository agent it goes to that scope's admins, and the first of them to decide closes it. It is delivered at once on the sign-off workflow: in-app, phone push, and email, on by default because a request waits on someone. The email's link opens a page with the request and two buttons, Approve and Deny; it needs the person's own session (a sign-in link if they have none), so a forwarded email approves nothing.
Approval checks first that nothing it was asked about has moved: the
agent still exists, is open and still answers to this person; a
repository is still the same one (by its project code) and still within
the agent's scope; and the person may still do the call. Then it runs
the stored call, exactly as made, through the ordinary operation
registry as the person. The act is journalled as agent (signed off by
person).
SMS is a notify channel, not a quarry feature: it is asked for upstream at danmestas/notify and becomes one more step on the sign-off workflow when notify ships it.
Results
The result of an approved call is kept with the request for the agent
to read with signoff.get. A field an operation marks secret (a minted
token, an invite link) is readable once, by the requesting agent only,
and is never shown on the page, in the email or in the journal; after
the read it is gone. A failed run keeps its error for both to read.
Limits
- A request expires after 7 days unanswered.
- An agent may have at most 20 requests pending; the same call asked again while one is pending returns that one.
- Asking is on for every agent by default. On an agent's page the person can turn it off for that agent; a refused agent is then told its person does not take requests from it.
The forge-agent guard
RFC 0021 kept two acts from forge agents so that a machine cannot multiply machines or raise its own standing: making or altering a forge agent, and changing any account's site-admin flag. Those acts stay unavailable to any agent directly, and become askable: with a person's approval they are that person's act, which is what the guard asked for.
Build order
- Requests become forge-wide: the approver is the agent's person, the repository optional, the result stored (secret fields once), expiry and the pending limit. The three deed operations move onto it and the allowlist goes.
- The router:
Quarry-Ask, the authority-only refusal test, the scope test and the202. - The page and the email: one request, two buttons, session-bound.
- The per-agent switch on the agent's page.
- Secret fields in operation outputs:
agent.token.new,account.invite,agent.token.reissue.
Decisions
- What may be asked: anything the person may do themselves, minus the exclusions above, not an allowlist (owner, 2026-11-08: "A").
- Who has it: every zeitforge user and every agent they register, according to the agent's scope and the person's permissions, with nothing to set up (owner, 2026-11-08).
- Reaching the person: inbox, push and email at once; SMS when notify has it (owner, 2026-11-08: "Inbox is fine but sms or email is even better").
- Settled with the owner's choices as the frame: the explicit
Quarry-Askheader, approval replaying the exact call as the person, 7-day expiry, 20 pending per agent, a secret read once, and asking on by default with a per-agent off switch.