Crear un cliente o host de ACP
Usa la modalidad de cliente cuando una aplicación ADK-Rust necesite delegar el trabajo de programación a un proceso externo de ACP. La aplicación sigue siendo el host: gestiona la selección del proyecto, la experiencia del usuario, las reglas de aprobación y cualquier servicio local ofrecido al agente de programación.
Instalación
[dependencies]
adk-acp = "2.1.0"
El conjunto de características predeterminado es la implementación del cliente. La característica server se
necesita únicamente al exponer un agente ADK-Rust.
Elegir la configuración del cliente
| Forma del producto | API |
|---|---|
| Una tarea aislada con un proceso nuevo | prompt_agent_with_policy |
| Una tarea aislada con contenido que no es texto (imagen, audio, recurso) | prompt_agent_content_with_policy |
| Un especialista en programación disponible para un agente LLM | AcpAgentTool |
| Varios especialistas en programación con nombre | AcpToolset |
| Una conversación continua sobre un proyecto | AcpSession |
| Progreso del texto y las herramientas mostrado mientras se ejecuta el turno | stream_prompt |
Solicitud de una sola ejecución
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 es la opción predeterminada porque un agente de programación iniciado puede solicitar operaciones con efectos secundarios reales. Usa AutoApprove únicamente dentro de un flujo de trabajo local de confianza.
Enviar contenido enriquecido en la solicitud
prompt_agent_content_with_policy transmite un valor adk_core::Content completo —
no solo una cadena —, de modo que una solicitud pueda transportar contenido que no sea texto. Las partes de recursos incrustados, imágenes y audio se asignan al bloque de contenido ACP correspondiente mediante el módulo de contenido compartido, en lugar de descartarse; el texto siempre se conserva. Las partes que no tienen una representación ACP transmisible se omiten, y se rechaza una solicitud que no se asigne a ningún bloque.
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?;
Delegar desde un agente 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()?;
Cada llamada a AcpAgentTool inicia un proceso y una sesión nuevos. Elige esta estructura cuando la tarea delegada sea autónoma y el coordinador solo necesite el texto final como resultado de su herramienta.
Sesiones persistentes y cancelación
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?;
El controlador de cancelación envía la notificación oficial de session/cancel. La solicitud debe permanecer esperada hasta que llegue el motivo de detención por cancelación; esto permite que la misma sesión acepte otra solicitud sin una respuesta obsoleta en su cola.
Transmitir un turno a una interfaz de usuario
stream_prompt produce valores OutputChunk para el texto del agente, los pensamientos, los inicios de herramientas, las decisiones de permisos, la finalización y los errores. Además de estos, expone dos vistas más detalladas del turno de un External_Agent:
OutputChunk::ToolUpdate— elToolCallUpdatede External_Agent, correlacionado medianteidde llamada a herramienta, que contiene el estado informado, el tipo, el título actualizado, el texto de contenido extraído y las ubicaciones de los archivos afectados. Esto permite que una interfaz de usuario muestre el progreso de las herramientas, las diferencias y las listas de archivos afectados, en lugar de mostrar únicamente el texto final.OutputChunk::Usage— elUsageUpdatede External_Agent, que contiene los tokensusedysizede la ventana de contexto, además de los valores acumulados decostycurrencycuando el agente los informa, para que una interfaz de usuario pueda mostrar el consumo de la ventana de contexto.
El texto de los mensajes del agente se muestra exactamente como antes, por lo que una interfaz de usuario que solo lea fragmentos de texto no se verá afectada. La aplicación puede ocultar los fragmentos de pensamiento, mostrar la actividad de las herramientas por separado y exponer el StatusTracker compartido en su interfaz.
Consulta el crate ejecutable acp_client_host para ver
el ciclo completo.
Permitir que el agente solicite archivos
Implementa AcpFileSystem y asígnalo con AcpAgentConfig::filesystem. Las capacidades de lectura
y escritura se anuncian de forma independiente mediante supports_read
y supports_write.
La devolución de llamada recibe rutas absolutas. Un host de producción debería:
- canonicalizar el espacio de trabajo aprobado y la ruta solicitada;
- rechazar las rutas fuera de las raíces aprobadas, incluidos los escapes mediante enlaces simbólicos;
- decidir si los búferes del editor no guardados tienen prioridad sobre el contenido del disco;
- aplicar límites de tamaño de archivo y de rangos de líneas;
- anunciar las escrituras únicamente cuando la aplicación las implemente y autorice.
El directorio de trabajo es contexto, no un entorno aislado. La validación del sistema de archivos y un límite de proceso del sistema operativo resuelven problemas diferentes.
Permitir que el agente ejecute comandos
Implementa AcpTerminal y asígnalo con AcpAgentConfig::terminal. ACP
anuncia la terminal como una capacidad, por lo que el host debe implementar el ciclo de vida completo de creación, salida, espera, terminación y liberación.
El anfitrión elige las listas de comandos permitidos, las reglas del directorio de trabajo, las variables de entorno, los límites de salida, el aislamiento de procesos y el comportamiento de limpieza. Las devoluciones de llamada de la terminal se ejecutan fuera del bucle de despacho de JSON-RPC, por lo que una espera prolongada no congela el tráfico de permisos ni de cancelación.
Proporcione un servidor MCP a la sesión
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 versión 1 estable de ACP requiere que los agentes acepten la configuración
stdio de MCP. Las entradas de HTTP y SSE solo se envían cuando el agente
externo anuncia esos transportes opcionales. La salida de depuración de
AcpAgentConfig muestra los nombres y las claves de entorno sin imprimir los valores
secretos.
Políticas de permisos
Cada solicitud de permiso incluye el ID de sesión, el ID exacto de la llamada a la herramienta, el tipo de herramienta, la entrada sin procesar y todas las opciones ofrecidas por el agente. Los ID de las opciones son opacos. ADK-Rust coincide con la semántica de permitir y rechazar, y luego devuelve el ID original; una selección inventada se convierte en una cancelación.
PermissionPolicy::async_custom puede esperar a un diálogo de escritorio, una interfaz web de aprobación
o un servicio de políticas de la organización. Mantenga el bucle de despacho
receptivo esperando la interacción humana mediante este API en lugar de
bloquear un hilo.