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
via API directly. This is how we "teach and learn to schedule" — the UI
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.