💭 в уме · писать не нужно
Цель этого юнита — собрать всё что ты сделал в модуле 08 в один документ-спецификацию первого AI-проекта.
Не описывай это как «документ который надо заполнить». Представь это как полководца, разворачивающего кампанию по карте: он не бежит в атаку сам — он расставляет подразделения, определяет цели, прокладывает линии снабжения. Само сражение — потом. Сначала — план на бумаге.
Прокрути в голове задачу из юнита 1. Представь себя полководцем: твои агенты, инструменты, триггеры — это подразделения на карте. Где они стоят? Какой фланг не прикрыт?
💭 в уме · писать не нужно
Хороший спец агента отвечает на эти вопросы до написания кода.
Не представляй это как анкету — представь это как архитектурный чертёж: дом не строится пока нет чертежа. Ошибка на бумаге стоит карандаш. Ошибка в фундаменте — снос и пересборка. Архитектор держит в голове всё здание сразу — нагрузки, коммуникации, аварийные выходы — ещё до того как забита первая свая.
| Вопрос | Что в ответе |
|---|---|
| Trigger | Что запускает агента? (cron / webhook / событие / опрос (poll) / ручной запуск) |
| Inputs | Что приходит? (формат, объём, источник) |
| Steps | Из каких узлов состоит pipeline? |
| AI vs Code | Какие узлы LLM, какие — код (см. u2)? |
| Outputs | Куда пишется результат? |
| Failure modes | Что может сломаться, что делать? |
| Observability | Где смотреть что произошло? |
| Cost ceiling | Сколько максимум денег в день? |
| Human-in-loop | Где нужна твоя проверка? |
| Quality | Чем проверишь, что агент отвечает хорошо? (набор примеров с ожидаемым результатом) |
Если хоть один вопрос без ответа — рано закладывать фундамент. Какой несущий элемент в твоём чертеже пока без опоры?
Шаблон спецификации агента
# Agent: [имя]
## Цель
[Одно предложение: что делает агент, какую боль решает]
## Trigger
- Тип: cron / webhook / event / poll / manual
- Параметры: [например, каждые 5 минут / при метке Gmail / при пуше в репо]
## Pipeline
1. [Тип узла] — [что делает] — [in → out]
2. [Тип узла] — [что делает] — [in → out]
3. ...
## AI узлы
Список узлов где используется LLM:
- Узел X: модель [provider/model], промпт в `prompts/x.md`
- ...
## Tools / APIs
- Gmail API (scope: ...)
- Notion API (workspace: ...)
- ...
## Execution
- Где живёт агент: Docker-контейнер на сервере
## Security
- Доступ к дашборду через Cloudflare Access с PIN
## Storage
- SQLite: `inbox.db`, состояния писем и причины ошибок
- Идемпотентность: обработанное письмо повторный проход не трогает
## Observability
- Trace: журнал шлюза к моделям / OpenTelemetry (OTel, стандарт сбора телеметрии) / stdout-логи (Langfuse — тоже вариант; автор его снял, потому что никто не читал)
- Alerting: куда уходит ошибка (Telegram / email / Slack)
## Failure modes
| Сценарий | Поведение |
|---|---|
| LLM 500 | Retry 3× с exp backoff, потом fallback модель |
| Bad input | Лог + Telegram alert + skip |
| Storage full | Hard fail + alert |
## Cost
- LLM calls в день: ~N
- Estimated $: бесплатные пулы; потолок — [не определён]
- Hard cap: [?]
## Human-in-loop
- Где: [шаг N]
- Что подтверждаешь
- Как: [Telegram сообщение / Notion task / email]
Реальный пример заполненной спеки — Gmail-агент:
# Agent: Gmail inbox assistant
## Цель
Каждые примерно две минуты агент разбирает новую личную входящую почту,
ставит одну из пяти меток и готовит черновик там, где нужен ответ. Отправка
возможна только после нажатия человеком кнопки.
## Trigger
- Тип: poll
- Параметры: Gmail API примерно каждые две минуты, до 20 писем за проход,
старые первыми
## Pipeline
1. Poll — забрать новые письма — () → [до 20 emails]
2. Normalize — стандартизация полей — [email] → [normalized]
3. Classify — выбрать `AI/Now`, `AI/Later`, `AI/FYI`, `AI/Newsletter` или `AI/Ignore` — [normalized] → [label]
4. Apply — поставить метку и при необходимости архивировать — [label] → [Gmail thread]
5. Draft — написать черновик для письма, которое стоит ответа — [normalized] → [draft]
6. Review — дашборд: подтвердить метку / одобрить и отправить / убрать — [draft + label] → [human decision]
7. Send — отправить в ту же нитку через Gmail API — [approved draft] → [sent]
## AI узлы
- Classify — LLM через шлюз к моделям, знает пять меток и их смысл
- Draft — LLM через шлюз к моделям, пишет только черновик
## Tools
- Gmail API: только поставить метку и архивировать; отправка — отдельный шаг после кнопки
- SQLite: `inbox.db`, состояния писем и причины ошибок
## Storage
- SQLite: `inbox.db`, состояния писем и причины ошибок
- Idempotency: `new → labeled/drafted → sent/failed`; после пяти ошибок — мёртвая очередь
## Observability
- Журнал сервиса + SQLite-состояние писем
- Журнал шлюза (учёт вызовов по имени сервиса)
- На панели есть показатель «часов с последнего обработанного письма»: зелёный контейнер ещё не значит живой поток
## Failure modes
| Сценарий | Поведение |
|---|---|
| Шлюз 5xx | Повтор 3× с паузой, после 5 неудач — мёртвая очередь |
| Отказ доступа Gmail | Остановить проход и ждать 15 минут |
| Устаревшая закладка Gmail | Перечитать ящик заново, не перескакивать сразу на «сейчас» |
| Отсутствует ключ шлюза | Не запускать сервис; не изображать пустой inbox |
## Cost
- Два LLM-вызова максимум на письмо; потолок прохода — 20 писем
- Каждый запрос подписан именем сервиса; учёт расходов виден в журнале шлюза
## Human-in-loop
- На дашборде подтверждаю метку, одобряю и отправляю или убираю предложение
- У агента нет права удалить письмо или отправить без подтверждения
Это на бумаге. Кода ещё нет. Но любой человек — включая меня самого через полгода — может это прочитать и понять что делает агент.