Skip to navigation

Черновики

Подготовка и отложенная отправка сообщений для агентов.

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

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

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

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

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

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

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

1. Создать Draft

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

# Нужен 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}")

2. Получить Draft

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

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

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

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

# Отправка удаляет черновик
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}")

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

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

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

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

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

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"

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

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

# Перенос на другое время
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
)

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

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

# Все запланированные черновики в 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})")
Значения send_status
  • scheduled — в очереди, отправка в момент send_at.
  • sending — идёт отправка.
  • failed — ошибка отправки. Повтор: обновите send_at на новое время.

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

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

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

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}"]
)

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

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

# В обработчике вебхука для "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

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

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

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

# Все черновики организации
all_drafts = client.drafts.list()
print(f"Found {all_drafts.count} drafts pending review.")

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

"""
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()