BOX-API-SPEC: Add confirmation system spec\n\nAPI requests result in DMs; DMs require explicit confirmations.\nCovers: [REQ id] -> [CONFIRM id] flow, pending request tracking,\nsweeper for timeouts, when to require confirmation.

This commit is contained in:
operator-main
2026-10-04 03:00:36 +00:00
parent ac6d7bf2d3
commit 706fe057a6
+114
View File
@@ -528,3 +528,117 @@ API equivalent:
The UI teaches the API. Agents learn by watching UI actions, then automate The UI teaches the API. Agents learn by watching UI actions, then automate
via API directly. This is how we "teach and learn to schedule" — the UI via API directly. This is how we "teach and learn to schedule" — the UI
is the classroom, the API is the workshop. is the classroom, the API is the workshop.
## Confirmation System
API requests must result in DMs, and DMs must result in confirmations.
Fire-and-forget is not enough for critical operations.
### The Problem
Currently:
```
Agent → API POST /timers → Server sends DM → Done
```
The DM being sent is treated as "working". But:
- Did the agent receive it?
- Did the agent act on it?
- Did the action succeed?
We need explicit confirmations, not just "DM was sent".
### Confirmation Flow
```
1. Agent → API: POST /api/box/timers {job_yaml}
↓
2. Server: Generate request_id, store pending
↓
3. Server → Agent (DM): [REQ {request_id}] Timer creation requested...
↓
4. Agent: Processes request
↓
5. Agent → Server (DM): [CONFIRM {request_id}] Timer created: job-foo.timer
↓
6. Server: Mark confirmed, log to audit
```
If step 5 doesn't happen within timeout:
- Retry the DM (up to 3x)
- Then mark as `UNCONFIRMED` and alert
### Confirmation DM Format
**Request (server → agent):**
```
[REQ a1b2c3d4] Create timer: job-board-watch
Details: schedule=*/5 * * * *, agent=muse
Reply with [CONFIRM a1b2c3d4] when done.
```
**Confirmation (agent → server):**
```
[CONFIRM a1b2c3d4] Timer job-board-watch.timer created and active.
```
**Failure:**
```
[CONFIRM a1b2c3d4] FAILED: Invalid schedule format
```
### API Response with Confirmation Tracking
When an API request triggers a DM, the response includes the request ID
for tracking:
```json
{
"request_id": "a1b2c3d4",
"status": "pending",
"dm_sent": true,
"confirmation_url": "/api/box/requests/a1b2c3d4"
}
```
**Check confirmation status:**
```
GET /api/box/requests/{request_id}
```
```json
{
"request_id": "a1b2c3d4",
"status": "confirmed", // pending | confirmed | failed | timeout
"created_at": "2026-10-04T02:30:00Z",
"confirmed_at": "2026-10-04T02:30:15Z",
"attempts": 1
}
```
### Pending Request Sweeper
A background job (every minute) checks for unconfirmed requests:
- If `now - created_at > timeout` (default 5m) and status is `pending`:
- Retry DM (if attempts < 3)
- Else mark `timeout`, log to audit, optionally alert
### When to Require Confirmation
Not all API calls need it. Use confirmation for:
- ✅ Timer create/delete (critical, hard to undo)
- ✅ Job trigger (should verify it started)
- ❌ Timer list (read-only, no side effects)
- ❌ Job status check (read-only)
**Rule:** If the API call has side effects (creates, deletes, modifies),
it requires confirmation. Reads do not.
### Integration with JOB System
The JOB system already uses `[JOB id]` → `[RESULT id]`. This is a specific
case of the general confirmation pattern:
- `[JOB id]` = `[REQ id]` with type=job
- `[RESULT id]` = `[CONFIRM id]` with result data
The confirmation system generalizes this to all API-triggered DMs.