> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://agentinbox.space/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://agentinbox.space/_mcp/server.

# Сообщения

> Узнайте, как отправлять, получать и управлять письмами как объектами Message в API Agent Inbox.

## Что такое Message?

В экосистеме Agent Inbox `Message` — это представление обычного письма, ориентированное на API. Это структурированный объект со всем привычным: отправитель, получатели, тема и тело.

Каждое `Message` живёт внутри `Thread`, чтобы беседы оставались упорядоченными. При отправке нового `Message` создаётся новый `Thread`. При ответе новое `Message` добавляется в существующий `Thread` — как в обычной почтовой переписке.

В Agent Inbox удобно подключать людей к диалогам агента: в любое сообщение можно добавить реального человека в `cc` или `bcc`, чтобы построить сценарий «человек в контуре» для контроля, эскалаций или проверки качества.

## Основные возможности

С ресурсом `Message` можно работать по-разному: отправлять новые письма и просматривать историю переписки.

### 1. Инициализация клиента

Сначала инициализируйте клиент Agent Inbox с API-ключом — через него выполняются все вызовы API.

**`Python`**

```python title="Python"
from agentinbox import Agentinbox

client = Agentinbox(api_key="YOUR_API_KEY")

```

**`TypeScript`**

```typescript title="TypeScript"
import { AgentinboxClient } from "agentinbox";

const client = new AgentinboxClient({ apiKey: "YOUR_API_KEY" });
```

### 2. Отправка нового `Message`

Чтобы начать новую беседу, отправьте `Message` из одного из ваших ящиков. Будет создан новый `Thread`, а в ответ вернётся объект `Message`.

```python
# You'll need an inbox ID to send from.
# Let's assume we have one:

sent_message = client.inboxes.messages.send(
inbox_id = 'my_inbox@domain.com',
to = 'recipient@domain.com',
labels=[
"outreach",
"startup"
],
subject="[YC S25] Founder Reachout ",
text="Hello, I'm Michael, and I'm a founder at Agent Inbox...",
html="<div dir=\"ltr\">Hello,<br /><br />I'm Michael, and I'm a founder at Agent Inbox..."
)
print(f"Message sent successfully with ID: {sent_message.message_id}")

```

**`TypeScript`**

```typescript title="TypeScript"
// You'll need an inbox ID to send from.

const sentMessage = await client.inboxes.messages.send(
	"outreach@agentinbox.space", // this is your inbox you are trying to send from
	{
    to: "recipient@domain.com",
		labels: [
				"outreach",
				"startup"
		],
		subject: "[YC S25] Founder Reachout ",
		text: "Hello, I'm Michael, and I'm a founder at Agent Inbox...",
		html: "<div dir=\"ltr\">Hello,<br /><br />I'm Michael, and I'm a founder at Agent Inbox..."
	}
)

console.log(`Message sent successfully with ID: ${sentMessage.id}`);
```

**`CLI`**

```bash title="CLI"
# send a new message with labels
agentinbox inboxes:messages send \
  --inbox-id outreach@agentinbox.space \
  --to recipient@domain.com \
  --subject "[YC S25] Founder Reachout " \
  --text "Hello, I'm Michael, and I'm a founder at Agent Inbox..." \
  --html "<div dir=\"ltr\">Hello,<br /><br />I'm Michael, and I'm a founder at Agent Inbox..." \
  --label outreach \
  --label startup
```

> **Warning**
>
> **Лимит получателей:** при каждой отправке или ответе не более **50 получателей** в сумме по полям `to`, `cc` и `bcc`. При превышении API вернёт ошибку.

### 3. Список `Messages` в `Inbox`

Можно получить список всех `Messages` в конкретном `Inbox` — удобно для истории переписки.

```python
all_messages = client.inboxes.messages.list(inbox_id='my_inbox@agentinbox.space')

print(f"Found {all_messages.count} messages in the inbox.")

```

**`TypeScript`**

```typescript title="TypeScript"

const allMessages = await client.inboxes.messages.list("outreach@agentinbox.space")

console.log(`Found ${allMessages.count} messages in the inbox.`);
```

**`CLI`**

```bash title="CLI"
# list all messages in an inbox
agentinbox inboxes:messages list --inbox-id outreach@agentinbox.space
```

### 4. Ответ на `Message`

Ответ на существующее `Message` добавляет новое `Message` в тот же `Thread`.

```python
# Python example
reply = client.inboxes.messages.reply(
    inbox_id='my_inbox@domain.com'
    message_id='<abc123@agentinbox.space>',
    text="Thanks for the referral!",
    attachments=[
        SendAttachment(
            content="resume" # this would obviously be your resume content, refer to the attachment section of the core-concepts for more details
        )
    ]
)

print(f"Reply sent successfully with ID: {reply.message_id}")

```

**`TypeScript`**

```typescript title="TypeScript"


const reply = await client.inboxes.messages.reply(
	"my_inbox@domain.com",
	"<abc123@agentinbox.space>",
	{
		text: "Thanks for the referral!",
		attachments: [
			{
				content: "resume"
			}
		]
	}
)

console.log(`Reply sent successfully with ID: ${reply.id}`);
```

**`CLI`**

```bash title="CLI"
# reply to a message with an attachment
agentinbox inboxes:messages reply \
  --inbox-id my_inbox@domain.com \
  --message-id "<abc123@agentinbox.space>" \
  --text "Thanks for the referral!" \
  --attachment.content "resume" \
  --attachment.filename "resume.pdf"
```

> **Note**
>
> В ответе `inbox_id` — это ящик, **с которого** вы отправляете. В отличие от
> сценария send, здесь нужно явно указать один из потенциально многих `Inboxes`.

### 5. Получение `Message`

Детали конкретного `Message` запрашиваются по его ID вместе с `inbox_id`, к которому оно относится.

**`Python`**

```python title="Python"

message = client.inboxes.messages.get(inbox_id = 'my_inbox@agentinbox.space', message_id = '<abc123@agentinbox.space>')

print(f"Retrieved message with subject: {message.subject}")

```

**`TypeScript`**

```typescript title="TypeScript"

await client.inboxes.messages.get(
	"my_inbox@domain.com",
	"<abc123@agentinbox.space>"
)

console.log(`Retrieved message with subject: ${message.subject}`);
```

**`CLI`**

```bash title="CLI"
# retrieve a specific message
agentinbox inboxes:messages retrieve \
  --inbox-id my_inbox@agentinbox.space \
  --message-id "<abc123@agentinbox.space>"
```

При получении ответов и пересылок для только нового текста используйте `extracted_text` или `extracted_html` — цитируемая история отрезается автоматически.

## Копировать в Cursor / Claude

Скопируйте один из блоков ниже в Cursor или Claude, чтобы за один раз передать полное описание API сообщений.

**`Python`**

```python title="Python"
"""
Agent Inbox Messages — copy into Cursor/Claude.

Setup: pip install agentinbox python-dotenv. Set AGENTINBOX_API_KEY in .env.

API reference:
- messages.send(inbox_id, to, subject, text, html?, cc?, bcc?, reply_to?, labels?, attachments?)
- messages.list(inbox_id, limit?, page_token?, labels?)
- messages.get(inbox_id, message_id)
- messages.reply(inbox_id, message_id, text, html?, attachments?, reply_all?)
- messages.forward(inbox_id, message_id, to, subject?, text?, html?)
- messages.update(inbox_id, message_id, add_labels?, remove_labels?)
- messages.get_attachment(inbox_id, message_id, attachment_id)
- messages.get_raw(inbox_id, message_id)

Reply content: use extracted_text/extracted_html for new content without quoted history.
Errors: SDK raises on 4xx/5xx. Rate limit: 429 with Retry-After.
"""
import os
from dotenv import load_dotenv
from agentinbox import Agentinbox

load_dotenv()
client = Agentinbox(api_key=os.getenv("AGENTINBOX_API_KEY"))

inbox_id = "agent@agentinbox.space"

# Send
sent = client.inboxes.messages.send(inbox_id, to="user@example.com", subject="Hi", text="Body", labels=["outreach"])
print(sent.message_id, sent.thread_id)

# List, get
res = client.inboxes.messages.list(inbox_id, limit=10)
for msg in res.messages:
    content = msg.extracted_text or msg.text
msg = client.inboxes.messages.get(inbox_id, res.messages[0].message_id)

# Reply
reply = client.inboxes.messages.reply(inbox_id, msg.message_id, text="Thanks!")
```

**`TypeScript`**

```typescript title="TypeScript"
/**
 * Agent Inbox Messages — copy into Cursor/Claude.
 *
 * Setup: npm install agentinbox dotenv. Set AGENTINBOX_API_KEY in .env.
 *
 * API reference:
 * - messages.send(inboxId, { to, subject, text, html?, cc?, bcc?, replyTo?, labels?, attachments? })
 * - messages.list(inboxId, { limit?, pageToken?, labels? })
 * - messages.get(inboxId, messageId)
 * - messages.reply(inboxId, messageId, { text, html?, attachments?, replyAll? })
 * - messages.forward(inboxId, messageId, { to, subject?, text?, html? })
 * - messages.update(inboxId, messageId, { addLabels?, removeLabels? })
 * - messages.getAttachment(inboxId, messageId, attachmentId)
 * - messages.getRaw(inboxId, messageId) -> { message_id, size, download_url, expires_at } (S3 presigned URL for .eml)
 * - messages.getRaw(inboxId, messageId)
 *
 * Reply content: use extractedText/extractedHtml for new content without quoted history.
 * Errors: SDK throws on 4xx/5xx. Rate limit: 429 with Retry-After.
 */
import { AgentinboxClient } from "agentinbox";
import "dotenv/config";

const client = new AgentinboxClient({ apiKey: process.env.AGENTINBOX_API_KEY! });

async function main() {
  const inboxId = "agent@agentinbox.space";

  const sent = await client.inboxes.messages.send(inboxId, {
    to: "user@example.com",
    subject: "Hi",
    text: "Body",
    labels: ["outreach"],
  });
  console.log(sent.messageId, sent.threadId);

  const res = await client.inboxes.messages.list(inboxId, { limit: 10 });
  for (const msg of res.messages) {
    const content = msg.extractedText ?? msg.text;
  }
  const msg = await client.inboxes.messages.get(inboxId, res.messages[0].messageId);

  await client.inboxes.messages.reply(inboxId, msg.messageId, { text: "Thanks!" });
}
main();
```

### Тело письма: HTML, текст и CSS

При отправке `Message` тело можно задать в двух форматах: `text` — простой текст, `html` — разметка со стилями.

* `text`: обычная строка без форматирования. Запасной вариант для клиентов без HTML.
* `html`: HTML-документ для оформления, цветов, шрифтов и изображений.

> **Tip**
>
> **Рекомендация:** всегда отправляйте и `text`, и `html`.

## Зачем и текст, и HTML?

Современные клиенты чаще показывают HTML, но не все умеют его рендерить — текстовый вариант гарантирует читаемость. Кроме того, это заметно улучшает доставляемость.

#### Стилизация через CSS

Чтобы стилизовать HTML в `Message`, встраивайте CSS в тег `<style>` внутри `<head>` тела запроса — так надёжнее для Gmail, Outlook и Apple Mail.

Пример аккуратного заголовка письма в HTML:

**`Styled HTML Email Example`**

```html title="Styled HTML Email Example"
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Agent Inbox Invoice</title>
    <style>
      body {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
        line-height: 1.6;
        color: #333;
        max-width: 600px;
        margin: 0 auto;
        padding: 20px;
        background-color: #f8f9fa;
      }
      .email-wrapper {
        background: #ffffff;
        border: 1px solid #e9ecef;
        border-radius: 8px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
        overflow: hidden;
      }
      .email-header {
        background-color: #000000;
        color: #ffffff;
        padding: 24px;
        text-align: center;
      }
      .email-header h1 {
        margin: 0;
        font-size: 24px;
        font-weight: 600;
      }
      .email-content {
        padding: 32px;
      }
      .greeting {
        font-size: 18px;
        font-weight: 500;
        margin-bottom: 24px;
      }
      .main-message {
        font-size: 16px;
        margin-bottom: 24px;
      }
      .cta-button {
        display: inline-block;
        padding: 12px 24px;
        background-color: #1a73e8;
        color: #ffffff;
        text-decoration: none;
        border-radius: 6px;
        font-weight: 500;
        font-size: 16px;
        margin-top: 8px;
        margin-bottom: 24px;
      }
      .invoice-details {
        background-color: #f8f9fa;
        padding: 16px;
        border-radius: 6px;
        margin-bottom: 24px;
        border: 1px solid #dee2e6;
      }
      .invoice-details p {
        margin: 0;
        font-size: 14px;
      }
      .invoice-details strong {
        color: #000;
      }
      .signature {
        margin-top: 24px;
        font-size: 14px;
        color: #555;
      }
      .email-footer {
        text-align: center;
        padding: 20px;
        font-size: 12px;
        color: #6c757d;
      }
      .email-footer a {
        color: #1a73e8;
        text-decoration: none;
      }
    </style>
  </head>
  <body>
    <div class="email-wrapper">
      <div class="email-header">
        <h1>Agent Inbox</h1>
      </div>
      <div class="email-content">
        <div class="greeting">Hi there,</div>
        <div class="main-message">
          Your invoice for the period of October 2025 is ready. We've automatically charged your saved payment method. Thank you for your business!
        </div>

        <div class="invoice-details">
          <p><strong>Invoice Number:</strong> INV-2025-10-0123</p>
          <p><strong>Amount:</strong> $49.00</p>
          <p><strong>Status:</strong> Paid</p>
        </div>

        <a href="#" class="cta-button">View Full Invoice</a>

        <div class="signature">
          Best regards,<br />
          The Agent Inbox Team
        </div>
      </div>
    </div>
    <div class="email-footer">
      <p>&copy; 2025 Agent Inbox, Inc. All Rights Reserved.</p>
      <p><a href="#">Unsubscribe</a> | <a href="#">Billing Settings</a></p>
    </div>
  </body>
</html>
```

## Замечание о наличии поля `text`

Поля `text` и `preview` у входящего `Message` берутся из MIME-части `text/plain`. Некоторые клиенты — в частности Gmail и Outlook — пересылают письма только в HTML без текстовой части. Тогда `text` и `preview` могут отсутствовать.

При обработке входящих сообщений считайте основным источником `html`, а `text` — опциональным.

## Получение `Messages`

Периодический список `Messages` возможен, но для входящей почты агентам эффективнее **вебхуки**. Настроив endpoint, вы получаете уведомление сразу при новом `Message` и можете сразу реагировать.

#### [Руководство: вебхуки](/overview)

Как настроить вебхуки для обработки сообщений в реальном времени.

### Пометка сообщений как прочитанных

В Agent Inbox нет отдельного endpoint «пометить прочитанным» — состояние читается через [метки](/labels). Так обычно избегают повторной обработки одних и тех же писем агентом.

**`Python`**

```python title="Python"
# Mark a message as read after processing
client.inboxes.messages.update(
    inbox_id="agent@agentinbox.space",
    message_id=msg.message_id,
    add_labels=["read"],
    remove_labels=["unread"]
)

# Only fetch unread messages
unread = client.inboxes.messages.list(
    inbox_id="agent@agentinbox.space",
    labels=["unread"]
)
```

**`TypeScript`**

```typescript title="TypeScript"
// Mark a message as read after processing
await client.inboxes.messages.update(
  "agent@agentinbox.space",
  msg.messageId,
  {
    addLabels: ["read"],
    removeLabels: ["unread"],
  }
);

// Only fetch unread messages
const unread = await client.inboxes.messages.list(
  "agent@agentinbox.space",
  { labels: ["unread"] }
);
```

**`CLI`**

```bash title="CLI"
# mark a message as read after processing
agentinbox inboxes:messages update \
  --inbox-id agent@agentinbox.space \
  --message-id "<message_id>" \
  --add-label read \
  --remove-label unread

# only fetch unread messages
agentinbox inboxes:messages list \
  --inbox-id agent@agentinbox.space \
  --label unread
```

> **Как не обрабатывать дубликаты**
>
> Если агент использует вебхуки, сразу после обработки помечайте сообщение как `read` (или `processed`). После перезапуска или повторной обработки фильтруйте по `labels=["unread"]`, чтобы пропускать уже обработанные письма.