This is a technical reference for developers writing a mail collector. If you only want to forward mail to your brain, see your email; it needs nothing from this page.
- One mailbox, one brain. A mail item may only enter the personal brain of the person whose mailbox it came from, and only from an address that person has verified. The door checks this in code before anything is stored, and refuses everything else with a 422. No hint, no partition and no
?brain=changes it. - The mail is never kept. A mail item is created with retention
none: its body exists only while the item waits to be filed, and is destroyed when filing ends (archive, reject, delete, or seven days unfiled). No archive copy, no downloadable original, no replay. What remains is the stub: subject, link, content hash, external id, the pages it was filed to, and the dates. - The skill is pinned to
ingest-email, at the door, whatever the caller asked for.
The shape
A markdown file: frontmatter, then the new messages of the thread, oldest first.
Rules for the body: only the new messages, oldest first. Quoted history is stripped by whatever produces the contract. Attachments are never sent, only named. Extra keys are allowed and preserved; unknown keys are ignored.
Where to send it
retain: none is implied for a kind: email contract whether or not you send it. It is worth sending anyway: it is the honest description of what you are asking for, and it applies to any item, not only mail.
Check the pairing before you send
A collector should verify its own configuration at startup rather than discovering a mistake at delivery. Callwhoami with the credential it will use:
- With a service credential on a personal brain, the response’s first brain carries
personal: trueandownerMailboxes, the owner’s verified addresses. Refuse to run unless the mailbox you are about to read is in that list. - With an OAuth connection,
user.mailboxescarries the signed-in caller’s own verified addresses.
What the door answers
Every refusal is a 422 with a message starting “Mail refused”, and nothing is stored: no item, no blob, no extracted text.
The agent route goes through the same door and gets the same refusal, so an agent cannot file mail into a shared brain even when it is asked to.
Verified mailboxes
An address is added and confirmed under Profile, then Mailboxes, in the web app: Cortex sends a six-digit code to the address, valid for fifteen minutes and dead after five wrong entries. The sign-in address is verified by signing in and is on the list from the start. Up to ten added addresses per account. Removing one takes effect immediately. The list belongs to the user rather than to a workspace. The list is managed in the web app and nowhere else: proving an address is something a person does, so there is nothing in the public API for it.Once it is in
The item is pinned to theingest-email skill, named by the subject, and carries the link as its source reference. From there it is an ordinary inbox item: filed by your agent, by Cortex under the brain’s filing mode, or by you in the review queue. What the skill writes is described in how a thread is filed.
get_inbox_item and list_inbox report retention (none or keep) and bodyDestroyedAt. Once the body is gone, GET .../inbox/{itemId}/download answers 410, get_source_file answers with an error instead of the file, and the Sources record shows “Body not kept”. A rejected mail item is closed rather than re-queued.