Skip to content

Минимальный harness

С чего начинается runner

Один agent run не является процессом. Это скорее разговор, после которого появился diff. Чтобы команда могла повторять, ревьюить и улучшать работу агентов, нужен маленький runner: он берёт задачу, собирает контекст, применяет output backend, запускает checks и честно говорит, что получилось.

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

Первый рабочий цикл

text
task -> prompt -> agent -> diff -> checks -> result

На первом шаге harness должен:

  • принимать task contract как input;
  • строить prompt из task + context pack;
  • запускать agent backend;
  • сохранять stdout/stderr, tool events и итоговый diff;
  • запускать testing plan;
  • возвращать result classification.

Дальше появляются ветки: задача может пройти, упасть, потребовать review или остановиться из-за policy. Это лучше зафиксировать в самом runner, а не обсуждать после каждого diff.

task contractcontext packagent backenddiffpolicy +checksdoneк review / mergeneeds_reviewрешение человекаblockedнужен доступ/решениеfailedchecks упалиretry с machine-readable feedback, пока есть retry budgetКаждый переход пишется как event в JSONL run log — см. главу Observability.

Как называть результат

ResultКогда ставить
doneChecks прошли, acceptance criteria закрыты, результат можно отдавать в review или merge flow.
needs_reviewChecks не отвечают на весь риск: нужен человек.
blockedНе хватает доступа, решения, context или policy запрещает действие.
failedRun завершился ошибкой, нарушил constraints или не прошёл checks.

Runner и backend — разные вещи

Runner не должен намертво срастаться с одной моделью или CLI. Сегодня backend может быть fixture, завтра Codex, OpenCode, Claude Code, Gemini CLI или внутренний agent. Логика процесса должна пережить замену backend.

Поэтому отделяйте:

  • orchestration logic;
  • prompt construction;
  • sandbox rules;
  • backend adapter;
  • verification commands;
  • логирование и summaries.

Тогда вы меняете adapter, а не весь workflow.

Где это увидеть в repo

В репозитории есть два уровня примеров:

text
examples/harness-labs/01-manual-runner/runner.py   # v01, написан руками
examples/harness-labs/fixtures/harness-v02/runner.py # v02, строится через v01
examples/harness-labs/fixtures/harness-v03/runner.py # v03, строится через v02

Пошаговая цепочка начинается так:

bash
rm -rf /tmp/harness-v02
cp -a examples/harness-labs/harness-seed /tmp/harness-v02

python3 examples/harness-labs/01-manual-runner/runner.py \
  --task examples/harness-labs/tasks/02-build-observable-runner.json \
  --workspace /tmp/harness-v02

После этого /tmp/harness-v02/runner.py уже строит первый ALGI slice. Важно: examples/algi-lite/ не содержит готовую реализацию заранее. Product files появляются только после harness execution.

Показательно, насколько маленькими остаются версии — каждая добавляет ровно один слой:

ВерсияРазмерЧто добавляет
v01~90 строкЦикл task → fixture → checks → exit code.
v02~140 строкJSONL events и result classification (done / blocked / failed).
v03~220 строкPolicy gate: allowed prefixes, blocked fragments, path allowlist.

Минимальный harness — это дисциплина в двухстах строках. Потом на неё можно добавлять policy, logs, evals и orchestration.

На что не соглашаться

  • Верить финальному сообщению агента вместо checks.
  • Не сохранять prompt и context, с которыми был run.
  • Считать partial diff успешным результатом.
  • Смешивать task selection, prompt building и backend-specific code в одном месте.
  • Не различать failed и blocked.

Что сделать руками

Соберите runner для одной bounded coding задачи. Успех выглядит так: запуск воспроизводим, checks запускаются автоматически, failed не маскируется под done, а blocked не превращается в загадочный crash.

Agentic Engineering: Context Engineering + Harness Engineering