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:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user