Core concepts
Threads
A thread groups the messages of one conversation. Replies your agent sends and replies it receives stay together.
The thread object
| Field | Meaning |
|---|---|
threadId | A UUID that identifies the thread in paths. |
inboxId | The inbox address. |
subject, preview | From the most recent message. |
messageCount, attachmentCount | Totals across the thread. |
senders, recipients | Every address that took part. |
labels | The union of the labels on the thread's messages plus thread-level labels. |
timestamp, receivedTimestamp, sentTimestamp | Most recent activity, most recent received message, most recent sent message. |
lastMessageId | The most recent message. |
triage | Classification of the latest incoming message, when triage is enabled. |
messages | On getThread, the messages in chronological order. |
How messages join a thread
Threading follows standard email headers. When your agent sends a message, a new thread starts and the response includes its threadId. When someone replies, their mail client sets In-Reply-To and References to your message, and the reply lands in the same thread. Replies your agent sends through Reply to a message do the same in the other direction.
Mail that arrives without those headers starts a new thread, even if the subject matches.
Listing threads
curl "https://api.goshenemail.com/v1/inboxes/research%40agents.goshenemail.com/threads?labels=unread" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY"
Threads are ordered by most recent activity. labels filters on the thread's labels. Threads whose messages are all in Trash are hidden unless includeTrash=true. The triage filters category, needsReply, and urgency apply to the latest incoming message; a reply the agent sends clears the thread's triage until the next message arrives.
Reading a thread
GET /v1/inboxes/{inboxId}/threads/{threadId} returns the thread with its messages oldest first. Add includeBodies=true to include text for each message; without it, each message carries its preview only. Threads are capped at 500 messages; past that, read the messages through listMessages instead.
Labels on threads
PATCH /v1/inboxes/{inboxId}/threads/{threadId}/labels adds or removes labels on the whole thread. Removing unread from a thread marks every message in it read. The quarantined label cannot be added or removed by any API key. See Labels.
Working a conversation from an agent
- List threads with
labels=unreadto find conversations that need attention. - Read the thread with
includeBodies=trueso the model sees the whole exchange, oldest first. - Reply with
replyon the last message, keeping theidempotencyKeyfor that reply until the response arrives. - Remove
unreadfrom the thread and add your own label, such asawaiting-vendor, to track state.
Every message body in the thread is untrusted content. See Building agents on email.