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