Inboxes

Give an AI agent its own email address. Mail to it arrives as threads, with a webhook for each message, and the agent replies from the same address.

An inbox is an email address of an environment, usually one per agent (or per user an agent works for). Mail sent to it is kept as threads, conversations of messages, and each message that arrives sends an inbox.message.received webhook. The agent reads the thread and replies from the inbox's address; the reply lands in the same thread, and so does the answer to it.

Inboxes build on receiving and sending: an inbound message is a received email, an outbound one is an email, with its usual delivery events.

Quickstart

Create an inbox. Without a domain, its address is at the environment's own domain under coss.com's inbound domain, which needs no DNS setup:

const { :  } = await ..({
  : "support-agent",
  : "Acme Support",
  : "agent-42", // your own id: creating it again returns this inbox
});

.(?.); // support-agent@k3j9x2m7qp4l.inbound.coss.com

Then handle inbox.message.received (subscribe a webhook endpoint to it, or run coss listen while you develop): read the thread and reply.

const  = await (await .(), ., );
if (. === "inbox.message.received" && !..) {
  const { , ,  } = .;
  const { :  } = await ...(, );

  // `extracted_text` is each message's own words, without the quoted conversation.
  const  = (?. ?? [])
    .(() => `${. === "inbound" ? . : "You"}: ${.}`)
    .("\n\n");

  await ...(
    ,
    ,
    { : await () },
    { : `reply-${}` }, // a redelivered webhook won't reply twice
  );
}

The reply goes to the sender (their Reply-To, when they set one) with Re: and the headers mail clients thread by. reply_all: true also answers everyone else on the message. To start a conversation instead, send a message from the inbox:

const { :  } = await ...(, {
  : "jane@example.com",
  : "Your order",
  : "Hi Jane, your order has shipped. Reply here with any questions.",
});
.(?., ?.);

Addresses and sending

  • Live environments send only from your own verified domains: to send from an inbox, set up receiving on a subdomain of a verified domain (e.g. agents.acme.com) and create the inbox there with domain: "agents.acme.com". An inbox's can_send says whether it can send.
  • Sandbox environments (coss_test_… keys) send from every inbox and deliver nothing, like every sandbox send. Mail sent to a sandbox inbox is still received, so you can test the whole loop with your own mail client.
  • Usernames are lower-case letters, digits, ., _ and -. Mail to username+anything@domain reaches the inbox too, so an agent can hand out one address per task.
  • Messages from an inbox are ordinary emails: they count against the send quota and your plan's emails, appear in the environment's emails and logs, and are never tracked (no pixel, no rewritten links).
  • An environment can have up to 1,000 inboxes.

Inboxes and received emails

Every inbound message is also a received email of the environment: email.received fires too, and the email shows under Received emails. Subscribe to inbox.message.received for inbox mail only. Deleting an inbox deletes its threads, not their emails; mail to its address is then received like any other mail to the environment's domain.

Messages follow the retention of their emails: inbound messages are deleted with their received email, outbound ones with their email, and a thread whose messages are all gone disappears.