AI-агенты
tapstep отдаёт весь свой инструментарий — увидеть экран, тапнуть, запустить тест, починить селектор — AI-агентам. Есть три пути: от нулевой настройки до своего агента.
Встроенный AI-чат (desktop)
Заголовок раздела «Встроенный AI-чат (desktop)»Иконка ✨ в десктоп-приложении открывает панель чата рядом с тестами. Агент
видит рабочую область и устройство: он записывает шаги через snapshot/act,
пишет файлы .flow.yaml, запускает их и чинит падающие селекторы. Каждая
правка файла показывается как diff в переписке, а перед первым изменением
сохраняется контрольная точка версии.
В чате нет выбора устройства: агент стартует на устройстве последнего прогона и
переключается своим инструментом select_device, когда вы попросите (или когда
флоу нужна другая платформа).
Чат — одна лента: шаги агента стоят прямо в переписке, там, где случились, а один переключатель Details открывает или закрывает вход и результат всех шагов сразу. Строка под перепиской называет фазу, в которой идёт терн, — Thinking, Working (и над чем именно) или Verifying, — а любой терн заканчивается done, чем бы он ни кончился.
Что даёт панель, коротко:
- Fast / Thorough (⚡) — урезанное размышление ради быстрых шагов или полное размышление между шагами (Anthropic API и Claude Code; остальные провайдеры его игнорируют). На уровне машины.
- Draft / Verified (✓) — в Verified терн обязан прогнать тест и чинить его до зелёного, прежде чем завершиться (стоит прогонов); Draft оставляет это на усмотрение модели.
- Дозаправка — пишите, пока терн идёт: сообщение попадает в летящий терн; если провайдер не может принять его посреди терна, оно встаёт в очередь на следующий.
- Вложения — картинки и текстовые файлы, кнопкой или drag-and-drop (до 4 картинок и 8 файлов на сообщение).
- History / New chat — переписки сохраняются по проектам; New chat архивирует текущую, History возвращает любую.
- Быстрые чипы под полем ввода — директивы в один тап: Re-runnable, Parameterize, Adapt to state, Run to green.
- Счётчик расхода — входные / кэшированные / выходные токены за сессию. Только токены, без денег.
Шесть провайдеров, в меню чата ⋯ → AI settings:
-
Anthropic API key — хранится в связке ключей ОС. Endpoint и модель настраиваются (
ai.endpoint,ai.modelвconfig.yaml). -
OpenAI-совместимый — любой endpoint
chat/completions: локальный Ollama или LM Studio, свой vLLM или облачный API. Укажите, например,http://localhost:11434/v1и модель с поддержкой инструментов — и ничего не покидает вашу машину. API-ключ опционален — локальным серверам он не нужен. -
Claude Code — без API-ключа: чат управляет локально установленным Claude Code, залогиненным в вашу подписку Claude. Установите один раз — и готово:
Terminal window npm install -g @anthropic-ai/claude-codeclaude # вход один раз -
Codex — то же самое для планов ChatGPT:
npm install -g @openai/codex, затемcodex login. -
Gemini CLI —
npm install -g @google/gemini-cli. Google закрыл бесплатный персональный вход, поэтому создайте API-ключ на aistudio.google.com/apikey (у него свой бесплатный лимит) и вставьте его в приложение — ключ хранится в связке ключей ОС и передаётся CLI при каждом запуске. -
OpenCode — открытый терминальный агент, который приносит своего провайдера модели, так что чат стоит ровно столько, сколько стоит этот провайдер:
npm install -g opencode-ai, затемopencode auth login. Приложение прописывает мост tapstep вopencode.jsonпроекта.
Выбранный provider десктоп держит в том же блоке ai: файла config.yaml
(для Anthropic API по умолчанию не пишется), рядом с endpoint, model и
флагом privacy ниже. Ключи в файл не попадают.
Маскирование персональных данных
Заголовок раздела «Маскирование персональных данных»Settings → AI → Privacy masking запускает on-device модель, которая
заменяет имена, e-mail, телефоны и секреты стабильными псевдонимами до того,
как запрос чата покинет машину; в переписке локально снова видны настоящие
значения. Это значение по умолчанию для машины; проект переопределяет его через
ai.privacy: true|false в config.yaml. С провайдерами-CLI-агентами
маскируются только ваши реплики — их трафик инструментов идёт во внешнем CLI,
куда маскирование не дотягивается.
В CLI то же маскирование для AI-шагов: tapstep privacy install один раз
скачивает модель (~945 МБ), tapstep privacy status показывает, что включено,
а TAPSTEP_PRIVACY=1 включает его на прогон.
Подключить внешнего агента (MCP)
Заголовок раздела «Подключить внешнего агента (MCP)»Settings → AI → MCP server запускает локальный MCP-сервер, привязанный к устройству, — только localhost, защищён токеном. Та же строка копирует готовую команду:
claude mcp add --transport http tapstep http://127.0.0.1:PORT/mcp \ --header "Authorization: Bearer TOKEN"Любой MCP-клиент работает так же (Cursor, Windsurf, …): наведите его на URL с
этим заголовком. Агент получает snapshot, try, act, resolve, diff,
run_flow, validate_flow, suggest, patch_flow и heal на выбранном
устройстве, плюс собственные инструменты десктопа list_devices,
select_device, list_runs, run_details и request_secret (спрашивает у
вас креденшел в диалоге и пишет его в .env, так что значение не попадает в
переписку).
CLI — тоже MCP-сервер:
tapstep mcp [--driver web|android|ios|app[:port]] [--browser …]Он говорит по MCP через stdio — на него и указывает .mcp.json ниже — и, как
любая другая команда, требует машину со входом. Без --driver берёт
подключённое устройство, иначе браузер. Инструменты: snapshot, try,
act, resolve, diff, run_flow, validate_flow, take_screenshot,
cheat_sheet, list_devices, suggest, patch_flow, heal,
convert_curl, request_to_curl, import_playwright, export_playwright и
export_extester. run_flow разрешает defaultEnvironment проекта, а оба
инструмента экспорта берут папку из настройки exports: проекта, когда вызов
её не назвал.
snapshot отвечает в компактной нотации — по строке на элемент, с тем, что
стабильно ($testId / #id), сколько на странице дубликатов (x6), значением
и состоянием поля и тем, в какой строке или диалоге он стоит, — под шапкой
страницы, которая говорит, устоялся ли экран. Полностью описана на странице
Нотация снапшота, и та же легенда едет в описании
самого инструмента и в cheat_sheet, так что агенту не нужно объяснять.
snapshot { detail: "regions" } — дешёвый обзор того же экрана: по строке на
контейнер, а не на элемент.
Как агент ведёт экран теперь
Заголовок раздела «Как агент ведёт экран теперь»Читать весь экран перед каждым шагом — дорогой способ его вести. Дешёвый цикл — два вызова:
snapshot { detail: "regions" }по прибытии — обзор. По строке на контейнер с тем, что в нём лежит (header: 2 buttons, 1 link "Log in",table "Orders": 20 rows,nav: 4 links), затем управляющие элементы, которые не держит ни один контейнер. Около 25 строк, каким бы ни был экран; перечитывать после смены страницы, а не перед каждым шагом.try { step: … }— сам шаг.step— одна команда в YAML флоу, ровно та, что лежит в.flow.yaml:tapOn,inputText,scroll— так что шаг, который сработал здесь, и есть строка для вставки во флоу.
try разрешает селектор шага так же, как его разрешает прогон, и действует
только когда тот называет ровно один элемент. Тогда в ответе идут квитанция
(done tapOn e41 button "Create order" in:header), события, которые доказали
два экрана (went, dialog opened, toast, focus, value, error), и
строка net: с запросами, которые вызвало действие.
Не совпало ничего — none "Create Order!" — или совпало несколько —
ambiguous "Save": 3 — и экран не тронут: в ответе до пяти кандидатов с
якорями, которые их различают, а via:exact|norm|sub|score у каждого говорит,
насколько пришлось растянуть имя, чтобы до него дотянуться. Сузьте шаг
(index:/of:, rightOf:, childOf:) и попробуйте снова; полный snapshot
читайте только после того, как try дважды ответил none или ambiguous про
один и тот же экран.
expect — необязательная команда assert*, которая выполняется сразу после
шага, когда важен исход; она возвращается в том же ответе как expect: ok или
expect: failed — …, и провалившаяся проверка — не провалившийся вызов:
действие произошло. ref называет элемент из прошлого шага вместо того, чтобы
описывать его заново: try { ref: "e7", step: "tapOn: '-'" } действует на e7,
что бы ни говорил собственный селектор шага. Шаги
request,
sql и
assertTrue тоже идут через try —
им экран не нужен, поэтому он и не читается.
Рабочие области CLI
Заголовок раздела «Рабочие области CLI»В репозитории один раз разложите конфиг агента:
tapstep init --agentsЭто создаёт .mcp.json (чтобы Claude Code в этой папке сам подхватывал
инструменты tapstep — он запускает tapstep mcp) и шпаргалку AGENTS.md с
конвенциями flow-файла.
Есть и скилл агента — подробный плейбук (справочник CLI и flow-файла, рабочие конвенции), который агент подгружает по необходимости:
tapstep skill installСтавится для каждого найденного агента — Claude Code (~/.claude/skills),
Codex (~/.codex/skills), Gemini CLI (~/.gemini/skills), Cursor
(~/.cursor/skills), OpenCode (~/.config/opencode/skills) — плюс общая копия
~/.agents/skills, которую читают и Codex, и Gemini CLI, и Cursor, и OpenCode.
Хотя бы одна из этих домашних папок должна существовать, и нужен вход.
Идемпотентно. tapstep skill status говорит по каждому агенту, установлена ли
копия и совпадает ли она с этим бинарём; tapstep skill refresh
пересинхронизирует установленные копии и сам запускается после tapstep update. В десктопе та же установка — в Settings → AI → Agent skill.
Десктоп-приложение также поставляется со встроенным терминалом (кнопка Terminal
в статус-баре или Ctrl+</kbd>) — удобно запускать claudeилиtapstep` прямо в рабочей области.
AI-шаги во флоу
Заголовок раздела «AI-шаги во флоу»Три команды спрашивают модель о текущем экране — текст снимка плюс скриншот, когда он есть у драйвера:
- assertWithAI: "the cart shows exactly one item" # голая форма: optional- assertWithAI: { assertion: "no error banner", optional: false }- assertNoDefectsWithAI # дефекты вёрстки/визуала- extractTextWithAI: "the order number" # → ${aiText}- extractTextWithAI: { query: "the total", into: total, pattern: "\\d+\\.\\d{2}" }Голые формы — это optional: true: упавшая проверка (или ошибка AI) — это
предупреждение в отчёте, а не упавший шаг; optional: false роняет флоу.
extractTextWithAI пишет в into (по умолчанию aiText); с pattern
значение обязано совпасть с этим регэкспом (одна повторная попытка, затем шаг
падает). Подробности: assertWithAI
и соседи в справочнике команд.
Подключение берётся из config.yaml (через --config; блок с обоими
endpoint и model побеждает окружение) или из окружения:
ai: endpoint: https://api.anthropic.com # или любой OpenAI-совместимый базовый URL model: claude-opus-4-8 key: sk-ant-… # опционально; ключ sk-ant-… означает AnthropicTAPSTEP_AI_ENDPOINT=http://localhost:11434/v1 TAPSTEP_AI_MODEL=qwen2.5 tapstep test flows/Ключ sk-ant-… выбирает Anthropic Messages API (с переменными окружения
TAPSTEP_AI_ENDPOINT тогда можно опустить); всё остальное считается
OpenAI-совместимым chat/completions. tapstep test --analyze тем же
подключением разбирает упавшие флоу после прогона.
В десктопе AI-шаги используют подключение чата — Anthropic API-ключ или
OpenAI-совместимый endpoint проекта. У провайдеров-CLI-агентов (Claude Code,
Codex, Gemini CLI) нет HTTP-endpoint’а, который можно вызвать, поэтому с ними
assertWithAI и компания падают как ненастроенные (AI commands need a model endpoint).