- Added core documentation for the Team Management feature, including iteration goals, implementation plans, and design specifications. - Introduced new files for team configuration, IPC channels, and UI components for team listing and Kanban board. - Established a clear definition of done and scope for the first iteration, focusing on visible results and graceful degradation in the UI. - Documented the messaging and task file formats, ensuring robust communication between team members. - Implemented a Kanban design with defined states and transitions for task management.
7 KiB
7 KiB
Research: Подходы к отправке сообщений тиммейтам
Сравнение 3 подходов
| Критерий | Inbox-файлы | Agent SDK | CLI subprocess |
|---|---|---|---|
| Скорость | ~5ms | ~12с | 10-15с |
| Стоимость | $0 | $0.01-0.08/msg | токены |
| Работает с запущенными | YES | NO | NO |
| Прерывает mid-turn | NO | NO | NO |
| Требует API ключ | NO | YES | NO |
| Расход памяти | 0 | 0 | 100-320MB |
1. Inbox-файлы (ВЫБРАНО)
Как работает
Прямая запись JSON в файл ~/.claude/teams/{team}/inboxes/{member}.json. Claude Code мониторит эти файлы через fs.watch и доставляет сообщения агентам между turns.
Плюсы
- Мгновенная запись (~5ms)
- $0 — никаких API вызовов
- Единственный способ общаться с запущенными тиммейтами
- Работает с idle и active агентами (но доставка между turns)
Минусы
- Race condition при одновременной записи (см. research-inbox.md)
- Формат недокументирован (internal API)
- Доставка между turns, не real-time
- from: "user" может не работать
Формат сообщения
{
"from": "user",
"text": "Не трогай файл auth.ts, я его сам изменю",
"timestamp": "2026-02-17T15:30:00.000Z",
"read": false,
"summary": "Do not modify auth.ts",
"messageId": "uuid-for-retry-check"
}
2. Agent SDK (ОТВЕРГНУТ)
Как работает
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const response = await client.messages.create({
model: 'claude-opus-4-6',
messages: [{ role: 'user', content: 'Send message to teammate...' }],
tools: [/* SendMessage, TaskUpdate, etc. */]
});
Почему отвергнут
- Создаёт НОВУЮ сессию — не подключается к работающему тиммейту. SendMessage и TaskCreate — это инструменты модели, не программные вызовы
- ~12 секунд на каждый вызов (полный API round-trip)
- Стоит токены — $0.01-0.08 за сообщение
- Нужен API ключ — отдельная оплата, а не подписка Claude
Когда может пригодиться
- Создание новых команд программно
- Автоматизация workflow (вне real-time UI)
3. CLI subprocess (ОТВЕРГНУТ)
Как работает
claude --message "Send message to teammate-1: stop working on X"
Почему отвергнут
- Новый процесс — не инжектится в работающего тиммейта
- 10-15 секунд холодный старт
- 100-320MB памяти на процесс
- Каждый вызов стоит токены
Доставка: Timing и ограничения
Цикл тиммейта
Turn N:
1. Читает inbox → видит новые (read: false)
2. Обрабатывает сообщения/задачи
3. Вызывает инструменты
4. Reasoning
5. Output
→ idle_notification → IDLE
... ожидание ...
Turn N+1:
1. Пробуждение (новое сообщение в inbox / назначение задачи)
2. Читает inbox → видит новые
...
Задержка
- Idle agent: получит при следующем пробуждении (доли секунды если inbox-change triggers)
- Active agent (mid-turn): получит только после завершения текущего turn (1-30 секунд)
Нельзя прервать
Если агент уже вызвал Edit/Bash — инструмент выполнится. Наше сообщение придёт ПОСЛЕ.
Пример:
17:12:30 — Agent начинает Edit на auth.ts
17:12:31 — Мы шлём "Не трогай auth.ts"
17:12:32 — Agent завершает Edit (auth.ts изменён)
17:12:33 — Agent читает inbox, видит наше сообщение
→ Поздно, файл уже изменён
Hard Interrupt (будущее)
Возможные подходы:
- kill -SIGINT процесса тиммейта (жёсткое прерывание, потеря контекста)
- Файловый flag
.interrupt-{member}(нужна поддержка в Claude Code) - API от Anthropic (если появится)
Текущее решение: задержка приемлема, hard interrupt — в будущем.
Финальное решение (после 3 раундов ревью)
Поле from
- Используем
from: "user"— интуитивно и описывает источник - Fallback
from: "team-lead"если агент не реагирует (team-lead всегда есть в config.json members) - Практический тест необходим при первой реализации (см. research-inbox.md)
messageId — обязателен в каждом сообщении
Каждое исходящее сообщение включает messageId: crypto.randomUUID():
{
"from": "user",
"text": "Please review task #12",
"timestamp": "2026-02-17T15:30:00.000Z",
"read": false,
"summary": "Review request for task #12",
"messageId": "550e8400-e29b-41d4-a716-446655440000"
}
Verify: проверка сразу после записи
- После atomic write читаем inbox и ищем наш
messageId - Если не найден — потеря обнаружена → warning в UI (не silent fail)
- Не автоматический retry на MVP
3 состояния offline-участника
| Состояние | Условие | Отображение |
|---|---|---|
ACTIVE |
idle < 5 минут | Зелёный dot |
IDLE |
idle > 5 минут | Жёлтый dot |
TERMINATED |
Получен shutdown_response с approve: true |
Серый dot, "Завершён" |
Определение состояния по timestamp последнего события в inbox (idle_notification, любое сообщение). TERMINATED — исключительно по явному shutdown_response.
Что не входит в MVP
- Автоматический retry при потере сообщения
from: "user"validation через config.json members (проверяем практически)- Hard Interrupt (kill -SIGINT, файловый flag) — Phase 2