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 |
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/listPinnedannotate files shared in chat (distinct from the workspace drive — see Board, work, and files).notification.updatePreferences/getPreferencesmanage the acting member's notification settings.
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.