Arquitetura do Agent Client Protocol
ACP padroniza a relação entre uma interface de programação e um agente de programação. Ele lhes dá uma maneira comum de estabelecer capacidades, abrir uma sessão de projeto, trocar prompts, transmitir progresso, solicitar permissão, cancelar o trabalho e encerrar ou retomar a sessão.
As duas funções
| Função | Responsabilidades |
|---|---|
| Cliente / host | Inicia o processo do agente, apresenta a interface humana, seleciona o workspace, fornece arquivos, terminais e servidores MCP opcionais, aplica a política de permissão e renderiza atualizações em tempo real |
| Agente ACP | Aceita sessões de projeto e prompts, executa o trabalho de codificação, relata mensagens e atividade de ferramentas, solicita permissão quando necessário e retorna um motivo de parada tipado |
ADK-Rust pode ocupar qualquer um dos papéis. Essas são duas direções de implantação, não dois protocolos diferentes.
Quando ADK-Rust consome outro agente de codificação, o lado esquerdo é ADK-Rust e o
lado direito é o processo externo. Quando um editor consome um agente ADK-Rust,
o editor controla o lado esquerdo e AcpServer controla o lado direito.
Uma rodada de ACP
A conexão é bidirecional. Um cliente deve continuar lendo enquanto um prompt está em execução porque o agente pode enviar notificações ou solicitações de permissão antes da resposta final do prompt.
Identidade e estado da sessão
Uma sessão ACP identifica uma conversa contínua sobre um projeto. Ela
contém um cwd absoluto, diretórios adicionais opcionais, vários prompts,
atualizações em streaming e um ciclo de vida. No servidor ADK-Rust, uma sessão
ACP se mapeia para uma sessão ADK-Rust, de modo que o histórico do modelo e o estado da sessão permaneçam associados
à mesma conversa.
Fechar uma conexão ativa é diferente de excluir o histórico persistido:
session/closelibera a sessão ativa e seus processos;session/resumese conecta ao estado de sessão ADK persistido;session/loadreativa uma sessão persistida e reproduz sua conversa armazenada para o cliente como notificaçõessession/updateordenadas antes de a solicitação ser concluída;session/forkramifica uma sessão persistida em um novo id de sessão cujo histórico armazenado é uma cópia do histórico da origem, deixando a origem intocada;session/deleteremove a sessão persistida;session/listretorna sessões visíveis por meio doSessionServiceconfigurado.
session/load valida o cwd fornecido em relação ao diretório de trabalho armazenado da sessão
da mesma forma que session/resume faz, e retorna um erro de sessão não encontrada
para um identificador de sessão desconhecido. A reprodução mapeia cada evento de usuário, agente, pensamento e ferramenta armazenado para sua variante correspondente de SessionUpdate na ordem cronológica original, para que um editor que se reconecta restaure o histórico visível na ordem em que aconteceu.
Controles interativos da sessão
Um agente pode expor controles interativos ao cliente fornecendo um
provedor SessionControls. Quando faz isso, o servidor os anuncia nas respostas
session/new, session/load, session/resume e session/fork:
- Modos — um conjunto de modos nomeados (por exemplo, "ask" versus "code") com uma
seleção atual.
session/set_modevalida o modo solicitado em relação ao conjunto anunciado, registra-o e emite umCurrentModeUpdate; um modo desconhecido é rejeitado e o modo atual permanece inalterado. - Opções de configuração — seletores e alternâncias que um cliente pode ler e alterar.
session/set_config_optionvalida o valor em relação às escolhas declaradas da opção, registra-o e emite umConfigOptionUpdate; uma opção desconhecida ou um valor inválido é rejeitado. - Comandos disponíveis — slash-commands ACP exibidos como um
AvailableCommandsUpdatequando uma sessão se torna ativa.
As seleções de modo e configuração persistem no estado da sessão ADK (acp:mode,
acp:config:<id>), então sobrevivem a carregamento, retomada e fork. Um título de sessão
registrado aparece como um SessionInfoUpdate na ativação e sempre que muda. Um
mapeamento de atualização Plan existe, mas permanece dormente até que um primitivo de plano ADK
aponte entradas de plano. Um agente que não fornece SessionControls
não anuncia modos nem opções, mantendo as capacidades anunciadas exatamente alinhadas com o que
o servidor implementa.
O conteúdo cruza a fronteira por meio de um único mapeamento
Prompts que chegam de um cliente e atualizações que voltam em streaming para ele passam
ambos por um único módulo de conteúdo que mapeia valores ACP ContentBlock para
valores adk_core::Part e vice-versa. Manter um único mapeamento em ambas as direções significa
que o parser de prompt do servidor, o streamer do servidor e o cliente concordam sobre como
cada tipo de conteúdo é representado.
O mapeamento preserva os payloads fielmente. Blocos de texto mapeiam para Part::Text com
a string intacta. Blocos de recurso incorporado mapeiam para Part::EmbeddedResource,
mantendo o URI de origem, o tipo MIME opcional e o conteúdo. Um recurso
de texto trafega literalmente em ambas as direções e nunca é codificado em base64; um
recurso binário é codificado em base64 na transmissão e decodificado para bytes brutos no
lado ADK da fronteira. Blocos de imagem e áudio mapeiam para Part::InlineData,
preservando o tipo MIME e os bytes decodificados; o servidor anuncia e aceita
esses meios de prompt, e o cliente transmite conteúdo não textual ADK (recurso
incorporado, imagem, áudio) como o bloco ACP correspondente em vez de descartá-lo.
Atualizações em streaming carregam mais do que texto
Enquanto um prompt é executado, o servidor traduz eventos ADK tipados em notificações
ACP session/update. O texto e os pensamentos do modelo se tornam chunks de mensagem e
de pensamento, e o conteúdo de recurso incorporado se torna um chunk de mensagem de recurso incorporado. Além dessa
superfície, dois tipos de atualização dão ao cliente uma visão mais rica da rodada:
- Atualizações de uso. Quando um evento ADK carrega metadados de uso, o servidor envia
um
UsageUpdaterefletindo as contagens de tokens reportadas, além do custo em USD quando o runtime o informa. Eventos sem metadados de uso não produzem atualização, e o servidor nunca fabrica contagens. - Atualizações ricas de chamada de ferramenta. Uma chamada de ferramenta começa como um
ToolCallcom umkindde ferramenta inferido do comportamento declarado da ferramenta. SeuToolCallUpdateposterior carrega o conteúdo do resultado da ferramenta e os locais de arquivo que a ferramenta informa ter afetado, para que um editor possa renderizar diffs e listas de arquivos afetados. A atualização mantém o mesmo identificador daToolCallde origem, preservando a correlação ao longo da rodada.
A direção do cliente tem a fidelidade correspondente. Quando uma aplicação ADK-Rust consome um External_Agent, sua superfície de streaming (OutputChunk) expõe não apenas o texto e os pensamentos do agent, mas também o External_Agent do ToolCallUpdate (como uma atualização de tool correlacionada por id que carrega status, tipo, título, texto de conteúdo e locais de arquivo afetados) e o seu UsageUpdate (tokens usados e tamanho, além de custo e moeda quando reportados). O texto da mensagem do agent é exibido exatamente como antes, então os consumidores de texto existentes não são afetados.
Solicitações de permissão fazem a ponte com confirmações de tool
Um agent ADK-Rust pode pausar uma rodada aguardando aprovação humana de uma chamada de tool (ToolConfirmationRequest). No lado do servidor, essa pausa se torna uma solicitação nativa de ACP session/request_permission descrevendo a tool e seus argumentos. O resultado do cliente retoma a rodada: uma aprovação se mapeia para allow, e uma negação ou um cancelamento ambos se mapeiam para deny, de modo que uma solicitação cancelada nunca executa a tool. Cada resultado é correlacionado à chamada exata pelo seu identificador de function-call e devolvido ao runner por meio de suas decisões de confirmação de tool. A solicitação de permissão aninhada é emitida a partir da task de prompt spawnada, então a resposta externa de session/prompt ainda é concluída normalmente.
Capacidades são um contrato
A inicialização não é um handshake decorativo. Cada lado anuncia apenas as operações e o conteúdo que suporta. ADK-Rust usa essas capacidades para evitar enviar configuração opcional de HTTP ou SSE MCP para um agent que aceita apenas stdio, e anuncia operações de sistema de arquivos ou de host de terminal apenas quando a aplicação fornece a implementação correspondente.
O servidor anuncia exatamente os tipos de conteúdo que seu manipulador de prompt aceita. Ele anuncia as capacidades de prompt embedded_context, image e audio porque conteúdo de recurso incorporado se mapeia para adk_core::Part::EmbeddedResource e conteúdo de imagem e áudio se mapeia para adk_core::Part::InlineData. Ele anuncia load_session porque registra um manipulador de session/load, e a capacidade de sessão fork porque registra um manipulador de session/fork. Modos de sessão e opções de configuração são anunciados apenas quando o agent fornece um provedor de SessionControls, então um agent sem um não anuncia nenhum dos dois. Transportes remotos, seletores de modelo e adições experimentais ao protocolo permanecem não anunciados. Um prompt que contenha um tipo de conteúdo que o servidor não anunciou é rejeitado com um erro descritivo em vez de ser tratado parcialmente. Os chamadores devem projetar-se com base no objeto de capacidade negociado, em vez de presumir que toda implementação de ACP tenha a mesma superfície.