ADR 0023: Triage query APIs and attention queues
Status
Accepted
Context
Duckbill™ Integrated Beta needs read-only Home, Needs Me, conversation, structured search, and the three first-class attention queues (Respond, Waiting, System Alerts). Clients must not talk to Graph for triage. Conversation attention already lives on conversation_states (ADR 0009). MailMessage is content; MessageInstance owns mailbox flags. READ is not COMPLETE. Search is structured metadata only — no vector database. ADR 0022 is the AI inference isolation decision.
Decision
- Versioned
/api/v1query contracts live in@inbox-agent/api-contractsand@inbox-agent/application(triage-query.ts,triage-http.ts). Next.js App Router exposes them. AI never calls mail adapters. - Queues are driven by conversation/attention state and classifications, not unread count. RESPOND remains after
MessageInstance.is_readchanges. Waiting can age. System Alerts are exception-oriented system mail; routine Vercel success is excluded. - Needs Me is the union of ACTION, RESPOND, SYSTEM_ALERT, and low-confidence items. Results always include mailbox and provider.
available_actionsis capability-driven.can_sendandcan_deleteare always false.ENABLE_SENDandENABLE_DELETEstay false. Future command routes are catalogued atGET /api/v1/commandsfor Stream B; this stream does not execute MailCommand / ProviderMutation.- Structured search uses the local canonical index only (
provider_search_used: false,vector_database_used: false). - The lightweight web UI (
/inbox) consumes these APIs. It is not a composer and has no send-from-composer path.
Alternatives
- Query Graph from the browser — rejected; the client must render from canonical tables.
- Derive RESPOND from unread — rejected; READ ≠ COMPLETE and ADR 0009.
- Add a vector index for search — rejected; MVP search is structured metadata.
- Implement send/delete command execution here — rejected; Stream B owns write-back.
Consequences
Triage UI and future clients share /api/v1. Stale sync is labeled. Empty and error states are first-class. No schema migration: queries use existing conversation_states, mail_threads, mail_messages, message_instances, classifications, and connected_accounts. Corrections (MAIL-40/54/55) and write-back stay on other issues.
