Pular para o conteúdo
OmniRoute source

ACP (Agent Client Protocol) (Português (Brasil))

O ACP (Agent Client Protocol) é um transporte de “CLI como backend” para o OmniRoute. Em vez de interceptar chamadas de API HTTP para provedores de IA, o ACP inicia agentes de CLI como processos filhos e envia prompts por meio de suas interfaces nativas.

Benefício Descrição
Não requer chaves de API Usa a autenticação existente da sua CLI
Protocolo nativo Usa o formato nativo de entrada/saída de cada CLI
Descoberta automática Detecta as CLIs instaladas no seu sistema
15 agentes integrados Pré-configurados para ferramentas de CLI populares
Agentes personalizados Adicione suas próprias ferramentas de CLI pelas configurações
Gerenciamento de processos Gerencia o ciclo de vida (iniciar, enviar, encerrar)

O ACP oferece suporte nativo a 15 agentes de CLI integrados:

ID do agente Nome de exibição Binário Protocolo
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

Você pode adicionar seus próprios agentes de CLI pelas configurações. Os agentes personalizados oferecem os mesmos recursos que os agentes integrados.


Janela do terminal
# Exemplo: instalar o Claude Code CLI
npm install -g @anthropic-ai/claude-code
# Verificar a instalação
claude --version

O ACP detecta automaticamente os agentes de CLI instalados no seu sistema. Nenhuma configuração é necessária!

Após a detecção, o ACP pode ser usado como transporte para qualquer provedor compatível. O OmniRoute usará o ACP automaticamente quando a CLI estiver disponível.


┌─────────────────┐
│ OmniRoute │
│ (Proxy HTTP) │
└────────┬────────┘
│
│ spawn()
▼
┌─────────────────┐
│ Processo filho │
│ (Agente de CLI)│
│ │
│ stdin ◄──────┤ Enviar prompt
│ stdout ──────►│ Receber resposta
│ stderr ──────►│ Receber erros
└─────────────────┘
  1. Inicialização — O ACP cria um processo filho para o agente de CLI
  2. Envio — O ACP grava prompts no stdin do processo
  3. Recebimento — O ACP lê respostas do stdout/stderr
  4. Detecção de inatividade — O ACP aguarda 2 segundos de inatividade antes de considerar a resposta concluída
  5. Encerramento — O ACP encerra o processo (SIGTERM e, depois, SIGKILL após 5s)

O ACP usa stdio (entrada/saída padrão) para se comunicar com agentes de CLI. O protocolo é:

  1. Enviar prompt — Gravar no stdin com uma nova linha
  2. Aguardar resposta — Ler o stdout até que fique inativo (2s sem saída)
  3. Tempo limite — 120 segundos por padrão (configurável)

Detecta todos os agentes de CLI instalados no sistema. Os resultados são armazenados em cache por 60 segundos.

import { detectInstalledAgents } from "@/lib/acp";
const agents = detectInstalledAgents();
// Retorna: CliAgentInfo[]
interface CliAgentInfo {
id: string; // por exemplo, "codex", "claude"
name: string; // Nome de exibição
binary: string; // Nome do binário a ser iniciado
versionCommand: string; // Comando de detecção da versão
version: string | null; // Versão detectada (null se não estiver instalado)
installed: boolean; // Indica se o agente está instalado
providerAlias: string; // ID do provedor no OmniRoute
spawnArgs: string[]; // Argumentos a serem passados ao iniciar
protocol: "stdio" | "http"; // Protocolo de comunicação
isCustom?: boolean; // Indica se este é um agente personalizado definido pelo usuário
}

Obtém somente os agentes que estão instalados e disponíveis para o ACP.

import { getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();
// Retorna: CliAgentInfo[] (somente agentes instalados)

Obtém um agente específico pelo ID.

import { getAgentById } from "@/lib/acp";
const agent = getAgentById("claude");
// Retorna: CliAgentInfo | undefined

Define as configurações de agentes personalizados.

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",
},
]);

Inicia um novo processo de agente de CLI.

import { acpManager } from "@/lib/acp";
const session = acpManager.spawn("claude", "claude", ["--print", "--output-format", "json"], {
/* variáveis de ambiente personalizadas */
});
// Retorna: AcpSession

IDs de agente permitidos: ["claude", "codex", "gemini", "qwen"]

acpManager.sendPrompt(sessionId, prompt, timeoutMs)

Seção intitulada “acpManager.sendPrompt(sessionId, prompt, timeoutMs)”

Envia um prompt a um agente de CLI e coleta a resposta.

import { acpManager } from "@/lib/acp";
const response = await acpManager.sendPrompt(
"acp-claude-1234567890-abc123",
"What is 2+2?",
120000 // tempo limite de 2 minutos
);
// Retorna: Promise<string>

Encerra uma sessão e realiza a limpeza.

import { acpManager } from "@/lib/acp";
const killed = acpManager.kill("acp-claude-1234567890-abc123");
// Retorna: boolean

Obtém todas as sessões ativas.

import { acpManager } from "@/lib/acp";
const sessions = acpManager.getActiveSessions();
// Retorna: AcpSession[]

Encerra todas as sessões.

import { acpManager } from "@/lib/acp";
acpManager.killAll();
interface AcpSession {
id: string; // ID exclusivo da sessão
agentId: string; // ID do agente (por exemplo, "claude")
process: ChildProcess; // Referência do processo filho
alive: boolean; // Indica se o processo está ativo
stdoutBuffer: string; // Buffer acumulado de stdout
stderrBuffer: string; // Buffer acumulado de stderr
createdAt: Date; // Data e hora de criação
}

O AcpManager estende EventEmitter e emite os seguintes eventos:

Emitido quando o agente de CLI grava em stdout.

acpManager.on("stdout", ({ sessionId, data }) => {
console.log(`[${sessionId}] stdout: ${data}`);
});

Emitido quando o agente de CLI grava em stderr.

acpManager.on("stderr", ({ sessionId, data }) => {
console.error(`[${sessionId}] stderr: ${data}`);
});

Emitido quando o processo do agente de CLI é encerrado.

acpManager.on("exit", ({ sessionId, code, signal }) => {
console.log(`[${sessionId}] exited with code ${code}, signal ${signal}`);
});

Emitido quando ocorre um erro no processo do agente de CLI.

acpManager.on("error", ({ sessionId, error }) => {
console.error(`[${sessionId}] error: ${error}`);
});

O ACP herda todas as variáveis de ambiente do processo pai e pode ser estendido com variáveis de ambiente personalizadas:

acpManager.spawn("claude", "claude", [], {
ANTHROPIC_API_KEY: "sk-...",
DEBUG: "true",
});

Cada agente possui argumentos de inicialização padrão definidos no registro. Você pode substituí-los:

acpManager.spawn("claude", "claude", ["--print", "--verbose"], {});

O tempo limite padrão para prompts é de 120 segundos (2 minutos). Você pode substituí-lo:

await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 minutos

A detecção de agentes é armazenada em cache por 60 segundos para evitar verificações custosas no sistema de arquivos. Para forçar a atualização:

import { refreshAgentCache } from "@/lib/acp";
refreshAgentCache();

O ACP valida os comandos de versão para evitar ataques de injeção de comandos:

const DISALLOWED_VERSION_COMMAND_CHARS = /[;&|<>`$\r\n]/;

Comandos de versão que contêm estes caracteres são rejeitados:

  • ; — Separador de comandos
  • & — Processo em segundo plano
  • | — Pipe
  • <, > — Redirecionamento
  • ` — Substituição de comando
  • $ — Expansão de variável
  • \r, \n — Quebras de linha

O ACP valida se o binário do comando de versão corresponde ao nome esperado do binário (a menos que seja um agente personalizado).

Cada sessão ACP é executada em seu próprio processo filho. O processo é encerrado quando a sessão termina ou atinge o tempo limite.


  • Primeira chamada: ~50-200ms (executa o comando version para cada agente)
  • Chamadas em cache: <1ms (retorna do cache)
  • TTL do cache: 60 segundos
  • Inicialização: ~50-100ms
  • Envio do prompt: ~10-50ms
  • Espera pela resposta: Depende do agente de CLI (normalmente de 1 a 30 segundos)
  • Encerramento: ~5 segundos (SIGTERM) + imediato (SIGKILL)
  • Memória por sessão: ~10-50MB (depende do agente de CLI)
  • CPU: Mínimo (limitado por E/S)
  • Disco: Nenhum

Problema: acpManager.spawn() gera Unknown agent: &lt;id&gt;

Solução: Apenas estes agentes são permitidos em spawn():

  • claude
  • codex
  • gemini
  • qwen

Outros agentes devem ser inicializados manualmente ou por meio de definições de agentes personalizados.

Problema: acpManager.sendPrompt() gera Session ${sessionId} is not alive

Solução: A sessão pode ter sido encerrada ou finalizada. Verifique o status da sessão:

const session = acpManager.getSession(sessionId);
if (!session?.alive) {
// Reinicialize a sessão
acpManager.spawn("claude", "claude", [], {});
}

Problema: acpManager.sendPrompt() gera ACP timeout after 120000ms

Solução: Aumente o tempo limite:

await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 minutos

Problema: detectInstalledAgents() não encontra sua CLI

Soluções:

  1. Verifique o PATH: Certifique-se de que a CLI esteja no PATH do sistema
  2. Verifique o comando de versão: Execute claude --version manualmente
  3. Verifique as permissões: Certifique-se de que a CLI seja executável
  4. Agente personalizado: Adicione uma definição de agente personalizado para CLIs não padronizadas

Problema: O ACP não consegue executar a CLI

Soluções:

  1. Verifique as permissões do arquivo: chmod +x /usr/local/bin/claude
  2. Verifique a propriedade: Certifique-se de que o OmniRoute tenha permissões de leitura/execução
  3. Verifique o SELinux/AppArmor: Pode bloquear a inicialização de processos

import { acpManager, detectInstalledAgents } from "@/lib/acp";
// Detectar agentes instalados
const agents = detectInstalledAgents();
const claude = agents.find((a) => a.id === "claude");
if (claude?.installed) {
// Iniciar uma nova sessão
const session = acpManager.spawn("claude", claude.binary, ["--print", "--output-format", "json"]);
// Enviar um prompt
const response = await acpManager.sendPrompt(
session.id,
"Explain quantum computing in 100 words"
);
console.log("Claude's response:", response);
// Limpar recursos
acpManager.kill(session.id);
}
import { acpManager, getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();
// Tentar o Claude primeiro; usar o Codex como alternativa
let agentId = "claude";
if (!available.find((a) => a.id === "claude")) {
if (available.find((a) => a.id === "codex")) {
agentId = "codex";
} else {
throw new Error("No ACP-compatible CLI agent found");
}
}
const agent = available.find((a) => a.id === agentId)!;
const session = acpManager.spawn(agentId, agent.binary, agent.spawnArgs);
const response = await acpManager.sendPrompt(session.id, "Hello!");
acpManager.kill(session.id);
import { setCustomAgents, detectInstalledAgents } from "@/lib/acp";
// Registrar um agente de CLI personalizado
setCustomAgents([
{
id: "my-llm-cli",
name: "My LLM CLI",
binary: "myllm",
versionCommand: "myllm --version",
providerAlias: "my-llm-provider",
spawnArgs: ["--format", "json"],
protocol: "stdio",
},
]);
// Agora, detectInstalledAgents() incluirá "my-llm-cli"
const agents = detectInstalledAgents();


  • Projeto AionUi — Inspiração para a detecção automática de ACP
  • Código-fonte do ACP — Detalhes da implementação
    • manager.ts — Gerenciamento do ciclo de vida dos processos
    • registry.ts — Descoberta e registro de agentes
    • index.ts — Exportações da API pública

Código-fonte do OmniRoute (a58000c7685f)

HagiCode

HagiCode é um ambiente de programação com agentes, fluxos estruturados, execução multiagente e visualizações Hero Dungeon.

Transforme ideias em software útil com um fluxo de trabalho com agentes mais inteligente, rápido e agradável.

Interface principal do HagiCode no tema claro
  • SmartFluxos estruturados transformam intenções em um caminho executável da ideia à entrega.
  • EfficientFluxos multiagente mantêm pesquisa, implementação e revisão em andamento simultaneamente.
  • FunO Hero Dungeon torna longas sessões de programação mais visuais e colaborativas.
Acessar HagiCode