Créer un client ou un hÎte ACP

Utilisez le mode client lorsqu’une application ADK-Rust doit dĂ©lĂ©guer du travail de programmation Ă  un processus ACP externe. L’application reste l’hĂŽte : elle gĂšre la sĂ©lection du projet, l’expĂ©rience utilisateur, les rĂšgles d’approbation et tous les services locaux proposĂ©s Ă  l’agent de programmation.

Installation

[dependencies]
adk-acp = "2.1.0"

L’ensemble de fonctionnalitĂ©s par dĂ©faut correspond Ă  l’implĂ©mentation client. La fonctionnalitĂ© server est nĂ©cessaire uniquement lors de l’exposition d’un agent ADK-Rust.

Choisir la forme du client

Forme du produitAPI
Une tùche isolée avec un nouveau processusprompt_agent_with_policy
Une tùche isolée avec du contenu non textuel (image, audio, ressource)prompt_agent_content_with_policy
Un spécialiste du codage disponible pour un agent LLMAcpAgentTool
Plusieurs spécialistes du codage nommésAcpToolset
Une conversation de projet continueAcpSession
Progression du texte et des outils affichĂ©e pendant l’exĂ©cution du tourstream_prompt

Invite en une seule requĂȘte

use adk_acp::{
    AcpAgentConfig, PermissionPolicy, prompt_agent_with_policy,
};
use std::sync::Arc;

let config = AcpAgentConfig::new("my-coding-agent --acp")
    .working_dir("/absolute/path/to/project");

let answer = prompt_agent_with_policy(
    &config,
    "Inspect the failing test and explain the cause.",
    Arc::new(PermissionPolicy::DenyAll),
).await?;

DenyAll est la valeur par dĂ©faut, car un agent de programmation lancĂ© peut demander des opĂ©rations ayant de vĂ©ritables effets secondaires. Utilisez AutoApprove uniquement dans le cadre d’un flux de travail local de confiance.

Envoyer un contenu de requĂȘte enrichi

prompt_agent_content_with_policy transmet une valeur adk_core::Content complĂšte — et pas seulement une chaĂźne — afin qu’une requĂȘte puisse transporter du contenu non textuel. Les parties intĂ©grĂ©es de ressource, d’image et d’audio sont mappĂ©es vers le bloc de contenu ACP correspondant par l’intermĂ©diaire du module de contenu partagĂ©, au lieu d’ĂȘtre supprimĂ©es ; le texte est toujours conservĂ©. Les parties qui ne possĂšdent aucune reprĂ©sentation ACP transmissible sont ignorĂ©es, et une requĂȘte qui ne correspond Ă  aucun bloc est rejetĂ©e.

use adk_acp::{AcpAgentConfig, PermissionPolicy};
use adk_acp::connection::prompt_agent_content_with_policy;
use adk_core::{Content, Part};
use std::sync::Arc;

let mut content = Content::new("user");
content.parts.push(Part::Text { text: "What is in this image?".into() });
content.parts.push(Part::InlineData { mime_type: "image/png".into(), data: png_bytes });

let config = AcpAgentConfig::new("my-coding-agent --acp")
    .working_dir("/absolute/path/to/project");

let answer = prompt_agent_content_with_policy(
    &config,
    &content,
    Arc::new(PermissionPolicy::DenyAll),
).await?;

Déléguer depuis un agent ADK

use adk_acp::{AcpAgentTool, PermissionDecision, PermissionPolicy};
use adk_agent::LlmAgentBuilder;
use std::sync::Arc;

let policy = PermissionPolicy::Custom(Box::new(|request| {
    if request.title.to_ascii_lowercase().contains("delete") {
        PermissionDecision::deny()
    } else {
        PermissionDecision::allow_once()
    }
}));

let coding_agent = AcpAgentTool::new("my-coding-agent --acp")
    .name("repository_specialist")
    .description("Inspect and improve the current Rust repository")
    .working_dir("/absolute/path/to/project")
    .permission_policy(policy);

let coordinator = LlmAgentBuilder::new("coordinator")
    .model(model)
    .instruction("Delegate repository changes to repository_specialist.")
    .tool(Arc::new(coding_agent))
    .build()?;

Chaque appel Ă  AcpAgentTool dĂ©marre un nouveau processus et une nouvelle session. Choisissez cette structure lorsque la tĂąche dĂ©lĂ©guĂ©e est autonome et que le coordinateur n’a besoin que du texte final comme rĂ©sultat de son outil.

Sessions persistantes et annulation

use adk_acp::{AcpAgentConfig, AcpSession, PermissionPolicy};
use std::sync::Arc;

let config = AcpAgentConfig::new("my-coding-agent --acp")
    .working_dir("/absolute/path/to/project");
let mut session = AcpSession::start(
    config,
    Arc::new(PermissionPolicy::DenyAll),
).await?;

let first = session.prompt("Map the error-handling modules.").await?;
let second = session.prompt("Now inspect the most central one.").await?;

let cancel = session.cancellation_handle()?;
// Move `cancel` into a stop-button, timeout, or shutdown task while another
// task awaits `session.prompt(...)`.

session.close().await?;

Le handle d’annulation envoie la notification officielle session/cancel. La requĂȘte doit rester en attente jusqu’à l’arrivĂ©e de la raison d’arrĂȘt indiquant l’annulation ; cela permet Ă  la mĂȘme session d’accepter une autre requĂȘte sans rĂ©ponse obsolĂšte dans sa file d’attente.

Diffuser un tour dans une interface utilisateur

stream_prompt produit des valeurs OutputChunk pour le texte de l’agent, ses rĂ©flexions, les dĂ©marrages d’outils, les dĂ©cisions d’autorisation, l’achĂšvement et les erreurs. En plus de ces Ă©lĂ©ments, il expose deux vues plus riches du tour d’un External_Agent :

  • OutputChunk::ToolUpdate — le ToolCallUpdate de External_Agent, corrĂ©lĂ© par id d’appel d’outil, contenant l’état signalĂ©, le type, le titre mis Ă  jour, le texte de contenu extrait et les emplacements de fichiers concernĂ©s. Cela permet Ă  une interface d’afficher la progression de l’outil, les diffĂ©rences et les listes de fichiers concernĂ©s, plutĂŽt que seulement le texte final.
  • OutputChunk::Usage — le UsageUpdate de External_Agent, contenant les jetons used et la size de la fenĂȘtre de contexte, ainsi que les cost et currency cumulĂ©s lorsque l’agent les signale, afin qu’une interface puisse afficher la consommation de la fenĂȘtre de contexte.

Le texte des messages de l’agent est exposĂ© exactement comme auparavant ; ainsi, une interface qui ne lit que les fragments de texte n’est pas affectĂ©e. L’application peut masquer les fragments de rĂ©flexion, afficher sĂ©parĂ©ment l’activitĂ© des outils et exposer le StatusTracker partagĂ© dans son interface.

Consultez le crate exécutable acp_client_host pour la boucle complÚte.

Laisser l’agent demander des fichiers

ImplĂ©mentez AcpFileSystem et associez-le avec AcpAgentConfig::filesystem. Les capacitĂ©s de lecture et d’écriture sont annoncĂ©es indĂ©pendamment par supports_read et supports_write.

Le callback reçoit des chemins absolus. Un hÎte de production doit :

  1. canonicaliser l’espace de travail approuvĂ© et le chemin demandĂ© ;
  2. rejeter les chemins situés en dehors des racines approuvées, y compris les échappements via des liens symboliques ;
  3. dĂ©terminer si les tampons d’éditeur non enregistrĂ©s remplacent le contenu du disque ;
  4. appliquer des limites de taille de fichier et de plage de lignes ;
  5. n’annoncer les Ă©critures que lorsque l’application les implĂ©mente et les autorise.

Le rĂ©pertoire de travail fournit un contexte, ce n’est pas une sandbox. La validation du systĂšme de fichiers et une frontiĂšre de processus du systĂšme d’exploitation rĂ©solvent des problĂšmes diffĂ©rents.

Laisser l’agent exĂ©cuter des commandes

ImplĂ©mentez AcpTerminal et associez-le avec AcpAgentConfig::terminal. ACP annonce le terminal comme une seule capacitĂ© ; l’hĂŽte doit donc implĂ©menter l’intĂ©gralitĂ© du cycle de vie : crĂ©ation, sortie, attente, arrĂȘt et libĂ©ration.

L’hĂŽte choisit les listes d’autorisation des commandes, les rĂšgles de rĂ©pertoire de travail, les variables d’environnement, les limites de sortie, l’isolation des processus et le comportement de nettoyage. Les rappels du terminal s’exĂ©cutent en dehors de la boucle de distribution JSON-RPC afin qu’une longue attente ne bloque pas le trafic d’autorisation ou d’annulation.

Fournir un serveur MCP Ă  la session

use adk_acp::AcpAgentConfig;
use adk_acp::agent_client_protocol::schema::v1::{
    McpServer, McpServerStdio,
};

let tools = McpServer::Stdio(
    McpServerStdio::new("project-tools", "/absolute/path/to/mcp-server")
        .args(vec!["--read-only".into()]),
);

let config = AcpAgentConfig::new("my-coding-agent --acp")
    .working_dir("/absolute/path/to/project")
    .mcp_server(tools);

La version stable ACP v1 exige que les agents acceptent la configuration stdio MCP. Les entrĂ©es HTTP et SSE ne sont envoyĂ©es que lorsque l’agent externe annonce la prise en charge de ces transports facultatifs. La sortie de dĂ©bogage AcpAgentConfig rĂ©pertorie les noms et les clĂ©s d’environnement sans afficher les valeurs secrĂštes.

Politiques d’autorisation

Chaque demande d’autorisation inclut l’ID de session, l’ID exact de l’appel d’outil, le type d’outil, l’entrĂ©e brute et toutes les options proposĂ©es par l’agent. Les ID d’options sont opaques. ADK-Rust applique la sĂ©mantique d’autorisation et de rejet, puis renvoie l’ID d’origine ; une sĂ©lection fabriquĂ©e devient une annulation.

PermissionPolicy::async_custom peut attendre une boĂźte de dialogue sur le bureau, une interface d’approbation web ou un service de politiques de l’organisation. Maintenez la boucle de distribution rĂ©active en attendant l’interaction humaine via ce API au lieu de bloquer un thread.

Suivant

Créer un client ou un hÎte ACP - Documentation ADK-Rust | ADK-Rust