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çãoResponsabilidades
Cliente / hostInicia 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 ACPAceita 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.

Rendering architecture…

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

Rendering architecture…

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/close libera a sessão ativa e seus processos;
  • session/resume se conecta ao estado de sessão ADK persistido;
  • session/load reativa uma sessão persistida e reproduz sua conversa armazenada para o cliente como notificações session/update ordenadas antes de a solicitação ser concluída;
  • session/fork ramifica 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/delete remove a sessão persistida;
  • session/list retorna sessões visíveis por meio do SessionService configurado.

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_mode valida o modo solicitado em relação ao conjunto anunciado, registra-o e emite um CurrentModeUpdate; 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_option valida o valor em relação às escolhas declaradas da opção, registra-o e emite um ConfigOptionUpdate; uma opção desconhecida ou um valor inválido é rejeitado.
  • Comandos disponíveis — slash-commands ACP exibidos como um AvailableCommandsUpdate quando 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 UsageUpdate refletindo 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 ToolCall com um kind de ferramenta inferido do comportamento declarado da ferramenta. Seu ToolCallUpdate posterior 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 da ToolCall de 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.

Próximo

Arquitetura do Agent Client Protocol - Documentação ADK-Rust | ADK-Rust