Собрали агента с руками: как мы добавили управление рабочим столом

Проект voice-agent развивается, и пришла пора дать ему не только уши и язык, но и руки. Три недели назад начал работать над тем, чтобы AI мог управлять графическим интерфейсом: кликать по окнам, вводить текст, перемещать мышь. Как оказалось, это совсем не простая задача.
Начинал я с классического подхода — добавить инструменты через BaseTool и ToolRegistry. Для GUI-автоматизации выбрал pyautogui (простой, кроссплатформенный), для скриншотов — PIL. Создал восемь инструментов: клик, печать текста, горячие клавиши, перемещение мыши, управление окнами. Казалось, готово. На самом деле это была половина работы.
Настоящая сложность началась с OCR — распознавания текста на экране. Инструмент screenshot возвращал картинку, но агенту нужно было понимать, что там написано. Первая попытка с pytesseract провалилась на текстах с кириллицей и сложной разметкой. Переписал логику: теперь скриншот обрабатывается асинхронно, результаты кэшируются, и язык можно переключать через конфиг. CUASettings в config/settings.py теперь управляет всеми параметрами компьютерного зрения.
Но вот парадокс: даже с OCR агент не мог самостоятельно планировать действия. Просто список инструментов — это не достаточно. Нужна была архитектура агента-помощника, который видит скриншот, понимает, где он находится, и решает, что делать дальше. Назвал её CUA (Computer Use Agent). Ядро — это цикл: сделай скриншот → отправь в Vision LLM → получи план действий → выполни → повтори.
Здесь выскочила проблема синхронизации: пока один агент кликает мышью, второй не должен пытаться печатать текст. Добавил asyncio.Lock() в исполнитель (CUAExecutor). И ещё одна дыра в безопасности: агент может зависнуть в бесконечном цикле. Решение простое — asyncio.Event для экстренной остановки плюс кнопка в system tray.
Все модули написал в пять этапов, создав 17 новых инструментов и 140+ тестов. Phase 0 — фундамент (DesktopDragTool, DesktopScrollTool, новые параметры конфига). Phase 1 — логика действий (парсер команд, валидация координат). Phase 2 — тесты (моки для Playwright, проверка расписаний). Phase 3 — интеграция в desktop_main.py. Phase 4 — финальная полировка.
Самый красивый момент — когда первый раз запустил агента, и он сам нашёл окно браузера, прочитал текст на экране и кликнул ровно туда, куда нужно было. Наконец-то не только слышит и говорит, но и видит.
Забавный факт: знакомство с Cassandra для хранения логов автоматизации — день первый восторг, день тридцатый «зачем я это вообще начал?» 😄
Метаданные
- Session ID:
- grouped_C--projects-ai-agents-voice-agent_20260216_2152
- Branch:
- main
- Dev Joke
- Знакомство с Cassandra: день 1 — восторг, день 30 — «зачем я это начал?»