Exposer un agent ADK-Rust via ACP
Utilisez lâorientation serveur lorsquâun Ă©diteur ou un autre client ACP doit dĂ©marrer votre binaire ADK-Rust et utiliser son agent dans une interface de codage. Votre processus Rust gĂšre lâagent, le modĂšle, les outils, les flux de travail, les sessions, la mĂ©moire et la politique dâexploitation. Le client ne voit que les capacitĂ©s et le cycle de vie des sessions publiĂ©s via ACP.
Installer la fonctionnalité serveur
[dependencies]
adk-acp = { version = "2.1.0", features = ["server"] }
Construire et servir un agent
use adk_acp::server::{AcpServer, AcpServerConfigBuilder};
use adk_session::InMemorySessionService;
use std::sync::Arc;
let config = AcpServerConfigBuilder::new()
.agent(Arc::new(repository_agent))
.session_service(Arc::new(InMemorySessionService::new()))
.agent_name("repository-guide")
.agent_description("Explains and improves this Rust workspace")
.max_sessions(16)
.build()?;
let handle = AcpServer::run(config).await?;
handle.wait().await?;
Le serveur utilise le générateur officiel Agent de SDK et le transport stdio. Le trafic
du protocole est la seule donnée écrite sur stdout ; configurez la journalisation et les
diagnostics pour utiliser stderr.
Correspondance dâexĂ©cution
Le gestionnaire valide un cwd absolu, réserve la capacité de session, crée ou reprend la
session ADK et exĂ©cute lâagent configurĂ©. Les Ă©vĂ©nements ADK typĂ©s sont traduits en
notifications session/update ACP pendant que lâinvite est active.
Cycle de vie implémenté
| Opération ACP | Comportement ADK-Rust |
|---|---|
initialize | NĂ©gocie le protocole v1 et renvoie les mĂ©tadonnĂ©es exactes de lâimplĂ©mentation et des capacitĂ©s |
session/new | Valide les chemins de lâespace de travail et crĂ©e une session ADK persistante |
session/prompt | Convertit les blocs de contenu pris en charge (text, resource-link, embedded-resource, image, audio) et diffuse le Runner |
session/load | Réactive une session persistée (en validant cwd) et rejoue sa conversation enregistrée sous forme de notifications session/update ordonnées avant de terminer |
session/cancel | Annule lâinvocation active du Runner et renvoie une raison dâarrĂȘt indiquant lâannulation |
$/cancel_request | Annule la requĂȘte JSON-RPC correspondante sans corrompre la session |
session/close | Annule le travail actif et libĂšre les processus appartenant Ă la session |
session/list | Répertorie les sessions persistées visibles par ACP |
session/resume | Se rattache Ă la session et Ă lâespace de travail dâorigine |
session/fork | CrĂ©e une branche dâune session persistĂ©e dans une nouvelle session, en copiant son historique et lâĂ©tat pertinent, tout en laissant la source inchangĂ©e |
session/set_mode | Valide et enregistre un mode de session dĂ©clarĂ© par le SessionControls de lâagent, en Ă©mettant un CurrentModeUpdate |
session/set_config_option | Valide et enregistre une valeur de configuration dĂ©clarĂ©e par le SessionControls de lâagent, en Ă©mettant un ConfigOptionUpdate |
session/delete | Supprime lâhistorique persistant et libĂšre les ressources actives |
Une seule invite peut sâexĂ©cuter Ă la fois dans une session. DiffĂ©rentes sessions peuvent sâexĂ©cuter simultanĂ©ment jusquâĂ max_sessions.
Mappage des événements
- le texte du modĂšle devient
agent_message_chunk; - le contenu de réflexion du modÚle devient
agent_thought_chunk; - le contenu de la ressource intégrée devient une ressource intégrée
agent_message_chunkde ACP ; - les appels de fonction ADK deviennent des mises Ă jour de dĂ©marrage dâoutil ACP avec un outil
kinddĂ©duit ; - les rĂ©ponses de fonction deviennent des mises Ă jour dâachĂšvement de lâoutil enrichies du contenu du rĂ©sultat et de tout emplacement de fichier affectĂ©, associĂ©es Ă lâappel dâoutil dâorigine ;
- les Ă©vĂ©nements contenant des mĂ©tadonnĂ©es dâutilisation deviennent des notifications
UsageUpdate(nombre de jetons, ainsi que le coĂ»t en USD lorsquâil est communiquĂ©) ; - les commandes dĂ©clarĂ©es par lâagent deviennent un
AvailableCommandsUpdatelorsquâune session devient active, et un titre de session enregistrĂ© devient unSessionInfoUpdate; - les entrĂ©es du plan deviendraient une mise Ă jour
Planâ ce mappage existe, mais reste inactif jusquâĂ ce quâune primitive de plan ADK expose les entrĂ©es du plan ; - lâannulation devient
StopReason::Cancelled; - lâachĂšvement normal devient
StopReason::EndTurn.
Un module de contenu partagĂ© gĂšre la correspondance ContentBlock â adk_core::Part
dans les deux sens. Le contenu dâinvite dâune ressource intĂ©grĂ©e est converti en
Part::EmbeddedResource, en préservant la source URI, le type MIME
facultatif et le contenu ; les ressources textuelles sont prĂ©servĂ©es Ă lâidentique,
tandis que les ressources binaires sont encodées en base64 sur le réseau, puis
dĂ©codĂ©es en octets bruts en interne. Le contenu dâinvite dâimage et audio est
converti en Part::InlineData, en préservant le type MIME, les octets
dĂ©codĂ©s, les annotations et la source URI facultative dâune
image. Ces champs restent dans la JSON de session et sont restaurés
par session/load. Comme le gestionnaire dâinvites accepte le contenu de
ressources intĂ©grĂ©es, dâimages et audio, le serveur annonce les capacitĂ©s
dâinvite embedded_context, image et audio. Une invite
contenant un type de contenu que le serveur nâa pas annoncĂ© est rejetĂ©e avec une
erreur explicite au lieu dâĂȘtre traitĂ©e partiellement.
Chargement et relecture de lâhistorique
session/load restaure lâhistorique visible dâune session persistante lorsquâun
client se reconnecte. Le gestionnaire rĂ©active la session de la mĂȘme maniĂšre que
session/resume â en vĂ©rifiant que lâappelant a fourni le cwd
dâorigine et en renvoyant une erreur indiquant que la session est introuvable pour
un identifiant inconnu â puis effectue une passe de relecture. Il lit les
événements persistants via le service de session et convertit chaque événement
stockĂ© dâutilisateur, dâagent, de rĂ©flexion et dâoutil en sa notification
session/update correspondante, dans lâordre chronologique dâorigine, avant la fin de
la requĂȘte de chargement. Le serveur annonce la capacitĂ© load_session afin quâun
client sache quâil peut se reconnecter et reconstruire la vue de la conversation.
Modes de session, options de configuration et bifurcation
Un agent active les contrĂŽles de session interactive en fournissant un fournisseur SessionControls
via AcpServerConfigBuilder::session_controls. Le fournisseur déclare
les modes disponibles (un SessionModeState), les options de configuration (sélections et
boutons bascule), ainsi que les commandes slash ACP. Le serveur annonce exactement ce que le fournisseur
dĂ©clare â un agent sans fournisseur nâannonce aucun mode ni aucune option â et
les expose dans les réponses session/new, session/load, session/resume et
session/fork.
session/set_mode valide lâidentifiant du mode demandĂ© par rapport Ă lâensemble annoncĂ©,
lâenregistre et Ă©met un CurrentModeUpdate ; un identifiant inconnu est rejetĂ© et le
mode actuel reste inchangé. session/set_config_option valide la valeur
par rapport aux choix dĂ©clarĂ©s pour lâoption, lâenregistre et Ă©met un
ConfigOptionUpdate ; une option inconnue ou une valeur non valide est rejetée. Les deux
sĂ©lections sont conservĂ©es dans lâĂ©tat de session ADK sous acp:mode et acp:config:<id>,
et persistent donc lors du chargement, de la reprise et de la crĂ©ation dâune branche.
session/fork crĂ©e une branche dâune session persistante : il lit la session source, crĂ©e
un nouvel identifiant de session, y copie les Ă©vĂ©nements enregistrĂ©s et lâĂ©tat
pertinent (cwd, les répertoires supplémentaires, le mode et la configuration),
puis renvoie le nouvel identifiant. Lâhistorique persistant de la session source
reste inchangĂ© octet par octet. La crĂ©ation dâune branche pour un identifiant de
session inconnu renvoie une erreur indiquant que la session est introuvable. Le serveur annonce la capacité de session
fork, car le gestionnaire est enregistré.
Lors de lâactivation dâune session, le serveur Ă©met Ă©galement un AvailableCommandsUpdate pour toutes les
commandes dĂ©clarĂ©es par le fournisseur (et aucun lorsquâil nâen dĂ©clare aucune), ainsi quâun
SessionInfoUpdate contenant le titre de la session lorsquâun titre est enregistrĂ© sous
acp:title (défini via set_session_title). Un mappage de mise à jour Plan existe, mais
reste inactif jusquâĂ ce quâune primitive de plan ADK expose des entrĂ©es de plan.
Serveurs MCP fournis par le client
Le client peut inclure des serveurs stdio MCP dans session/new ou session/resume.
Le serveur valide les noms, les commandes, les arguments et les entrĂ©es dâenvironnement avant
de démarrer un processus. Il :
- dĂ©marre chaque processus enfant dans lâespace de travail de la session ;
- applique une négociation de démarrage limitée ;
- encapsule la connexion en tant que ADK
McpToolset; - injecte lâensemble dâoutils dans cette invocation de Runner ;
- annule les services MCP lors de la fermeture, de la suppression, dâun Ă©chec du dĂ©marrage ou de lâarrĂȘt du serveur.
Les ensembles dâoutils associĂ©s Ă une invocation sont actuellement rĂ©solus par LlmAgent et
CodeActAgent. Les transports HTTP et SSE MCP facultatifs ne sont pas annoncés par le
serveur.
Décisions de persistance
InMemorySessionService convient Ă un processus dâĂ©diteur local et aux tests. Utilisez
un service durable lorsque les sessions doivent survivre aux redémarrages du processus. La reprise valide
que lâappelant fournit le cwd dâorigine ; une session ne peut pas ĂȘtre rattachĂ©e
silencieusement Ă un autre projet.
Limite dâapprobation des outils
Le serveur fait le lien entre les confirmations dâoutils ADK et les demandes dâautorisation
natives ACP. Lorsque lâagent configurĂ© se met en pause sur un ToolConfirmationRequest pendant un tour
de requĂȘte â signalĂ© sur event.actions.tool_confirmation lorsquâun agent attend
lâapprobation humaine dâun appel dâoutil â le serveur envoie une requĂȘte session/request_permission
dĂ©crivant lâoutil et ses arguments, attend le rĂ©sultat du client, puis
reprend lâexĂ©cution avec la dĂ©cision correspondante. Une approbation est mappĂ©e vers lâautorisation,
et un refus ou une annulation sont tous deux mappĂ©s vers le refus, de sorte quâune requĂȘte annulĂ©e
nâexĂ©cute jamais lâoutil. Chaque rĂ©sultat est associĂ© Ă lâappel exact au moyen de son identifiant
dâappel de fonction et renvoyĂ© au Runner via
RunConfig::tool_confirmation_decisions.
Le session/request_permission imbriquĂ© est Ă©mis depuis la tĂąche qui gĂšre dĂ©jĂ le session/prompt externe, gĂ©nĂ©rĂ© via ConnectionTo::spawn ; il ne bloque donc pas la boucle de distribution de la connexion, et la rĂ©ponse Ă lâinvite externe sâachĂšve tout de mĂȘme. Une inquiĂ©tude prĂ©cĂ©dente selon laquelle le SDK Rust officiel perdrait la rĂ©ponse Ă lâinvite externe aprĂšs une requĂȘte bidirectionnelle imbriquĂ©e ne se reproduit pas avec ce flux de suspension/reprise ; ce cas est couvert par les tests dâinteropĂ©rabilitĂ© en mĂ©moire.
Lâautorisation des outils gĂ©rĂ©e par le serveur, les outils en lecture seule, RBAC, les garde-fous et les interruptions de workflow restent disponibles lorsque lâapprobation doit avoir lieu entiĂšrement au sein du processus ADK-Rust. Le chemin dâautorisation cĂŽtĂ© client pour les agents ACP externes est Ă©galement entiĂšrement implĂ©mentĂ©.
Déployer en toute sécurité
- DĂ©marrez le binaire avec lâespace de travail du projet prĂ©vu.
- Considérez
cwdet les racines supplĂ©mentaires comme un contexte, et non comme un mĂ©canisme dâisolation du systĂšme dâexploitation. - Appliquez
adk-sandbox, un conteneur ou une autre limite de processus pour les invites et commandes non fiables. - Conservez les identifiants du modĂšle et de MCP dans un magasin de secrets client ou dans lâenvironnement du processus.
- NâĂ©crivez jamais de banniĂšres, dâobjets de dĂ©bogage ou de journaux sur la sortie standard du protocole.
- Utilisez un
SessionServicedurable lorsque la reprise doit survivre au redémarrage du processus. - Définissez une limite de session finie et fermez les sessions inactives.
Le crate acp_server exĂ©cutable inclut un agent basĂ© sur Gemini, des outils de lecture limitĂ©s Ă lâespace de travail, la journalisation de suivi vers la sortie dâerreur et la configuration du processus de lâĂ©diteur.