ACP (Agent Client Protocol) (Русский)
Что такое ACP?
Заголовок раздела «Что такое ACP?»ACP (Agent Client Protocol) — это транспорт типа «CLI как бэкенд» для OmniRoute. Вместо перехвата вызовов HTTP API к поставщикам ИИ ACP запускает CLI-агенты как дочерние процессы и передаёт запросы через их нативный интерфейс.
Зачем использовать ACP?
Заголовок раздела «Зачем использовать ACP?»| Преимущество | Описание |
|---|---|
| API-ключи не требуются | Использует существующую аутентификацию вашего CLI |
| Нативный протокол | Использует нативный формат ввода-вывода каждого CLI |
| Автообнаружение | Обнаруживает установленные в системе CLI |
| 15 встроенных агентов | Предварительно настроен для популярных CLI-инструментов |
| Пользовательские агенты | Позволяет добавлять собственные CLI-инструменты через настройки |
| Управление процессами | Управляет жизненным циклом (запуск, отправка, завершение) |
Поддерживаемые CLI-агенты
Заголовок раздела «Поддерживаемые CLI-агенты»ACP изначально поддерживает 15 встроенных CLI-агентов:
| ID агента | Отображаемое имя | Исполняемый файл | Протокол |
|---|---|---|---|
codex |
OpenAI Codex CLI | codex |
stdio |
claude |
Claude Code CLI | claude |
stdio |
goose |
Goose CLI | goose |
stdio |
openclaw |
OpenClaw | openclaw |
stdio |
aider |
Aider | aider |
stdio |
opencode |
OpenCode | opencode |
stdio |
cline |
Cline | cline |
stdio |
qwen |
Qwen Code | qwen --acp |
stdio |
forge |
ForgeCode | forge |
stdio |
amazon-q |
Amazon Q Developer | q |
stdio |
interpreter |
Open Interpreter | interpreter |
stdio |
cursor-cli |
Cursor CLI | cursor |
stdio |
warp |
Warp AI | warp |
stdio |
gemini |
Gemini CLI | gemini |
stdio |
zcode |
ZCode | zcode |
stdio |
Пользовательские агенты
Заголовок раздела «Пользовательские агенты»Вы можете добавлять собственные CLI-агенты через настройки. Пользовательские агенты поддерживают те же возможности, что и встроенные.
Быстрый старт
Заголовок раздела «Быстрый старт»Шаг 1. Установите CLI-агент
Заголовок раздела «Шаг 1. Установите CLI-агент»# Пример: установите Claude Code CLInpm install -g @anthropic-ai/claude-code
# Проверьте установкуclaude --versionШаг 2. Автоматическое обнаружение ACP
Заголовок раздела «Шаг 2. Автоматическое обнаружение ACP»ACP автоматически обнаруживает установленные в вашей системе CLI-агенты. Настройка не требуется!
Шаг 3. Используйте транспорт ACP
Заголовок раздела «Шаг 3. Используйте транспорт ACP»После обнаружения ACP можно использовать как транспорт для любого поддерживаемого поставщика. OmniRoute автоматически использует ACP, когда CLI доступен.
Как работает ACP
Заголовок раздела «Как работает ACP»Архитектура
Заголовок раздела «Архитектура»┌─────────────────┐│ OmniRoute ││ (HTTP-прокси) │└────────┬────────┘ │ │ spawn() ▼┌─────────────────┐│ Дочерний процесс││ (CLI-агент) ││ ││ stdin ◄──────┤ Отправка запроса│ stdout ──────►│ Получение ответа│ stderr ──────►│ Получение ошибок└─────────────────┘Жизненный цикл процесса
Заголовок раздела «Жизненный цикл процесса»- Запуск — ACP создаёт дочерний процесс для CLI-агента
- Отправка — ACP записывает запросы в stdin процесса
- Получение — ACP считывает ответы из stdout/stderr
- Обнаружение простоя — ACP ожидает 2 секунды бездействия, прежде чем считать ответ завершённым
- Завершение — ACP завершает процесс (SIGTERM, затем SIGKILL через 5 секунд)
Протокол взаимодействия
Заголовок раздела «Протокол взаимодействия»Для взаимодействия с CLI-агентами ACP использует stdio (стандартный ввод-вывод). Протокол выглядит следующим образом:
- Отправка запроса — запись в stdin с символом новой строки
- Ожидание ответа — чтение из stdout до наступления простоя (отсутствие вывода в течение 2 секунд)
- Тайм-аут — по умолчанию 120 секунд (настраивается)
Справочник API
Заголовок раздела «Справочник API»Функции реестра
Заголовок раздела «Функции реестра»detectInstalledAgents()
Заголовок раздела «detectInstalledAgents()»Обнаруживает все установленные в системе CLI-агенты. Результаты кэшируются на 60 секунд.
import { detectInstalledAgents } from "@/lib/acp";
const agents = detectInstalledAgents();// Возвращает: CliAgentInfo[]
interface CliAgentInfo { id: string; // например, "codex", "claude" name: string; // Отображаемое имя binary: string; // Имя запускаемого бинарного файла versionCommand: string; // Команда определения версии version: string | null; // Обнаруженная версия (null, если не установлен) installed: boolean; // Установлен ли агент providerAlias: string; // ID провайдера в OmniRoute spawnArgs: string[]; // Аргументы, передаваемые при запуске protocol: "stdio" | "http"; // Протокол связи isCustom?: boolean; // Является ли агент пользовательским}getAvailableAgents()
Заголовок раздела «getAvailableAgents()»Получает только агенты, которые установлены и доступны для ACP.
import { getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();// Возвращает: CliAgentInfo[] (только установленные агенты)getAgentById(id)
Заголовок раздела «getAgentById(id)»Получает конкретного агента по ID.
import { getAgentById } from "@/lib/acp";
const agent = getAgentById("claude");// Возвращает: CliAgentInfo | undefinedsetCustomAgents(agents)
Заголовок раздела «setCustomAgents(agents)»Устанавливает определения пользовательских агентов из настроек.
import { setCustomAgents } from "@/lib/acp";
setCustomAgents([ { id: "my-custom-cli", name: "My Custom CLI", binary: "mycli", versionCommand: "mycli --version", providerAlias: "my-provider", spawnArgs: [], protocol: "stdio", },]);Функции менеджера
Заголовок раздела «Функции менеджера»acpManager.spawn(agentId, binary, args, env)
Заголовок раздела «acpManager.spawn(agentId, binary, args, env)»Запускает новый процесс CLI-агента.
import { acpManager } from "@/lib/acp";
const session = acpManager.spawn("claude", "claude", ["--print", "--output-format", "json"], { /* пользовательские переменные окружения */});// Возвращает: AcpSessionДопустимые ID агентов: ["claude", "codex", "gemini", "qwen"]
acpManager.sendPrompt(sessionId, prompt, timeoutMs)
Заголовок раздела «acpManager.sendPrompt(sessionId, prompt, timeoutMs)»Отправляет запрос CLI-агенту и получает ответ.
import { acpManager } from "@/lib/acp";
const response = await acpManager.sendPrompt( "acp-claude-1234567890-abc123", "What is 2+2?", 120000 // тайм-аут 2 минуты);// Возвращает: Promise<string>acpManager.kill(sessionId)
Заголовок раздела «acpManager.kill(sessionId)»Завершает сеанс и освобождает ресурсы.
import { acpManager } from "@/lib/acp";
const killed = acpManager.kill("acp-claude-1234567890-abc123");// Возвращает: booleanacpManager.getActiveSessions()
Заголовок раздела «acpManager.getActiveSessions()»Получает все активные сеансы.
import { acpManager } from "@/lib/acp";
const sessions = acpManager.getActiveSessions();// Возвращает: AcpSession[]acpManager.killAll()
Заголовок раздела «acpManager.killAll()»Завершает все сеансы.
import { acpManager } from "@/lib/acp";
acpManager.killAll();Интерфейс сеанса
Заголовок раздела «Интерфейс сеанса»interface AcpSession { id: string; // Уникальный ID сеанса agentId: string; // ID агента (например, "claude") process: ChildProcess; // Дескриптор дочернего процесса alive: boolean; // Активен ли процесс stdoutBuffer: string; // Накопленный буфер stdout stderrBuffer: string; // Накопленный буфер stderr createdAt: Date; // Временная метка создания}События
Заголовок раздела «События»AcpManager расширяет EventEmitter и генерирует следующие события:
Генерируется, когда CLI-агент записывает данные в stdout.
acpManager.on("stdout", ({ sessionId, data }) => { console.log(`[${sessionId}] stdout: ${data}`);});Генерируется, когда CLI-агент записывает данные в stderr.
acpManager.on("stderr", ({ sessionId, data }) => { console.error(`[${sessionId}] stderr: ${data}`);});Генерируется при завершении процесса CLI-агента.
acpManager.on("exit", ({ sessionId, code, signal }) => { console.log(`[${sessionId}] exited with code ${code}, signal ${signal}`);});Генерируется при возникновении ошибки в процессе CLI-агента.
acpManager.on("error", ({ sessionId, error }) => { console.error(`[${sessionId}] error: ${error}`);});Конфигурация
Заголовок раздела «Конфигурация»Переменные окружения
Заголовок раздела «Переменные окружения»ACP наследует все переменные окружения родительского процесса и может быть дополнен пользовательскими переменными окружения:
acpManager.spawn("claude", "claude", [], { ANTHROPIC_API_KEY: "sk-...", DEBUG: "true",});Аргументы запуска
Заголовок раздела «Аргументы запуска»Каждый агент имеет аргументы запуска по умолчанию, определённые в реестре. Их можно переопределить:
acpManager.spawn("claude", "claude", ["--print", "--verbose"], {});Тайм-ауты
Заголовок раздела «Тайм-ауты»Тайм-аут запроса по умолчанию составляет 120 секунд (2 минуты). Его можно переопределить:
await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 минутКеш обнаружения
Заголовок раздела «Кеш обнаружения»Результаты обнаружения агентов кешируются на 60 секунд, чтобы избежать ресурсоёмкого сканирования файловой системы. Чтобы принудительно обновить кеш:
import { refreshAgentCache } from "@/lib/acp";
refreshAgentCache();Безопасность
Заголовок раздела «Безопасность»Предотвращение внедрения команд
Заголовок раздела «Предотвращение внедрения команд»ACP проверяет команды получения версии, чтобы предотвратить атаки с внедрением команд:
const DISALLOWED_VERSION_COMMAND_CHARS = /[;&|<>`$\r\n]/;Команды получения версии, содержащие следующие символы, отклоняются:
;— Разделитель команд&— Фоновый процесс|— Конвейер<,>— Перенаправление`— Подстановка команды$— Подстановка переменной\r,\n— Переносы строк
Проверка имени исполняемого файла
Заголовок раздела «Проверка имени исполняемого файла»ACP проверяет, совпадает ли исполняемый файл в команде получения версии с ожидаемым именем исполняемого файла (кроме случаев, когда используется пользовательский агент).
Изоляция процессов
Заголовок раздела «Изоляция процессов»Каждый сеанс ACP выполняется в отдельном дочернем процессе. Процесс завершается при окончании сеанса или по истечении тайм-аута.
Производительность
Заголовок раздела «Производительность»Производительность обнаружения
Заголовок раздела «Производительность обнаружения»- Первый вызов: ~50-200 мс (выполняет команду
versionдля каждого агента) - Кешированные вызовы: <1 мс (возвращает результат из кеша)
- TTL кеша: 60 секунд
Производительность обработки запросов
Заголовок раздела «Производительность обработки запросов»- Запуск: ~50-100 мс
- Отправка запроса: ~10-50 мс
- Ожидание ответа: Зависит от CLI-агента (обычно 1-30 секунд)
- Завершение: ~5 секунд (SIGTERM) + немедленно (SIGKILL)
Использование ресурсов
Заголовок раздела «Использование ресурсов»- Память на сеанс: ~10-50 МБ (зависит от CLI-агента)
- ЦП: Минимальное использование (ограничено операциями ввода-вывода)
- Диск: Не используется
Устранение неполадок
Заголовок раздела «Устранение неполадок»Ошибка “Unknown agent”
Заголовок раздела «Ошибка “Unknown agent”»Проблема: acpManager.spawn() выдаёт ошибку Unknown agent: <id>
Решение: В spawn() разрешены только следующие агенты:
claudecodexgeminiqwen
Другие агенты необходимо запускать вручную или с помощью пользовательских определений агентов.
Ошибка “Session not alive”
Заголовок раздела «Ошибка “Session not alive”»Проблема: acpManager.sendPrompt() выдаёт ошибку Session ${sessionId} is not alive
Решение: Возможно, сеанс завершился или был принудительно остановлен. Проверьте состояние сеанса:
const session = acpManager.getSession(sessionId);if (!session?.alive) { // Повторно запустите сеанс acpManager.spawn("claude", "claude", [], {});}Ошибка “ACP timeout”
Заголовок раздела «Ошибка “ACP timeout”»Проблема: acpManager.sendPrompt() выдаёт ошибку ACP timeout after 120000ms
Решение: Увеличьте тайм-аут:
await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 минутCLI не обнаружен
Заголовок раздела «CLI не обнаружен»Проблема: detectInstalledAgents() не находит ваш CLI
Решения:
- Проверьте PATH: Убедитесь, что CLI находится в системной переменной PATH
- Проверьте команду получения версии: Выполните
claude --versionвручную - Проверьте разрешения: Убедитесь, что CLI является исполняемым
- Пользовательский агент: Добавьте пользовательское определение агента для нестандартных CLI
Доступ запрещён
Заголовок раздела «Доступ запрещён»Проблема: ACP не может выполнить CLI
Решения:
- Проверьте права доступа к файлу:
chmod +x /usr/local/bin/claude - Проверьте владельца: Убедитесь, что OmniRoute имеет права на чтение и выполнение
- Проверьте SELinux/AppArmor: Эти системы могут блокировать запуск процессов
Примеры
Заголовок раздела «Примеры»Пример 1: Запуск и использование Claude Code
Заголовок раздела «Пример 1: Запуск и использование Claude Code»import { acpManager, detectInstalledAgents } from "@/lib/acp";
// Обнаружение установленных агентовconst agents = detectInstalledAgents();const claude = agents.find((a) => a.id === "claude");
if (claude?.installed) { // Запуск нового сеанса const session = acpManager.spawn("claude", claude.binary, ["--print", "--output-format", "json"]);
// Отправка запроса const response = await acpManager.sendPrompt( session.id, "Объясни квантовые вычисления в 100 словах" );
console.log("Ответ Claude:", response);
// Очистка ресурсов acpManager.kill(session.id);}Пример 2: Автоматическое обнаружение с резервным вариантом
Заголовок раздела «Пример 2: Автоматическое обнаружение с резервным вариантом»import { acpManager, getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();
// Сначала пробуем Claude, затем используем Codex как резервный вариантlet agentId = "claude";if (!available.find((a) => a.id === "claude")) { if (available.find((a) => a.id === "codex")) { agentId = "codex"; } else { throw new Error("ACP-совместимый CLI-агент не найден"); }}
const agent = available.find((a) => a.id === agentId)!;const session = acpManager.spawn(agentId, agent.binary, agent.spawnArgs);
const response = await acpManager.sendPrompt(session.id, "Привет!");
acpManager.kill(session.id);Пример 3: Пользовательский агент
Заголовок раздела «Пример 3: Пользовательский агент»import { setCustomAgents, detectInstalledAgents } from "@/lib/acp";
// Регистрация пользовательского CLI-агентаsetCustomAgents([ { id: "my-llm-cli", name: "My LLM CLI", binary: "myllm", versionCommand: "myllm --version", providerAlias: "my-llm-provider", spawnArgs: ["--format", "json"], protocol: "stdio", },]);
// Теперь detectInstalledAgents() будет включать "my-llm-cli"const agents = detectInstalledAgents();Что дальше?
Заголовок раздела «Что дальше?»- Справочник по API — Конечные точки REST API
- Справочник по провайдерам — Все 352 провайдера
- Сервер MCP — Интеграция Model Context Protocol
- Сервер A2A — Протокол взаимодействия между агентами
- Облачный агент — Облачные агенты
Справочные материалы
Заголовок раздела «Справочные материалы»- Проект AionUi — Источник вдохновения для автоматического обнаружения ACP
- Исходный код ACP — Подробности реализации
manager.ts— Управление жизненным циклом процессовregistry.ts— Обнаружение и регистрация агентовindex.ts— Экспорт публичного API
HagiCode
HagiCode — агентная среда разработки со структурированными процессами, параллельным выполнением несколькими агентами и интерфейсами Hero Dungeon.
Превращайте идеи в полезное ПО с более умным, быстрым и увлекательным агентным рабочим процессом.

- SmartСтруктурированные процессы превращают намерение в исполнимый путь от идеи до готового изменения.
- EfficientМультиагентные процессы параллельно продвигают исследование, реализацию и проверку.
- FunHero Dungeon делает длительную совместную разработку наглядной и увлекательной.