🖱️

Claude Computer Use: агент управляет компьютером

Настройка Claude Computer Use для автоматизации десктопа: скриншоты, клики, набор текста. Docker-контейнер + Python SDK для полного управления GUI.

advanced ⏱ 22 мин
Архитектура Claude Computer Use Python SDK (anthropic) Claude API /v1/messages Docker Container claude-computer-use xvfb + xdotool Virtual Desktop Xvfb :99 loop: screenshot → action Скриншот → Claude анализирует → действие (click/type/scroll) → снова скриншот

# 1. Запуск Docker-контейнера с виртуальным десктопом

Claude Computer Use работает внутри Docker-контейнера с виртуальным дисплеем Xvfb. Сначала клонируем репозиторий и запускаем образ. Контейнер включает xdotool для эмуляции действий мыши и клавиатуры, а также VNC-сервер для наблюдения за действиями агента в реальном времени.

# Клонируем репозиторий с эталонной реализацией
git clone https://github.com/anthropics/anthropic-quickstarts.git
cd anthropic-quickstarts/computer-use-demo

# Билдим и запускаем Docker-образ
export ANTHROPIC_API_KEY="sk-ant-..."
docker build -t computer-use-demo .
docker run -d \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
  -p 5900:5900 -p 8501:8501 -p 8888:8888 \
  --name computer-use computer-use-demo

# VNC доступен на порту 5900, Streamlit UI на 8501, noVNC на 8888
    

# 2. Python SDK: отправка скриншота и получение действия

Устанавливаем Anthropic SDK и отправляем Claude скриншот виртуального десктопа. Модель анализирует изображение и возвращает конкретное действие: координаты клика, текст для ввода или комбинацию клавиш. Используем бета-заголовок computer-use-2024-10-22.

import base64
import os
from anthropic import Anthropic

client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def get_computer_action(screenshot_path: str, task: str) -> dict:
    """Отправляет скриншот Claude и получает следующее действие."""
    with open(screenshot_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode()

    response = client.beta.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        betas=["computer-use-2024-10-22"],
        tools=[{
            "type": "computer_20241022",
            "name": "computer",
            "display_width_px": 1024,
            "display_height_px": 768,
            "display_number": 1
        }],
        messages=[{
            "role": "user",
            "content": [
                {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": image_data}},
                {"type": "text", "text": task}
            ]
        }]
    )

    return response.content
    

# 3. Исполнение действий на виртуальном десктопе

Claude возвращает действия в формате tool_use блока. Парсим ответ и исполняем: клики мышью через xdotool, ввод текста, скролл, горячие клавиши. Каждое действие логируется в консоль для отладки.

import subprocess
import time

# DISPLAY должен указывать на Xvfb
DISPLAY = ":99"

def execute_action(action_block: dict):
    """Исполняет действие, полученное от Claude."""
    name = action_block["name"]
    inp = action_block["input"]

    if name == "left_click":
        subprocess.run(["xdotool", "mousemove",
                         str(inp["x"]), str(inp["y"])],
                        env={"DISPLAY": DISPLAY})
        subprocess.run(["xdotool", "click", "1"],
                        env={"DISPLAY": DISPLAY})
        print(f"🖱️ Click at ({inp['x']}, {inp['y']})")

    elif name == "type":
        subprocess.run(["xdotool", "type", inp["text"]],
                        env={"DISPLAY": DISPLAY})
        print(f"⌨️ Typed: {inp['text'][:50]}")

    elif name == "key":
        subprocess.run(["xdotool", "key", inp["text"]],
                        env={"DISPLAY": DISPLAY})

    elif name == "scroll":
        scroll_y = inp["scroll_y"]
        subprocess.run(["xdotool", "click", "5" if scroll_y < 0 else "4"],
                        env={"DISPLAY": DISPLAY})

    time.sleep(0.5)  # даём интерфейсу обновиться
    

# 4. Главный цикл: скриншот → анализ → действие

Объединяем всё в асинхронный цикл. Агент делает скриншот экрана через ImageMagick, отправляет Claude, получает действие, исполняет его — и повторяет, пока задача не будет выполнена. Ограничиваем 50 итерациями для безопасности.

def take_screenshot(output_path: str = "/tmp/screen.png"):
    subprocess.run(["import", "-window", "root", output_path],
                    env={"DISPLAY": DISPLAY})

def run_agent_loop(task: str, max_steps: int = 50):
    """Главный цикл Computer Use агента."""
    messages = [{"role": "user", "content": task}]

    for step in range(max_steps):
        print(f"\n--- Step {step + 1}/{max_steps} ---")

        # 1. Скриншот
        take_screenshot()

        # 2. Отправляем Claude
        action = get_computer_action("/tmp/screen.png", task)

        # 3. Если модель решила, что задача выполнена
        if action[0].type == "text" and "done" in str(action[0].text).lower():
            print("✅ Task completed!")
            break

        # 4. Исполняем действие
        for block in action:
            if block.type == "tool_use":
                execute_action({
                    "name": block.name,
                    "input": block.input
                })

# Запуск: открыть Firefox, найти погоду в Москве
run_agent_loop(
    "Открой Firefox, перейди на google.com, "
    "найди погоду в Москве и запиши результат в текстовый файл"
)
    

# 5. Автоматизация браузера: заполнение веб-форм

Практический пример: агент открывает браузер, переходит на сайт с формой обратной связи, заполняет поля и отправляет. Вся навигация происходит через анализ скриншотов, а не через DOM — поэтому работает с любым сайтом, включая SPA и Canvas-приложения.

# Сценарий: заполнить форму на сайте компании
form_task = """
1. Открой Firefox (иконка на рабочем столе)
2. В адресной строке введи https://example.com/contact
3. Найди поле "Имя" и введи "Иван Петров"
4. Найди поле "Email" и введи "ivan@company.ru"
5. Найди поле "Сообщение" и введи "Здравствуйте, интересует демо"
6. Нажми кнопку "Отправить"
7. Дождись сообщения об успешной отправке
"""

run_agent_loop(form_task)

# Claude сам определит координаты полей по скриншотам
# и будет кликать/печатать без CSS-селекторов
    

# 6. Обработка ошибок и восстановление

В реальной работе интерфейс может измениться, появиться неожиданное модальное окно или alert. Добавляем обработку ошибок и механизм восстановления: если Claude не смог выполнить действие три раза подряд — делаем скриншот всей ситуации и запрашиваем новую стратегию.

def robust_agent_loop(task: str):
    """Цикл с восстановлением после ошибок."""
    consecutive_failures = 0

    for step in range(50):
        try:
            take_screenshot()
            action = get_computer_action("/tmp/screen.png", task)

            if action[0].type == "text":
                text = action[0].text.lower()
                if "unexpected" in text or "error" in text:
                    consecutive_failures += 1
                    if consecutive_failures >= 3:
                        # Запрашиваем новую стратегию
                        task += "\nЧто-то пошло не так. Опиши, что видишь на экране, и предложи новый план."
                        continue
                else:
                    consecutive_failures = 0

            for block in action:
                if block.type == "tool_use":
                    execute_action({"name": block.name, "input": block.input})

        except Exception as e:
            print(f"⚠️ Error: {e}, retrying...")
            consecutive_failures += 1
            time.sleep(2)
    
✅ Итог

Claude Computer Use — это мощный подход к автоматизации GUI, не требующий селекторов и знания DOM. Агент видит экран как человек и принимает решения на основе визуального контекста. Решение идеально подходит для автоматизации legacy-приложений, тестирования UI и задач, где нет API. Полный цикл «скриншот → анализ → действие» укладывается в 2-5 секунд на шаг при использовании Claude Sonnet.

🔗 Полезные ссылки

📖 Документация 💻 GitHub 🛠️ Build with Claude