> 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.

# Черновики

> Создание, управление и отправка черновиков: сценарии с участием человека и отправка по расписанию.

## Что такое черновик?

`Draft` — это ещё не отправленное `Message`. Ресурс, в котором агент готовит письмо: получатели, тема, тело и `Attachments` — без немедленной отправки.

Надёжность агентов сегодня на первом плане: с `Drafts` письма могут быть готовы к отправке, а уйти в мир только с вашего разрешения.

`Drafts` важны для продвинутых сценариев:

* **Human-in-the-loop:** агент создаёт `Draft` для чувствительного или важного письма; человек проверяет и одобряет перед отправкой.
* **Отправка по расписанию:** агент создаёт `Draft`, отдельный процесс отправляет его в нужное время (например в рабочие часы получателя).
* **Сложная сборка:** если письмо собирается из нескольких шагов (данные из разных источников, генерация текста), черновик сохраняет промежуточное состояние.

## Жизненный цикл `Draft`

От создания до отправки.

### 1. Создать `Draft`

Нужен `Inbox`, от имени которого потом пойдёт отправка.

```python
# Нужен inbox_id для создания черновика

new_draft=client.inboxes.drafts.create(
    inbox_id="outbound@domain.com",
    to=["review-team@example.com"],
    subject="[NEEDS REVIEW] Agent's proposed response"
)

print(f"Draft created successfully with ID: {new_draft.draft_id}")

```

**`TypeScript`**

```typescript title="TypeScript"
// Нужен inbox_id для создания черновика

const newDraft = await client.inboxes.drafts.create(
	"my_inbox@domain.com",
	{
		to: [
				"review-team@example.com"
			],
		subject: "[NEEDS REVIEW] Agent's proposed response"
	}
)

console.log(`Draft created successfully with ID: ${newDraft.id}`);
```

**`CLI`**

```bash title="CLI"
# создать черновик в inbox
agentinbox inboxes:drafts create \
  --inbox-id outbound@domain.com \
  --to review-team@example.com \
  --subject "[NEEDS REVIEW] Agent's proposed response"
```

### 2. Получить `Draft`

После создания — по ID.

**`Python`**

```python title="Python"
# Получить черновик
draft = client.inboxes.drafts.get(inbox_id = "my_inbox@domain.com", draft_id = "draft_id_123")

```

**`TypeScript`**

```typescript title="TypeScript"

// Получить черновик
const draft = await client.inboxes.drafts.get(
	"inbox_id",
	"draft_id_123"
)

```

**`CLI`**

```bash title="CLI"
# получить черновик по id
agentinbox inboxes:drafts retrieve \
  --inbox-id my_inbox@domain.com \
  --draft-id draft_id_123
```

### 3. Отправить `Draft`

Финальный шаг: черновик превращается в отправленное `Message` и удаляется.

**`Python`**

```python title="Python"

# Отправка удаляет черновик

sent_message = client.inboxes.drafts.send(inbox_id = 'my_inbox@domain.com', draft_id = 'draft_id_123')

print(f"Draft sent! New message ID: {sent_message.message_id}")

```

**`TypeScript`**

```typescript title="TypeScript"

const sentMessage = await client.inboxes.drafts.send('my_inbox@domain.com', 'draft_id_123');

console.log(`Draft sent! New message ID: ${sentMessage.message_id}`);
```

**`CLI`**

```bash title="CLI"
# отправить черновик
agentinbox inboxes:drafts send \
  --inbox-id my_inbox@domain.com \
  --draft-id draft_id_123
```

Дальше к письму обращайтесь уже по `message_id` — это уже сообщение.

## Отправка по расписанию

Черновик можно запланировать на будущее, передав поле `send_at` при создании или обновлении. Agent Inbox отправит его в указанное время — без cron и опроса.

### Запланировать `Draft`

Передайте дату-время в формате ISO 8601 в `send_at`. Черновик автоматически получит метку `scheduled`, а `send_status` станет `scheduled`.

**`Python`**

```python title="Python"
from datetime import datetime, timedelta

# Завтра в 9:00 UTC
send_time = (datetime.utcnow() + timedelta(days=1)).replace(
    hour=9, minute=0, second=0
)

scheduled_draft = client.inboxes.drafts.create(
    inbox_id="outreach@domain.com",
    to=["prospect@example.com"],
    subject="Following up on our conversation",
    text="Hi, just wanted to follow up on our chat yesterday...",
    send_at=send_time.isoformat() + "Z"
)

print(f"Draft scheduled for {scheduled_draft.send_at}")
# send_status будет "scheduled"
```

**`TypeScript`**

```typescript title="TypeScript"
// Завтра в 9:00 UTC
const sendTime = new Date();
sendTime.setUTCDate(sendTime.getUTCDate() + 1);
sendTime.setUTCHours(9, 0, 0, 0);

const scheduledDraft = await client.inboxes.drafts.create(
    "outreach@domain.com",
    {
        to: ["prospect@example.com"],
        subject: "Following up on our conversation",
        text: "Hi, just wanted to follow up on our chat yesterday...",
        sendAt: sendTime.toISOString()
    }
);

console.log(`Draft scheduled for ${scheduledDraft.sendAt}`);
// sendStatus будет "scheduled"
```

**`CLI`**

```bash title="CLI"
# запланировать черновик на завтра 9:00 UTC
agentinbox inboxes:drafts create \
  --inbox-id outreach@domain.com \
  --to prospect@example.com \
  --subject "Following up on our conversation" \
  --text "Hi, just wanted to follow up on our chat yesterday..." \
  --send-at 2026-04-01T09:00:00Z
```

### Отмена или перенос

Чтобы отменить запланированную отправку — удалите `Draft`. Чтобы перенести — обновите `send_at`.

**`Python`**

```python title="Python"
# Перенос на другое время
new_time = (datetime.utcnow() + timedelta(days=3)).replace(hour=14, minute=0, second=0)
client.inboxes.drafts.update(
    inbox_id="outreach@domain.com",
    draft_id=scheduled_draft.draft_id,
    send_at=new_time.isoformat() + "Z"
)

# Или отмена полным удалением черновика
client.inboxes.drafts.delete(
    inbox_id="outreach@domain.com",
    draft_id=scheduled_draft.draft_id
)
```

**`TypeScript`**

```typescript title="TypeScript"
// Перенос
const newTime = new Date();
newTime.setUTCDate(newTime.getUTCDate() + 3);
newTime.setUTCHours(14, 0, 0, 0);

await client.inboxes.drafts.update(
    "outreach@domain.com",
    scheduledDraft.draftId,
    { sendAt: newTime.toISOString() }
);

// Отмена удалением
await client.inboxes.drafts.delete(
    "outreach@domain.com",
    scheduledDraft.draftId
);
```

**`CLI`**

```bash title="CLI"
# перенос
agentinbox inboxes:drafts update \
  --inbox-id outreach@domain.com \
  --draft-id scheduled_draft_id \
  --send-at 2026-04-02T14:00:00Z

# отмена удалением
agentinbox inboxes:drafts delete \
  --inbox-id outreach@domain.com \
  --draft-id scheduled_draft_id
```

### Список запланированных `Draft`

Если при создании указан `send_at`, ставится метка `scheduled`. Фильтр по параметру `labels`.

**`Python`**

```python title="Python"
# Все запланированные черновики в inbox
scheduled = client.inboxes.drafts.list(
    inbox_id="outreach@domain.com",
    labels=["scheduled"]
)

for draft in scheduled.drafts:
    print(f"{draft.subject} — scheduled for {draft.send_at} ({draft.send_status})")
```

**`TypeScript`**

```typescript title="TypeScript"
const scheduled = await client.inboxes.drafts.list(
    "outreach@domain.com",
    { labels: ["scheduled"] }
);

for (const draft of scheduled.drafts) {
    console.log(`${draft.subject} — scheduled for ${draft.sendAt} (${draft.sendStatus})`);
}
```

**`CLI`**

```bash title="CLI"
# запланированные черновики в inbox
agentinbox inboxes:drafts list \
  --inbox-id outreach@domain.com \
  --label scheduled
```

> **Значения send_status**
>
> * `scheduled` — в очереди, отправка в момент `send_at`.
> * `sending` — идёт отправка.
> * `failed` — ошибка отправки. Повтор: обновите `send_at` на новое время.

### Условные фоллоу-апы

Частый паттерн: «фоллоу-ап через 3 дня, если не ответили». Создайте запланированный черновик фоллоу-апа и отмените его через `Webhook`, если пришёл ответ.

**1. Первое письмо и план фоллоу-апа:**

**`Python`**

```python title="Python"
from datetime import datetime, timedelta

inbox_id = "outreach@domain.com"

# Первое письмо
initial = client.inboxes.messages.send(
    inbox_id=inbox_id,
    to=["prospect@example.com"],
    subject="Quick question about your workflow",
    text="Hi, I noticed your team is scaling quickly..."
)

# Фоллоу-ап через 3 дня
follow_up_time = (datetime.utcnow() + timedelta(days=3)).replace(hour=9, minute=0, second=0)

follow_up = client.inboxes.drafts.create(
    inbox_id=inbox_id,
    to=["prospect@example.com"],
    subject="Re: Quick question about your workflow",
    text="Hi again — just bumping this in case it got buried...",
    in_reply_to=initial.message_id,
    send_at=follow_up_time.isoformat() + "Z"
)

# Метка на треде для обработчика вебхука
client.inboxes.threads.update(
    inbox_id=inbox_id,
    thread_id=initial.thread_id,
    add_labels=[f"follow-up:{follow_up.draft_id}"]
)
```

**`TypeScript`**

```typescript title="TypeScript"
const inboxId = "outreach@domain.com";

const initial = await client.inboxes.messages.send(inboxId, {
    to: ["prospect@example.com"],
    subject: "Quick question about your workflow",
    text: "Hi, I noticed your team is scaling quickly..."
});

const followUpTime = new Date();
followUpTime.setUTCDate(followUpTime.getUTCDate() + 3);
followUpTime.setUTCHours(9, 0, 0, 0);

const followUp = await client.inboxes.drafts.create(inboxId, {
    to: ["prospect@example.com"],
    subject: "Re: Quick question about your workflow",
    text: "Hi again — just bumping this in case it got buried...",
    inReplyTo: initial.messageId,
    sendAt: followUpTime.toISOString()
});

await client.inboxes.threads.update(inboxId, initial.threadId, {
    addLabels: [`follow-up:${followUp.draftId}`]
});
```

**`CLI`**

```bash title="CLI"
# первое письмо
agentinbox inboxes:messages send \
  --inbox-id outreach@domain.com \
  --to prospect@example.com \
  --subject "Quick question about your workflow" \
  --text "Hi, I noticed your team is scaling quickly..."

# фоллоу-ап через 3 дня
agentinbox inboxes:drafts create \
  --inbox-id outreach@domain.com \
  --to prospect@example.com \
  --subject "Re: Quick question about your workflow" \
  --text "Hi again — just bumping this in case it got buried..." \
  --in-reply-to initial_message_id \
  --send-at 2026-04-03T09:00:00Z
```

**2. Отмена при ответе (вебхук):**

При входящем ответе ищите на треде метку `follow-up:<draft_id>` и удалите черновик.

**`Python`**

```python title="Python"
# В обработчике вебхука для "message.received":
thread = client.inboxes.threads.get(inbox_id=inbox_id, thread_id=thread_id)

for label in thread.labels:
    if label.startswith("follow-up:"):
        draft_id = label.split("follow-up:")[1]
        try:
            client.inboxes.drafts.delete(inbox_id=inbox_id, draft_id=draft_id)
        except Exception:
            pass  # Черновик мог уже уйти
        client.inboxes.threads.update(
            inbox_id=inbox_id, thread_id=thread_id,
            remove_labels=[label]
        )
        break
```

**`TypeScript`**

```typescript title="TypeScript"
// В обработчике вебхука для "message.received":
const thread = await client.inboxes.threads.get(inboxId, threadId);

for (const label of thread.labels) {
    if (label.startsWith("follow-up:")) {
        const draftId = label.split("follow-up:")[1];
        try {
            await client.inboxes.drafts.delete(inboxId, draftId);
        } catch {
            // Черновик мог уже уйти
        }
        await client.inboxes.threads.update(inboxId, threadId, {
            removeLabels: [label]
        });
        break;
    }
}
```

Если лид ответил — фоллоу-ап отменяется. Если нет — уходит по расписанию.

## Организация: все `Draft` по организации

Как и для `Threads`, можно получить все `Draft` по всей `Organization` — удобно для единой панели, где супервайзер видит, одобряет или удаляет черновики любых агентов.

**`Python`**

```python title="Python"
# Все черновики организации
all_drafts = client.drafts.list()

print(f"Found {all_drafts.count} drafts pending review.")

```

**`TypeScript`**

```typescript title="TypeScript"
const allDrafts = await client.drafts.list();

console.log(`Found ${allDrafts.count} drafts pending review.`);
```

**`CLI`**

```bash title="CLI"
# все черновики организации
agentinbox drafts list
```

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

**`Python`**

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

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

API reference:
- inboxes.drafts.create(inbox_id, to, subject?, text?, html?, cc?, bcc?, reply_to?, attachments?, send_at?)
- inboxes.drafts.get(inbox_id, draft_id)
- inboxes.drafts.update(inbox_id, draft_id, to?, subject?, text?, html?, send_at?, ...)
- inboxes.drafts.send(inbox_id, draft_id) — converts to Message, deletes draft
- inboxes.drafts.delete(inbox_id, draft_id)
- inboxes.drafts.list(inbox_id, limit?, page_token?, labels?)
- drafts.list(limit?, page_token?) — org-wide

Scheduled sending: pass send_at (ISO 8601 datetime) to create() or update().
Draft is auto-labeled 'scheduled' and sent at the specified time.
send_status: 'scheduled' | 'sending' | 'failed'.
Cancel by deleting the draft. Reschedule by updating send_at.

Errors: SDK raises on 4xx/5xx. Rate limit: 429 with Retry-After.
"""
import os
from datetime import datetime, timedelta
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"

# Create and send immediately
draft = client.inboxes.drafts.create(inbox_id, to=["review@example.com"], subject="[REVIEW] Proposed reply")
sent = client.inboxes.drafts.send(inbox_id, draft.draft_id)
print(sent.message_id)

# Schedule for later
send_time = (datetime.utcnow() + timedelta(days=1)).replace(hour=9, minute=0, second=0)
scheduled = client.inboxes.drafts.create(
    inbox_id, to=["prospect@example.com"], subject="Follow up",
    text="Just following up...", send_at=send_time.isoformat() + "Z"
)
print(f"Scheduled for {scheduled.send_at}, status: {scheduled.send_status}")

all_drafts = client.drafts.list()
```

**`TypeScript`**

```typescript title="TypeScript"
/**
 * Agent Inbox Drafts — copy into Cursor/Claude.
 *
 * Setup: npm install agentinbox dotenv. Set AGENTINBOX_API_KEY in .env.
 *
 * API reference:
 * - inboxes.drafts.create(inboxId, { to, subject?, text?, html?, cc?, bcc?, replyTo?, attachments?, sendAt? })
 * - inboxes.drafts.get(inboxId, draftId)
 * - inboxes.drafts.update(inboxId, draftId, { to?, subject?, text?, html?, sendAt?, ... })
 * - inboxes.drafts.send(inboxId, draftId) — converts to Message, deletes draft
 * - inboxes.drafts.delete(inboxId, draftId)
 * - inboxes.drafts.list(inboxId, { limit?, pageToken?, labels? })
 * - drafts.list({ limit?, pageToken? }) — org-wide
 *
 * Scheduled sending: pass sendAt (ISO 8601 datetime) to create() or update().
 * Draft is auto-labeled 'scheduled' and sent at the specified time.
 * sendStatus: 'scheduled' | 'sending' | 'failed'.
 * Cancel by deleting the draft. Reschedule by updating sendAt.
 *
 * 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";

  // Create and send immediately
  const draft = await client.inboxes.drafts.create(inboxId, {
    to: ["review@example.com"],
    subject: "[REVIEW] Proposed reply",
  });
  const sent = await client.inboxes.drafts.send(inboxId, draft.draftId);
  console.log(sent.messageId);

  // Schedule for later
  const sendTime = new Date();
  sendTime.setUTCDate(sendTime.getUTCDate() + 1);
  sendTime.setUTCHours(9, 0, 0, 0);

  const scheduled = await client.inboxes.drafts.create(inboxId, {
    to: ["prospect@example.com"],
    subject: "Follow up",
    text: "Just following up...",
    sendAt: sendTime.toISOString(),
  });
  console.log(`Scheduled for ${scheduled.sendAt}, status: ${scheduled.sendStatus}`);

  const allDrafts = await client.drafts.list();
}
main();
```