summaryrefslogtreecommitdiff
path: root/AI_AGENT_ACCESS.md
diff options
context:
space:
mode:
Diffstat (limited to 'AI_AGENT_ACCESS.md')
-rw-r--r--AI_AGENT_ACCESS.md340
1 files changed, 0 insertions, 340 deletions
diff --git a/AI_AGENT_ACCESS.md b/AI_AGENT_ACCESS.md
deleted file mode 100644
index 40fe6a1..0000000
--- a/AI_AGENT_ACCESS.md
+++ /dev/null
@@ -1,340 +0,0 @@
-# AI Agent Access Design
-
-## Overview
-Add a dedicated API endpoint optimized for AI agents (like Claude) to access dashboard data in a structured, machine-readable format with simple authentication.
-
-## Authentication Strategy
-
-### API Key-Based Auth
-Simple bearer token authentication that's easy to use from Claude.ai:
-- Generate a long, random API key for AI access
-- Store in environment variable: `AI_AGENT_API_KEY`
-- Use standard `Authorization: Bearer {key}` header
-- No complex OAuth flows or JWT rotation
-
-### Why This Approach?
-1. **Simple for Claude**: Just include auth header in requests
-2. **Stateless**: No session management needed
-3. **Revocable**: Change key in .env to revoke access
-4. **Standard**: Uses common HTTP authorization pattern
-
-## API Endpoints
-
-### GET /api/ai/dashboard
-Returns complete dashboard data in AI-optimized JSON format.
-
-**Request:**
-```http
-GET /api/ai/dashboard HTTP/1.1
-Host: localhost:8080
-Authorization: Bearer {AI_AGENT_API_KEY}
-```
-
-**Response (Success - 200 OK):**
-```json
-{
- "status": "success",
- "timestamp": "2026-01-09T14:30:00Z",
- "data": {
- "trello_boards": [
- {
- "id": "board123",
- "name": "Work Projects",
- "cards": [
- {
- "id": "card1",
- "name": "Complete project proposal",
- "list": "In Progress",
- "due_date": "2026-01-15",
- "url": "https://trello.com/c/card1"
- }
- ]
- }
- ],
- "todoist_tasks": [
- {
- "id": "task1",
- "content": "Buy groceries",
- "project": "Personal",
- "priority": 1,
- "due_date": "2026-01-10",
- "completed": false,
- "labels": ["shopping"],
- "url": "https://todoist.com/task/1"
- }
- ],
- "obsidian_notes": [
- {
- "filename": "meeting-notes.md",
- "title": "Team Meeting Notes",
- "content_preview": "Discussed Q1 goals...",
- "modified": "2026-01-09T10:00:00Z",
- "tags": ["meetings", "work"]
- }
- ],
- "plantoeat_meals": [
- {
- "id": "meal1",
- "recipe": "Spaghetti Carbonara",
- "date": "2026-01-09",
- "meal_type": "dinner",
- "url": "https://plantoeat.com/recipe/123"
- }
- ]
- },
- "metadata": {
- "cache_age_seconds": 45,
- "sources_refreshed": ["trello", "todoist"],
- "errors": []
- }
-}
-```
-
-**Response (Unauthorized - 401):**
-```json
-{
- "status": "error",
- "error": "Invalid or missing API key",
- "hint": "Include 'Authorization: Bearer {key}' header"
-}
-```
-
-### GET /api/ai/boards/{board_id}/cards
-Get cards from a specific Trello board.
-
-**Request:**
-```http
-GET /api/ai/boards/board123/cards HTTP/1.1
-Authorization: Bearer {AI_AGENT_API_KEY}
-```
-
-### GET /api/ai/tasks?filter={filter}
-Get filtered tasks (today, week, overdue, completed).
-
-**Request:**
-```http
-GET /api/ai/tasks?filter=today HTTP/1.1
-Authorization: Bearer {AI_AGENT_API_KEY}
-```
-
-### POST /api/ai/task
-Create a new Todoist task (Phase 2).
-
-**Request:**
-```http
-POST /api/ai/task HTTP/1.1
-Authorization: Bearer {AI_AGENT_API_KEY}
-Content-Type: application/json
-
-{
- "content": "Buy milk",
- "project": "Personal",
- "due_date": "2026-01-10",
- "priority": 1,
- "labels": ["shopping"]
-}
-```
-
-## AI-Optimized Response Format
-
-### Design Principles
-1. **Flat structure**: Avoid deep nesting where possible
-2. **Explicit field names**: Use `due_date` not `dueDate` for clarity
-3. **Include metadata**: Provide context about data freshness
-4. **Clear errors**: Return actionable error messages
-5. **Consistent types**: Always use ISO 8601 for dates
-
-### Example Claude.ai Usage
-```markdown
-User: "What tasks do I have due today?"
-
-Claude uses MCP tool or API call:
-GET /api/ai/tasks?filter=today
-Authorization: Bearer sk-ai-1234567890abcdef
-
-Claude response: "You have 3 tasks due today:
-1. Buy groceries (Personal, Priority 1)
-2. Complete project proposal (Work, Priority 2)
-3. Call dentist (Health, Priority 3)"
-```
-
-## Implementation
-
-### Middleware: Auth Check
-```go
-// internal/middleware/ai_auth.go
-func AIAuthMiddleware(apiKey string) func(http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- authHeader := r.Header.Get("Authorization")
-
- if !strings.HasPrefix(authHeader, "Bearer ") {
- respondJSON(w, 401, map[string]string{
- "status": "error",
- "error": "Missing or invalid Authorization header",
- "hint": "Include 'Authorization: Bearer {key}' header",
- })
- return
- }
-
- token := strings.TrimPrefix(authHeader, "Bearer ")
- if token != apiKey {
- respondJSON(w, 401, map[string]string{
- "status": "error",
- "error": "Invalid API key",
- })
- return
- }
-
- next.ServeHTTP(w, r)
- })
- }
-}
-```
-
-### Handler: AI Dashboard
-```go
-// internal/handlers/ai_handlers.go
-func (h *Handler) HandleAIDashboard(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
-
- // Fetch all data
- data, err := h.fetchDashboardData(ctx, false)
- if err != nil {
- respondJSON(w, 500, map[string]interface{}{
- "status": "error",
- "error": err.Error(),
- })
- return
- }
-
- // Format for AI consumption
- response := map[string]interface{}{
- "status": "success",
- "timestamp": time.Now().Format(time.RFC3339),
- "data": map[string]interface{}{
- "trello_boards": formatBoardsForAI(data.Boards),
- "todoist_tasks": formatTasksForAI(data.Tasks),
- "obsidian_notes": formatNotesForAI(data.Notes),
- "plantoeat_meals": formatMealsForAI(data.Meals),
- },
- "metadata": map[string]interface{}{
- "errors": data.Errors,
- },
- }
-
- respondJSON(w, 200, response)
-}
-```
-
-### Router Setup
-```go
-// cmd/dashboard/main.go
-func main() {
- // ... existing setup ...
-
- // AI Agent routes (protected by auth middleware)
- if cfg.AIAgentAPIKey != "" {
- aiRouter := chi.NewRouter()
- aiRouter.Use(middleware.AIAuthMiddleware(cfg.AIAgentAPIKey))
-
- r.Route("/api/ai", func(r chi.Router) {
- r.Use(middleware.AIAuthMiddleware(cfg.AIAgentAPIKey))
- r.Get("/dashboard", h.HandleAIDashboard)
- r.Get("/boards/{boardID}/cards", h.HandleAIBoardCards)
- r.Get("/tasks", h.HandleAITasks)
- // Phase 2: Write operations
- // r.Post("/task", h.HandleAICreateTask)
- })
- }
-}
-```
-
-## Security Considerations
-
-1. **Key Storage**: Never commit API key to git
-2. **Key Rotation**: Easy to change in .env file
-3. **Rate Limiting**: Consider adding rate limits per key
-4. **HTTPS Only**: Use HTTPS in production
-5. **Logging**: Log API key usage (last 4 chars only)
-
-## Configuration
-
-### .env.example
-```bash
-# AI Agent Access
-AI_AGENT_API_KEY=sk-ai-1234567890abcdef...
-# Generate with: openssl rand -hex 32
-```
-
-### config.go
-```go
-type Config struct {
- // ... existing fields ...
- AIAgentAPIKey string
-}
-
-func Load() (*Config, error) {
- cfg := &Config{
- // ... existing fields ...
- AIAgentAPIKey: os.Getenv("AI_AGENT_API_KEY"),
- }
- return cfg, nil
-}
-```
-
-## Usage from Claude.ai
-
-### With MCP (Model Context Protocol)
-```json
-{
- "mcpServers": {
- "dashboard": {
- "command": "curl",
- "args": [
- "-H", "Authorization: Bearer ${AI_AGENT_API_KEY}",
- "http://localhost:8080/api/ai/dashboard"
- ]
- }
- }
-}
-```
-
-### Direct API Call
-Claude can make HTTP requests directly:
-```
-GET http://localhost:8080/api/ai/dashboard
-Authorization: Bearer sk-ai-1234567890abcdef
-```
-
-## Future Enhancements
-
-1. **Webhook Support**: POST updates to Claude.ai when data changes
-2. **Streaming**: Server-sent events for real-time updates
-3. **Scoped Keys**: Different keys for read vs write access
-4. **GraphQL**: More flexible querying for AI agents
-5. **Natural Language Queries**: `/api/ai/query?q=What's due today?`
-
-## Testing
-
-### Manual Test
-```bash
-# Generate API key
-export AI_KEY=$(openssl rand -hex 32)
-
-# Add to .env
-echo "AI_AGENT_API_KEY=sk-ai-$AI_KEY" >> .env
-
-# Test endpoint
-curl -H "Authorization: Bearer sk-ai-$AI_KEY" \
- http://localhost:8080/api/ai/dashboard | jq .
-```
-
-### Unit Test
-```go
-func TestAIAuthMiddleware(t *testing.T) {
- // Test valid key
- // Test invalid key
- // Test missing header
-}
-```