diff options
Diffstat (limited to 'issues/feature_agent_context_api.md')
| -rw-r--r-- | issues/feature_agent_context_api.md | 271 |
1 files changed, 39 insertions, 232 deletions
diff --git a/issues/feature_agent_context_api.md b/issues/feature_agent_context_api.md index 7be5f50..69b3feb 100644 --- a/issues/feature_agent_context_api.md +++ b/issues/feature_agent_context_api.md @@ -1,114 +1,46 @@ # Feature: Agent Context API -**Status:** [IN_PROGRESS] Phase 1 Complete +**Status:** [COMPLETED] **Created:** 2026-01-27 +**Updated:** 2026-03-23 **Author:** Architect --- ## Overview -Expose a JSON API that allows external chat agents (e.g., Claude Code) to query dashboard context and manipulate items. Authentication uses a notification-based approval flow with agent identity binding. +Expose a JSON API that allows external chat agents (e.g., Claude Code, Gemini CLI) to query dashboard context and manipulate items. Authentication uses a notification-based approval flow with agent identity binding. --- ## User Stories -1. **As a user**, I can approve/deny agent access requests from the dashboard UI -2. **As a user**, I can see which agents have been granted access and revoke them -3. **As an agent**, I can request access by providing my name and unique ID -4. **As an agent**, once approved, I can query the 7-day context (tasks, meals, timeline) -5. **As an agent**, I can complete/uncomplete tasks, update due dates, modify details, and create items +1. [x] **As a user**, I can approve/deny agent access requests from the dashboard UI +2. [x] **As a user**, I can see which agents have been granted access and revoke them +3. [x] **As an agent**, I can request access by providing my name and unique ID +4. [x] **As an agent**, once approved, I can query the 7-day context (tasks, meals, timeline) +5. [x] **As an agent**, I can complete/uncomplete tasks, update due dates, modify details, and create items --- -## Authentication Flow +## Implementation Status -``` -Agent Dashboard API Browser Tab - │ │ │ - │ POST /agent/auth/request │ │ - │ {name, agent_id} │ │ - │ ──────────────────────────────>│ │ - │ │ │ - │ {request_token, status: │ WebSocket push: │ - │ "pending"} │ "Agent X wants access" │ - │ <──────────────────────────────│ ────────────────────────────>│ - │ │ │ - │ │ User approves - │ │ │ - │ │ POST /agent/auth/approve │ - │ │ <────────────────────────────│ - │ │ │ - │ GET /agent/auth/poll │ │ - │ ?token=X │ │ - │ ──────────────────────────────>│ │ - │ │ │ - │ {status: "approved", │ │ - │ session_token, expiry} │ │ - │ <──────────────────────────────│ │ - │ │ │ - │ GET /agent/context │ │ - │ Authorization: Bearer X │ │ - │ ──────────────────────────────>│ │ - │ │ │ - │ {timeline, tasks, ...} │ │ - │ <──────────────────────────────│ │ -``` +### Phase 1: Auth Flow + Read Context (Complete) +- [x] Agent authentication handshake (Request -> Approve -> Token) +- [x] `/agent/context` endpoint returning timeline + today items +- [x] WebSocket notification for approval requests +- [x] Browser-only agent support (`/agent/web/context`) ---- - -## Agent Identity Binding - -| Scenario | Behavior | -|----------|----------| -| New agent (name + ID never seen) | Show approval prompt, store pairing on approve | -| Known agent (name + ID match stored) | Show approval prompt with "Recognized" indicator | -| Suspicious (known name, different ID) | Show warning: "Agent 'X' with different ID" — require explicit re-trust | - ---- - -## Design Decisions +### Phase 2: Write Operations (Complete) +- [x] `POST /agent/tasks/{id}/complete` +- [x] `POST /agent/tasks/{id}/uncomplete` +- [x] `PATCH /agent/tasks/{id}/due` +- [x] `PATCH /agent/tasks/{id}` (generic update) -| Decision | Choice | Rationale | -|----------|--------|-----------| -| Session refresh | None — re-authenticate after expiry | Keep it simple | -| Concurrent sessions | One per agent — new approval invalidates previous | Predictable state | -| Deny behavior | Single-request denial, no blocking | Simple first pass | - ---- - -## Database Schema - -### New Tables - -```sql --- Registered/approved agents -CREATE TABLE agents ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - agent_id TEXT NOT NULL UNIQUE, -- UUID from agent - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - last_seen DATETIME, - trusted BOOLEAN DEFAULT 1 -- can be revoked -); - --- Pending access requests and sessions -CREATE TABLE agent_sessions ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - request_token TEXT NOT NULL UNIQUE, - agent_name TEXT NOT NULL, - agent_id TEXT NOT NULL, - status TEXT DEFAULT 'pending', -- pending, approved, denied, expired - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - expires_at DATETIME NOT NULL, -- request expires after 5 min - session_token TEXT, -- populated on approval - session_expires_at DATETIME -- session TTL (1 hour) -); - -CREATE INDEX idx_agent_sessions_request ON agent_sessions(request_token); -CREATE INDEX idx_agent_sessions_session ON agent_sessions(session_token); -``` +### Phase 3: Create + Management (Complete) +- [x] `POST /agent/tasks` (Quick add) +- [x] `POST /agent/shopping` (Add shopping item) +- [x] Trusted Agent management UI in Settings (list, revoke) --- @@ -128,149 +60,23 @@ CREATE INDEX idx_agent_sessions_session ON agent_sessions(session_token); | POST | `/agent/auth/approve` | User approves request | | POST | `/agent/auth/deny` | User denies request | -### Context (agent session required) +### Context & Operations (agent session required) | Method | Path | Purpose | |--------|------|---------| | GET | `/agent/context` | Full 7-day context | +| POST | `/agent/tasks` | Create task | +| POST | `/agent/tasks/{id}/complete` | Complete task | +| POST | `/agent/tasks/{id}/uncomplete` | Reopen task | +| PATCH | `/agent/tasks/{id}/due` | Update due date | +| PATCH | `/agent/tasks/{id}` | Update details (title, desc) | +| POST | `/agent/shopping` | Add shopping item | -### Write Operations (agent session required) - -| Method | Path | Purpose | Priority | -|--------|------|---------|----------| -| PATCH | `/agent/tasks/{id}/due` | Update due date | P1 | -| POST | `/agent/tasks/{id}/complete` | Complete task | P1 | -| POST | `/agent/tasks/{id}/uncomplete` | Reopen task | P1 | -| PATCH | `/agent/tasks/{id}` | Update details (title, desc) | P2 | -| POST | `/agent/tasks` | Create task | P3 | -| POST | `/agent/shopping/add` | Add shopping item | P3 | - ---- - -## Context Response Format - -```json -{ - "generated_at": "2026-01-27T10:30:00-10:00", - "range": { - "start": "2026-01-27", - "end": "2026-02-03" - }, - "timeline": [ - { - "id": "task_123", - "source": "todoist", - "type": "task", - "title": "Buy groceries", - "description": "Milk, eggs, bread", - "due": "2026-01-27T17:00:00-10:00", - "priority": 2, - "completable": true, - "url": "https://todoist.com/..." - } - ], - "summary": { - "total_items": 42, - "by_source": {"todoist": 15, "trello": 20, "plantoeat": 7}, - "overdue": 3, - "today": 8 - } -} -``` - ---- - -## Browser Components - -### WebSocket Endpoint -- Path: `/ws/notifications` -- Purpose: Push agent request alerts to open browser tabs -- Must handle: reconnect on disconnect, authentication check - -### Approval UI -- Trigger: WebSocket message of type `agent_request` -- Display: Modal or toast notification -- Content: - - Agent name - - Agent ID (truncated to 8 chars) - - Trust indicator: "New Agent" / "Recognized" / "Warning: Different ID" -- Actions: Approve / Deny buttons +### Management (browser session required) -### Agent Management (Phase 3) -- List of trusted agents with last-seen timestamp -- Revoke access button per agent - ---- - -## Session Configuration - -| Parameter | Value | -|-----------|-------| -| Request expiry | 5 minutes | -| Session TTL | 1 hour | -| Poll interval (agent-side) | 2 seconds | - ---- - -## Security Considerations - -1. **Rate limiting** on `/agent/auth/request` — 10 requests/minute per IP -2. **Tokens** are cryptographically random (32 bytes, base64url) -3. **HTTPS required** — tokens in Authorization header -4. **No CSRF** for agent endpoints — token-based auth, not cookies -5. **One session per agent** — new approval invalidates previous session - ---- - -## Implementation Phases - -### Phase 1: Auth Flow + Read Context -Files to create/modify: -- `migrations/010_agent_tables.sql` — new tables -- `internal/store/sqlite.go` — agent/session CRUD methods -- `internal/handlers/agent.go` — new handler file for agent endpoints -- `internal/handlers/websocket.go` — WebSocket notification hub -- `cmd/dashboard/main.go` — register new routes -- `web/templates/partials/agent-approval.html` — approval modal -- `web/static/js/app.js` — WebSocket connection + approval UI logic - -Endpoints: -- POST `/agent/auth/request` -- GET `/agent/auth/poll` -- POST `/agent/auth/approve` -- POST `/agent/auth/deny` -- GET `/agent/context` -- WS `/ws/notifications` - -### Phase 2: Write Operations (P1 + P2) -- POST `/agent/tasks/{id}/complete` -- POST `/agent/tasks/{id}/uncomplete` -- PATCH `/agent/tasks/{id}/due` -- PATCH `/agent/tasks/{id}` - -### Phase 3: Create + Management -- POST `/agent/tasks` -- POST `/agent/shopping/add` -- Agent management UI (list, revoke) - ---- - -## Testing Strategy - -### Unit Tests -- `internal/store/sqlite_test.go` — agent/session CRUD -- `internal/handlers/agent_test.go` — endpoint logic - -### Integration Tests -- Full auth flow: request → approve → poll → context -- Identity binding: same name different ID triggers warning -- Session expiry: requests fail after TTL - -### Manual Testing -- Open dashboard in browser -- Run agent simulation script to request access -- Verify notification appears -- Approve and verify context returned +| Method | Path | Purpose | +|--------|------|---------| +| DELETE | `/settings/agents/{id}` | Revoke agent access | --- @@ -280,8 +86,9 @@ Endpoints: |---------|------| | Migration | `migrations/010_agent_tables.sql` | | Store methods | `internal/store/sqlite.go` | -| Agent handlers | `internal/handlers/agent.go` (new) | -| WebSocket hub | `internal/handlers/websocket.go` (new) | +| Agent handlers | `internal/handlers/agent.go` | +| WebSocket hub | `internal/handlers/websocket.go` | | Route registration | `cmd/dashboard/main.go` | -| Approval modal | `web/templates/partials/agent-approval.html` (new) | -| Client JS | `web/static/js/app.js` | +| Settings handler | `internal/handlers/settings.go` | +| Settings template | `web/templates/settings.html` | +| Tests | `internal/handlers/agent_test.go` | |
