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 produit | API |
|---|---|
| Une tâche isolée avec un nouveau processus | prompt_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 LLM | AcpAgentTool |
| Plusieurs spécialistes du codage nommés | AcpToolset |
| Une conversation de projet continue | AcpSession |
| Progression du texte et des outils affichée pendant l’exécution du tour | stream_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— leToolCallUpdatede External_Agent, corrélé paridd’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— leUsageUpdatede External_Agent, contenant les jetonsusedet lasizede la fenêtre de contexte, ainsi que lescostetcurrencycumulé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 :
- canonicaliser l’espace de travail approuvé et le chemin demandé ;
- rejeter les chemins situés en dehors des racines approuvées, y compris les échappements via des liens symboliques ;
- déterminer si les tampons d’éditeur non enregistrés remplacent le contenu du disque ;
- appliquer des limites de taille de fichier et de plage de lignes ;
- 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.