惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
月光博客
月光博客
The GitHub Blog
The GitHub Blog
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
T
Tailwind CSS Blog
美团技术团队
D
Docker
V
Visual Studio Blog
Martin Fowler
Martin Fowler
博客园 - 聂微东
The Cloudflare Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания
Как я проектировал очередь задач для работы с AI-агентом
J3d1fm · 2026-06-07 · via Все публикации подряд на Хабре

Средний

6 мин

4.8K

Когда я начал регулярно работать с AI-агентом, выяснилась неприятная вещь: само выполнение задачи часто уже не было главным узким местом. Узкое место появлялось раньше. Нужно было каждый раз вручную понять, какие задачи вообще можно отдать агенту, какие должен сделать человек, какие уже выполнены, но требуют проверки, а какие нельзя двигать без внешнего решения или доступа.

То есть вместе с AI появился новый слой работы: диспетчеризация. До этого я воспринимал таск-трекер как список дел. После нескольких недель работы с агентами стало понятно, что список дел сам по себе не отвечает на главный операционный вопрос:

кто должен сделать следующий шаг?

Именно из этого вопроса выросла маленькая система очередей для работы человека и AI-агента. В этой статье разберу модель, API и архитектурные решения, которые в итоге оказались полезными.

Почему обычная доска задач плохо ложится на agent workflow

Обычная доска хорошо показывает, что задача существует. Например, есть колонки Backlog, In progress, Done. Этого хватает, пока все задачи делает человек или команда людей.

С AI-агентом появляется дополнительное состояние, которого в классической доске обычно нет. Агент может уже сделать работу, но человек еще не принял результат. Или задача может быть технически исполнимой, но агенту не хватает доступа. Или наоборот: задача выглядит сложной, но для агента она полностью готова, потому что контекст, репозиторий и критерий готовности уже известны.

В результате простая колонка In progress перестает быть достаточно точной. В ней могут лежать совершенно разные ситуации:

  • задача сейчас делается человеком;

  • задача сейчас делается агентом;

  • агент закончил, но результат должен проверить человек;

  • задача заблокирована секретом, логином или решением;

  • задача не имеет владельца следующего действия.

Проблема не в названии колонки. Проблема в том, что система не отделяет жизненный цикл задачи от владельца следующего действия.

Два измерения вместо одного

Я разделил задачу на два независимых измерения:

  • статус;

  • владелец следующего действия.

Статус отвечает на вопрос: где задача находится в жизненном цикле. В моей модели достаточно таких состояний:

backlog
in_progress
waiting_review
blocked
done
cancelled

Владелец следующего действия отвечает на другой вопрос: кто должен двигать задачу дальше.

me
codex
unassigned

Смысл не в конкретном имени codex. В реальной системе это может быть любой AI-агент или несколько разных агентов. Важно другое: задача может быть в backlog, но уже иметь владельца codex, если для нее достаточно контекста. Точно так же задача может быть blocked, но владельцем следующего действия будет человек, потому что нужно принять решение или дать доступ.

Самое важное состояние для agent workflow — waiting_review. Агент не должен переводить свою работу сразу в done, если результат еще не принят человеком. Например, он мог открыть pull request, подготовить черновик письма, изменить конфигурацию или собрать отчет. Во всех этих случаях работа технически выполнена, но финальная ответственность остается у человека. Поэтому результат попадает в очередь проверки.

Как выглядит минимальная модель задачи

Я намеренно оставил модель небольшой. В MVP мне хватило таких полей:

title
description
status
assignee
origin
priority
due_at
reminder_at
source_name
source_url
source_context

origin нужен, чтобы понимать источник: ручной ввод, почта, мессенджер, задача из внешнего трекера или действие агента. source_context хранит краткий контекст, из которого была извлечена задача. Это позволяет не открывать заново письмо или тред в Slack только для того, чтобы понять, почему задача появилась.

При этом я специально не стал тащить в модель десятки полей из Jira, Linear или Asana. Если пытаться совместить все возможные трекеры в одной схеме, получается тяжелая универсальная сущность, которую неудобно использовать локально. Для очереди делегирования важнее компактность и понятный следующий шаг.

Очередь для агента

Отдельный UI для человека полезен, но агенту он не нужен. Агенту нужен машиночитаемый список задач, которые можно выполнять.

Поэтому отдельный endpoint возвращает очередь:

GET /api/agent/queue

Пример запроса:

curl "$TASK_TRACKER_URL/api/agent/queue?assignee=codex&sort=smart&limit=25" \
  -H "Authorization: Bearer $TASK_TRACKER_API_KEY"

В ответе есть summary, чтобы вызывающая сторона понимала общее состояние доски:

{
  "summary": {
    "active": 42,
    "overdue": 3,
    "due_soon": 4,
    "codex_ready": 12,
    "human_input": 18,
    "review": 5,
    "blocked": 2,
    "unassigned": 1
  },
  "tasks": []
}

Для агента это удобнее, чем читать всю доску. Он может запросить только задачи с владельцем codex, отсортировать их по приоритету и дедлайну, взять верхнюю задачу, перевести ее в in_progress, а после выполнения вернуть в waiting_review.

Захват задач из контекста

Следующая часть системы — нормализация задач из внешнего контекста. В моем случае источниками могут быть письма, сообщения, заметки встреч или другие трекеры. Но ядро системы не должно знать детали каждого источника. Иначе оно очень быстро превращается в комбайн со множеством OAuth-flow, токенов и исключений.

Я остановился на модели маленьких адаптеров:

  • webhook-адаптер получает событие из внешней системы и отправляет нормализованную задачу;

  • polling-адаптер периодически читает источник и создает задачи;

  • sync-адаптер читает очередь агента и при необходимости обновляет внешний трекер.

Контракт для загрузки задач из контекста выглядит так:

POST /api/agent/ingest/context

Пример payload:

{
  "origin": "email",
  "source_name": "Gmail thread from Alice",
  "source_url": "https://mail.google.com/...",
  "source_context": "Alice asked for revised numbers by Friday.",
  "tasks": [
    {
      "title": "Send Alice revised numbers",
      "assignee": "me",
      "priority": 2,
      "reminder_at": "2026-05-07T09:00:00Z"
    }
  ]
}

В такой схеме ядро отвечает только за очередь, статусы, дедлайны и API. Адаптеры отвечают за конкретные источники и хранят свои секреты отдельно. Это оказалось проще и безопаснее, чем пытаться встроить все интеграции в основное приложение.

Дедлайны по умолчанию

Еще одна практическая проблема: многие задачи приходят без явного срока. Если оставить их без даты, они быстро перестают всплывать в нужный момент.

Я добавил простое правило: если due_at не передан, сервер оценивает дедлайн по приоритету.

P1 -> около 1 дня
P2 -> около 3 дней
P3 -> около 7 дней
P4 -> около 14 дней
P5 -> около 30 дней

Это не попытка угадать настоящий дедлайн. Это защита от задач, которые бесконечно лежат без даты. Реальный срок, если он есть в исходном письме или трекере, всегда должен иметь приоритет над такой оценкой.

Архитектура MVP

Технически MVP получился довольно прямолинейным:

  • FastAPI отдает web UI и JSON API;

  • SQLite используется для локальной разработки;

  • Firestore можно использовать как hosted-хранилище;

  • Google OAuth защищает браузерный UI;

  • Bearer token защищает API для агентов и адаптеров;

  • отдельный reminder job может периодически читать /api/reminders/due.

Эта архитектура не самая модная, но у нее есть важное преимущество: она понятная. Локально можно запустить SQLite-версию, а production-вариант можно развернуть как Cloud Run + Firestore + Secret Manager.

Локальный запуск выглядит так:

python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
uvicorn app.main:app --reload

После этого UI доступен на http://127.0.0.1:8000.

Что я бы сделал иначе

Первое, что стало понятно после использования: определение “AI-ready” задачи лучше не зашивать только в один признак assignee=codex. В будущем полезно хранить объяснение, почему задача считается готовой для агента. Например: “есть ссылка на репозиторий”, “есть критерий готовности”, “не требуется внешний логин”, “не требуется отправка сообщения без подтверждения”.

Второй момент — ревью должно быть более структурированным. Сейчас waiting_review просто показывает, что человек должен проверить результат. Но для agent workflow полезно хранить артефакты: ссылку на PR, список измененных файлов, тесты, summary, риски и следующий шаг.

Третий момент — адаптеры лучше держать отдельно от ядра. Сначала хочется положить в основной репозиторий все интеграции сразу, но это быстро усложняет безопасность и поддержку. Гораздо чище иметь маленькое ядро и набор примеров адаптеров.

Вывод

Чем лучше AI-агенты выполняют задачи, тем заметнее становится проблема маршрутизации. Человек не должен каждый раз вручную разбирать список дел и решать, что можно поручить агенту.

Для меня полезной оказалась модель, где задача описывает не только состояние, но и владельца следующего действия. Тогда доска превращается не просто в список, а в очередь делегирования:

  • что делает человек;

  • что может взять агент;

  • что ждет проверки;

  • что заблокировано;

  • что еще не разобрано.

Исходники прототипа лежат на GitHub