# Claude in CLAWD Mail

CLAWD Mail uses the exact `anthropic/claude-haiku-5.5` model through OpenRouter's standard streaming Chat Completions API. Compose a new draft, draft a reply, or summarize a conversation from **Ask Claude**. Text appears as it arrives. **Apply draft** and **Apply reply** replace only the editor body after completion; sending remains a separate action. Summaries stay in the review panel.

## Configuration

```dotenv
OPENROUTER_API_KEY=
OPENROUTER_CLAUDE=anthropic/claude-haiku-5.5
```

Set both values in the private backend environment. This installation stores them in ignored `backend/.env.local`. Never use a `VUE_APP_` variable for the key. Restart the backend after changing configuration.

The provider endpoint is `POST https://openrouter.ai/api/v1/chat/completions`, with `stream: true`, a 1,000-token output limit, and no automatic model substitution or retry. Only answer text is returned to the app. Provider reasoning fields are not displayed or stored. Official references: [model](https://openrouter.ai/anthropic/claude-haiku-5.5), [streaming](https://openrouter.ai/docs/api_reference/streaming).

## Private requests and review

The assistant shares only the selected draft or owned conversation and the user's instructions when **Request** is clicked. Thread content is fetched from private storage after checking inbox ownership; client-supplied conversation objects cannot replace it. Summaries do not send an unrelated reply draft. Attachments are not sent. Email text is treated as untrusted input, and the model has no tools or ability to send mail.

Assistance uses the same account session or legacy mailbox authentication as mail APIs. A shared mailbox key cannot bypass individual accounts. AgentMail connections currently display the private CLAWD mailbox sign-in requirement. Authenticated users can have four requests in progress and submit 20 requests per hour. Conversations use up to the latest 100 messages and 250,000 body characters; the review panel identifies shortened context.

Results and request status are stored in the existing private R2 bucket under each user's namespace. Closing a panel or disconnecting its stream does not automatically repeat a paid request. Completed results can be reopened. An unfinished request whose 90-second execution lease expires becomes an explicit interrupted result after a server restart or lost worker. Cancellation is not offered.

## API and verification

All routes below require private mailbox authentication:

| Route | Behavior |
| --- | --- |
| `GET /api/mail/assistant/config` | Public assistant configuration for the signed-in user; no secret values |
| `POST /api/mail/assistant/jobs` | `draft`, `reply`, or `summary`; streams `event: job` updates with `Accept: text/event-stream`, otherwise returns a queued job with HTTP 202 |
| `GET /api/mail/assistant/jobs` | Recent private request history |
| `GET /api/mail/assistant/jobs/:id` | Saved or currently running request status; never starts another provider request |

Run `npm run mail:test` for ownership, validation, streaming, durable results, interruption, provider failure, and output validation checks. Run `npm run build` followed by `node scripts/verify-assistant.cjs` for browser checks using local fixtures. The optional `node scripts/verify-assistant-live.cjs` uses the configured OpenRouter key for three small synthetic requests; account, email, and storage providers remain local fixtures, and no real email is sent. Verification reports and screenshots are saved in ignored `artifacts/qa/`.
