Skip to content

Неделя 5. Runtime и оркестрация workflow

Что уже умеем
Вызывать модель через `ModelClient`, проверять структурированный ответ и tool proposal.
Какую проблему решаем
Между вызовами теряется состояние, провайдер протекает в логику.
Что нового появится
Runtime вокруг известного model call: State, Workflow, RunPolicy и HumanGate.
Что получится в конце
Workflow с конечным бюджетом и тестами на mock.

🧭 Где мы: LLM → Context / State → Tools → [Runtime / Orchestration] → Policy / Permissions → Evaluation / Observability.


Что меняем в Capstone

Week 5. Формализуем runtime: выносим State → Role → Transition → RunPolicy → HumanGate в отдельные компоненты. RunPolicy задаёт конечный budget, HumanGate останавливает side effects.

Вспомни прошлую неделю

  1. Что делает ModelClient между workflow и provider SDK?
  2. Где в Capstone tool proposal проходит validation до исполнения?

Материал

🤔 Predict

Вызов модели трижды завершился timeout, а лимит попыток исчерпан. Должен ли runtime продолжать вызывать модель, пометить запуск blocked или завершить его как ошибку выполнения?

В Week 4 мы научились вызывать модель через ModelClient. Теперь строим runtime вокруг этой capability: сохраняем состояние между ролями, задаём переходы кодом, ограничиваем бюджет и останавливаем опасные side effects до исполнения. Реализуем это на обычном Python; новый framework не нужен.

Основной проход недели: State → Workflow → RunPolicy → HumanGate. ModelClient остаётся известной зависимостью, которую runtime вызывает внутри шага.

Обязательное ядро: State, Workflow, RunPolicy, HumanGate и runtime, который связывает их. Поля State, условия переходов и лимиты должны быть проверяемы тестами; модель остаётся за интерфейсом из Week 4.


Компоненты

Не обязательно строить инфраструктуру целиком. Каждый компонент вводится только против конкретной проблемы:

Компонент Какую проблему решает Объём
State факты о прогрессе теряются между ролями обязательное ядро
ModelClient provider differences не должны попадать в логику workflow изучен в Week 4; используется runtime
Workflow переходы между ролями зависят от того, как модель сформулировала текст обязательное ядро
HumanGate опасное действие должно ждать подтверждения, а не выполняться сразу обязательное ядро
RunPolicy лимиты вызовов и повторов иначе не соблюдаются обязательное ядро
RoleRunner сборка сообщений для роли упрощённая реализация, артефакты в памяти или файлах
ArtifactStore prompts, outputs, diff и test results нужно хранить долго и с redaction расширение

Один проход через эти компоненты

Теперь те же пять абстракций на одном реальном шаге — узле planner:

Workflow: решить, что делать дальше; условие перехода — заполнены acceptance_criteria
  ↓ передаёт не текст, а поле state
State: {issue, acceptance_criteria[2], allowed_paths[], status: planning}
  ↓ собирает сообщение из state, инструкции роли и правил формата
RoleRunner → ModelClient: один вызов; на выходе — JSON по схеме или явная ошибка
  ↓ схема невалидна / пустой ответ / timeout во время вызова
RunPolicy: один ограниченный повтор; после исчерпания — failed, дальше не идём
  ↓ scope не подтверждён человеком
HumanGate: needs_approval, запись не выполняется

Один вызов — одно решение: где хранится факт, кто зовёт модель, что проверяется до вызова и что происходит после. Когда все пять компонентов на месте, этот проход одинаков для любой роли: planner, analyst, reviewer отличаются только содержимым state и инструкцией.


Бюджет (обязательное ядро) и model routing (расширение)

Лимит вызовов — не оптимизация, а граница отказа: без конечного числа повторов цикл «попробовать ещё раз» превращается в зависший процесс, который выглядит как работа.

Зафиксируйте один провайдер и модель, установите конечные лимиты вызовов, времени и повторов. Не допускайте тихого переключения на другой или платный endpoint.

Расширение: добавьте routing — детерминированное правило, какая модель или обычный код обрабатывает какой тип шага:

Тип шага Начальный выбор Условие эскалации
Извлечение полей, нормализация, классификация Маленькая локальная модель или обычный Python-код Формат не прошёл schema validation или низкая уверенность
Анализ кода, планирование, сложный review Привычная более сильная coding-модель; локальная — только после собственного eval Не хватает доказательств, повторяется ошибка, высокий риск
Высокорисковое изменение / неоднозначные требования Human gate до вызова implementer Не эскалировать автоматически без лимита/разрешения
Простые проверки и маршрутизация Python-правила, тесты и allowlist Не вызывать LLM там, где достаточно детерминированной проверки

Платный API для local-first пути не требуется. Облачный fallback необязателен и потенциально платен: он должен быть явно включён, иметь лимит и не получать приватный контекст без отдельного разрешения. Условия локального прогона — модель и тег, квантование, num_ctx, wall-clock, число вызовов, память — фиксируются по странице о выборе модели.

Расширение: сравните две модели или провайдера на одном наборе задач; routing должен иметь явные лимиты и завершать execution error как failed, возвращать needs_input для неоднозначности и blocked только при отказе policy до вызова.


Состояние задачи

State из недели 3 теперь становится конкретной структурой. Минимальный набор полей, который реально используется в capstone:

run_id
issue
acceptance_criteria[]
allowed_paths[]
plan
human_plan_approved
repo_evidence[]
test_plan[]
proposed_patch
commands_requested[]
commands_approved[]
test_results[]
review_findings[]
iteration_count
status: planning|needs_approval|implementing|testing|blocked|failed|done

blocked — policy не допустила действие до исполнения; failed — model/tool/runtime execution уже начался, но завершился ошибкой или исчерпал retry budget.

Секреты, .env, токены и содержимое credentials не должны попадать в промпты, артефакты логов или commit. Используйте .gitignore, redaction и отдельный учебный репозиторий.


Практика

Соберите первую цепочку без автоматического shell:

issue → planner → schema validation → человек утверждает план
     → read-only analyst → один отчёт

На выходе программа печатает артефакт и предлагает следующий шаг; она не меняет код. Добавьте тесты на invalid schema, provider timeout и needs_input.

🎉 What you can do now

Вы можете ограничить выполнение конечным бюджетом, сохранить состояние между шагами и остановить запуск на HumanGate до side effect.

Rule

Явные state, адаптер внешнего сервиса и конечные retry-бюджеты полезны в любом интеграционном workflow.

Результат недели: Capstone checkpoint

Week 5. Runtime + policy работают: State → Role → Transition → RunPolicy → HumanGate, конечный budget на mock.

Проверь себя

  1. Какую проблему решает runtime поверх ModelClient?
  2. Чем RunPolicy отличается от HumanGate?
  3. Где в Capstone сохраняется состояние и где останавливается side effect?

✅ Definition of Done

  • Объяснить, зачем runtime нужен поверх ModelClient, и различать обязанности RunPolicy и HumanGate.
  • Реализовать переходы workflow по полям State, а не по свободному тексту модели.
  • Тестом проверить invalid schema, timeout, конечный retry budget и needs_input.
  • Показать, что исчерпание retry завершает выполнение как failed, а policy rejection до tool execution даёт blocked; незакрытый HumanGate не допускает side effect.

→ Дальше: runtime управляет переходами и остановками; в Week 6 сузим, какие инструменты и действия ему вообще разрешено выполнять.


Навигация

← Week 4: Model provider
→ Week 6: Tools / Policy / Security