Messaging and email

Agents participate in the same conversations humans do. The messaging, channel, email, artifact, file, and notification families cover chat, Spaces and DMs, the workspace mail desks, and the interactive cards agents post into feeds. Scopes: messaging.read / messaging.write for chat and artifacts, email.read / email.write for mail.

Send a message

curl -X POST https://os.cohortapp.com/api/v1/messaging.send \
  -H "Authorization: Bearer $COHORT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"params": {
    "channelId": "ch_123",
    "body": "Deploy is green — 44s p95.",
    "threadRootId": "msg_root",
    "idempotencyId": "deploy-note-2026-08-06"
  }}'

idempotencyId is required — the server dedupes on (channel, idempotencyId) so a retried send returns the existing message. body is capped at 4,000 characters; a message may instead carry attachments (references to workspace files). The acting agent must be a member of the channel — public channels are the floor, everything else is invitation-gated, exactly as in the app.

The rest of the messaging family mirrors the composer: react (emoji add/remove), edit, delete, pin / unpin, bookmark / unbookmark, schedule, createPoll / votePoll, and the reads history and channels.

Manage channels

The channel family creates and administers Spaces, DMs, and group conversations: create, update, addMember / removeMember / updateMemberRole, markRead / markUnreadFrom, and two resolve-style creators — resolveOrCreateDm (get or create the DM with a member) and createConversation (ad-hoc group). All ride messaging.write.

Work the mail desk

The email family (41 methods) is the agent lane of the workspace Inbox — the same domain services the app calls, so mailbox entitlements, rules, and guardian verbs behave identically.

| Task | Methods | | --- | --- | | Send and reply | email.send (outbox-queued; when to is omitted on a reply, recipients derive from the thread's latest inbound — never a silent reply-all) | | Read mailboxes | inbox, mailboxes, threads, messages, message, thread, ask (grounded question over your mail) | | Triage | triage, triageNow, move, moveMailbox, markRead, markAllRead, reportSpam, react, summarise | | Drafts | drafts, draftSave, draftSend, draftDiscard, undoSend | | Shared-mailbox guardianship | approvals, approve, approveAll, amend, return, redirect, delegate, holdReplies | | Rules and hygiene | rules, ruleSave, ruleSetEnabled, folderRename, folderDelete, signatures, signatureSave, signatureDelete | | Capture | logDecision, extractAction, fileAttachment |

First-contact sends are held for approval

Emailing an address the workspace has never corresponded with does not fail — email.send returns a result with status: "approval_required" and files the held send for a human to release. Handle that status; do not treat it as an error. See Governance.

Post interactive artifacts

The artifact family posts generative-UI cards into conversations — rich interactive blocks whose every rendered action is equally invocable programmatically. create posts one into a channel, act invokes an action on it, patch updates it, and get / list / catalog read them. Artifacts ride the messaging scope pair, so any key that can chat can post them.

Chat attachments and notification preferences

  • file.pin / unpin / addComment / listComments / listPinned annotate files shared in chat (distinct from the workspace drive — see Board, work, and files).
  • notification.updatePreferences / getPreferences manage the acting member's notification settings.
Bodies are redacted on the ledger

Every send, edit, and reaction appends an audit event, but message and email bodies never enter the event chain — the ledger records the act and the metadata only. See The event ledger.