Headless-режим и автоматизация
waibee run запускает агента без интерфейса: на вход промпт, на выход результат в stdout. Никакого TUI, поэтому агента можно вызывать из Makefile, git-хука, шага CI или другой программы, в том числе из другого агента.
waibee run "объясни, что делает calc.py, одним предложением"Агент работает в реальном проекте: читает файлы, запускает команды, правит код. Отличие от TUI только в способе общения.
Форматы вывода
Заголовок раздела «Форматы вывода»waibee run --format text "..." # обычный текст, по умолчаниюwaibee run --format json "..." # построчный JSONwaibee run --format jsonl "..." # то же самое, второе имя того же форматаjson и jsonl дают одинаковый вывод: поток событий, по одному JSON-объекту в строке.
В JSON-режимах каждая строка это отдельное событие:
{"type":"text","text":"ГОТОВО"}{"type":"goal_evaluated","decision":"met","reason":"В ответе есть слово ГОТОВО"}{"type":"goal_achieved","duration_secs":80}{"type":"usage","models":[{"model":"anthropic/claude-haiku-4.5","input_tokens":812,"output_tokens":96}]}Ответ модели приходит частями в событиях type: "text": собирай их конкатенацией. События goal mode (goal_evaluated, goal_achieved, goal_aborted) появляются, когда цель активна, а завершающая строка usage когда счётчики токенов доступны.
Результат идёт в stdout, логи и предупреждения в stderr. Поэтому $(waibee run ...) подхватывает только ответ, а диагностику можно оставить в логах шага CI.
Коды возврата
Заголовок раздела «Коды возврата»Без цели waibee run завершается нулём, если агент отработал, и ненулём при ошибке. С флагом --goal код отражает результат проверки:
| Код | Значение |
|---|---|
0 |
Цель достигнута |
1 |
Исчерпан лимит ходов, цель не достигнута |
2 |
Ошибка агента или проверяющей модели |
130, 143 |
Прерывание: второй Ctrl+C и SIGTERM. По этим кодам в CI видно, что шаг сняли, а не что задача провалилась |
Отсутствующий или отвергнутый роутером ключ тоже даёт ненулевой код, а причина пишется в stderr.
Это и есть главный способ встроить агента в пайплайн: --goal описывает, что считается успехом, а код возврата решает, падает шаг или нет. Подробнее в Режиме цели.
Один проход или проверка результата
Заголовок раздела «Один проход или проверка результата»По умолчанию агент старается не останавливаться на первом ответе: он формулирует условие завершения по задаче и проверяет, выполнено ли оно. Это дороже и дольше, зато результат не «почти готов». Для вопросов, объяснений и мелких правок условие не формулируется, и запуск сам сводится к одному проходу.
waibee run "перенеси модуль auth на новый клиент" # работает до проверяемого результатаwaibee run --once "объясни, что делает этот файл" # один проход, без проверкиДля вопросов и разовых справок бери --once: там проверять нечего.
Флаги и порядок аргументов
Заголовок раздела «Флаги и порядок аргументов»Общие флаги (модель, рабочая папка) относятся ко всей команде и ставятся перед run, свои флаги run после него:
waibee -m haiku run --once "перескажи README в трёх пунктах"waibee -c ~/projects/api run --format json "какие эндпоинты объявлены?"waibee run -m haiku не сработает: -m это флаг верхнего уровня.
| Флаг | Где | Назначение |
|---|---|---|
-m, --model |
до run |
Модель: псевдоним (haiku) или полный идентификатор |
-c, --cwd |
до run |
Рабочая папка проекта |
--format |
после run |
text, json, jsonl |
--once |
после run |
Один проход без проверки результата |
--goal |
после run |
Условие завершения, см. Goal mode |
--goal-max-iterations |
после run |
Предел автопродолжений |
--goal-model |
после run |
Модель-проверяющий |
Права в headless-режиме
Заголовок раздела «Права в headless-режиме»waibee run работает в режиме доверия, если в settings.json не задан другой: правки файлов и обычные команды выполняются сразу. Значение permissions.mode действует и здесь.
Важное исключение: команда с высоким риском (sudo, curl, удаление по шаблону) всё равно требует подтверждения, а отвечать в headless некому, поэтому запуск встанет и будет ждать. Разрушительные команды отклоняются сразу, в любом режиме. Подробнее: Права доступа.
Что из этого следует для автоматизации:
- Разреши заранее то, что задаче нужно. Правила
allowвsettings.jsonснимают вопрос по конкретным командам, не открывая всё подряд. - Ставь таймаут шага. Он же страховка от зависшего запроса на подтверждение.
- Читающим задачам не нужен доступ на запись. Сформулируй промпт как «проанализируй и опиши», а результат забирай из stdout, не из изменённых файлов.
- Правки запускай в одноразовой копии. Отдельный клон, worktree или контейнер CI: там нечего терять, если агент сделает не то. Там же уместен режим
bypassPermissions. - Запрещай опасное явно. Правила
deny(напримерgit push, доступ к секретам) действуют в любом режиме. - Ограничивай ходы.
--goal-max-iterationsне даст циклу тянуться до таймаута раннера.
Сценарии
Заголовок раздела «Сценарии»| Задача | Как ставить |
|---|---|
| Ревью диффа в PR | git diff origin/main > /tmp/d.patch, затем промпт «проверь риски в этом диффе», результат в файл или комментарий |
| Разбор упавшего теста | Промпт с командой запуска: агент сам воспроизведёт и объяснит причину |
| Черновик CHANGELOG | Промпт по git log между тегами, вывод в файл релиза |
| Массовая правка по списку файлов | Цикл в bash: по одному вызову на файл, сначала проверь на двух-трёх |
| Ночная задача с проверкой | --goal "make lint и make test проходят", код возврата решает, чинить ли дальше |
| Разбор алерта или лога | Текст лога в промпт, на выходе гипотеза и место в коде |
| Инструмент внутри другого агента | --once --format json, разбор событий text (пример ниже) |
| Проверка перед коммитом | Git-хук с читающим промптом, при непустых замечаниях вернуть ненулевой код |
Промпты для этих сценариев удобно держать не в шелле, а в своих командах .waibee/commands/: тогда они версионируются вместе с проектом.
Вызов из другой программы
Заголовок раздела «Вызов из другой программы»Агент это обычный процесс: запусти его, прочитай stdout, разбери JSON.
import jsonimport subprocess
TIMEOUT_SECONDS = 600
def ask(prompt: str, cwd: str = ".") -> str: process = subprocess.run( ["waibee", "run", "--once", "--format", "json", prompt], cwd=cwd, capture_output=True, text=True, timeout=TIMEOUT_SECONDS, ) if process.returncode != 0: # Диагностика агента идёт в stderr, поэтому её и показываем. raise RuntimeError(f"waibee run завершился с кодом {process.returncode}: " f"{process.stderr.strip()[-500:]}") events = (json.loads(line) for line in process.stdout.splitlines()) return "".join(event["text"] for event in events if event["type"] == "text")
print(ask("Одним предложением: что делает calc.py?"))Так агента подключают как инструмент к другому агенту или к сервису. Он умеет то, чего у вызывающей стороны нет: работать в чужом репозитории с файлами, командами и тестами.
Если нужны не разовые вызовы, а разговор с сохранением контекста между запусками, смотри ACP в терминале.
- name: Установить агента run: curl -fsSL https://raw.githubusercontent.com/waibee-main/waibee-code/main/install.sh | bash
- name: Ревью диффа env: WAIBEE_API_KEY: ${{ secrets.WAIBEE_API_KEY }} run: | git diff origin/${{ github.base_ref }}...HEAD > /tmp/diff.patch waibee run --once --format text \ "Прочитай /tmp/diff.patch и перечисли риски: логические ошибки, потеря данных, ломающиеся контракты. Только замечания по делу, без пересказа диффа." \ > review.md cat review.md >> $GITHUB_STEP_SUMMARYЧто учесть в CI:
- Ключ только через секреты.
WAIBEE_API_KEYв окружении шага, никогда в коде. - Задавай таймаут шага. Агент с проверкой результата может работать долго; ограничение времени в CI обязательно.
- MCP-серверы проекта поднимаются и в headless. Те, что требуют интерактивной авторизации, в CI не запустятся и будут писать ошибки в stderr. Держи для CI отдельный конфиг без них, см. MCP.
- Не смешивай чтение и запись в одном шаге. Ревью пусть только читает; правки отдельным шагом, который явно коммитит результат.
- Goal mode: условие завершения и коды возврата.
- Права доступа: правила
allowиdeny. - Лучшие практики: формулировки, на которых агент не гадает.