Puente DCP-AI ↔ protocolo A2A (Agent-to-Agent)¶
Traducción informativa de la versión en inglés, actualizada el 26/10/2026. Si difieren, prevalece la versión en inglés. Los identificadores, comandos y bloques de código se conservan sin traducir.
Lleva el Agent Passport firmado de DCP dentro de la Agent Card de A2A, para que un consumidor de A2A pueda verificar sin conexión el hash y la autofirma del pasaporte antes de delegar una tarea. El pasaporte nombra a un principal responsable; este puente no verifica el RPR de ese principal ni establece la admisión. También asigna las tareas de A2A a intenciones y entradas de auditoría de DCP.
Instalación¶
Publicado en npm (26/10/2026). @dcp-ai/google-a2a 2.1.0 es latest y depende de @dcp-ai/sdk ^2.2.0. Las funciones descritas abajo están disponibles en npm.
verifyAgentCardPassport usa auxiliares de firma compuesta, no el verificador completo verifySignedBundleV2; no establece confianza en el principal ni admisión.
Consulta el inventario de publicaciones npm para ver todas las versiones.
Para desarrollar con una copia del repositorio, compila e instala el paquete local:
git clone https://github.com/dcp-ai-protocol/dcp-ai.git
cd dcp-ai/integrations/google-a2a
npm ci && npm run build
# then, in your project:
npm install /path/to/dcp-ai/integrations/google-a2a
El pasaporte dentro de la Agent Card¶
A2A permite que una Agent Card declare extensiones en capabilities.extensions (AgentExtension: uri,
description, required, params). La extensión del pasaporte de DCP, con URI
https://dcp-ai.org/a2a/extensions/passport/v2, lleva el SignedPayload<AgentPassportV2> (DCP-01) del agente en
params.passport: el pasaporte que el agente firmó con las claves Ed25519 + ML-DSA-65 que enumera, con su
principal_binding_reference al Responsible Principal Record. Nada nuevo en el formato de transmisión.
// Fragment: signedPassport is your agent's SignedPayload<AgentPassportV2>
import { passportToAgentCard, verifyAgentCardPassport, agentCardToPassport } from '@dcp-ai/google-a2a';
// Publisher: the signed passport (as produced by the DCP SDK or @dcp-ai/openclaw) goes into the card.
const card = passportToAgentCard(signedPassport, 'https://my-agent.example.com/a2a');
// Consumer: check passport consistency; trust and endpoint possession require the steps below.
const check = await verifyAgentCardPassport(card);
if (!check.verified) throw new Error(check.errors.join('; '));
check.passport.agent_id; // the verified DCP agent
Qué prueba la verificación y qué no¶
verifyAgentCardPassport comprueba que la extensión está presente, que el payload_hash coincide, que la firma
compuesta es pq_over_classical (Ed25519 más ML-DSA-65 o SLH-DSA-192f, cada hueco fijado a su algoritmo) y se verifica
en el contexto AgentPassport con claves que el propio pasaporte enumera (activas, no caducadas, cada kid el hash de su
clave pública), que las marcas de tiempo siguen un patrón RFC 3339 y se interpretan con Date.parse (no es una comprobación completa del calendario: algunas fechas imposibles, como el 30 de febrero, se normalizan y pasan), que el pasaporte está active, y que metadata.dcp_agent_id y
expectedAgentId, si se dan, nombran al mismo agente. Una tarjeta que no supera alguna de estas comprobaciones
enumeradas se rechaza; no es una validación completa del pasaporte contra el JSON Schema, así que los campos que quedan
fuera de estas comprobaciones no se validan.
Un pasaporte es público, y cualquiera puede copiarlo en su propia tarjeta. Así que un resultado verified por sí solo
prueba que el pasaporte es coherente consigo mismo: firmado por las claves que enumera. No prueba que quien sirve
la tarjeta tenga esas claves, ni que url, name, provider o skills pertenezcan al agente del pasaporte. Para
convertirlo en una comprobación de identidad:
- Pasa
trustedKeys: las claves en las que ya confías para ese agente (de un registro, de un pasaporte anterior fijado, o de lasbinding_keysde un RPR cuyo principal anclas fuera del bundle, cuando el principal firma por el agente; una firma válida sobre un RPR no lo hace, por sí sola, de confianza) yexpectedAgentId. Las dos claves firmantes deben estar entre ellas, y las propias entradas de confianza deben estaractivey no caducadas (tu registro de una clave prevalece sobre la copia del pasaporte); el resultado dice entoncesanchored: true.anchoredsolo indica que se pasótrustedKeys, incluso cuando la verificación falla: para una comprobación anclada, exigeverified && anchored. - Usa solo
result.passport, nunca los campos sin firmar de la tarjeta, como identidad del agente. - Antes de delegar una tarea, exige al endpoint una prueba de posesión:
generateRegistrationPoP/verifyRegistrationPoPdel SDK, o una sesión A2A de DCP-04.verifyRegistrationPoPsolo comprueba la firma sobre el reto que recibe: tu propio protocolo debe emitir un nonce fresco e impredecible desde el verificador, imponer su caducidad y su uso único, y vincularlo al kid, al agente y al endpoint. No confíes en una PoP que el endpoint envíe por su cuenta o reutilice. ElAgentCard.signaturesde A2A 1.0 (JWS sobre la tarjeta) es la forma propia del protocolo de vincular el resto de la tarjeta; este puente no lo implementa.
attachPassportToAgentCard(card, signedPassport) añade la extensión a una tarjeta que ya tienes (sustituyendo un
pasaporte de DCP anterior), agentCardPassport(card) la lee, y agentCardToPassport(card) devuelve el pasaporte que
lleva, en lugar de un esqueleto, cuando la tarjeta tiene uno.
Especificaciones de DCP admitidas¶
De DCP-01 a DCP-09, como correspondencias parciales (las funciones de abajo); no es una implementación completa de esas especificaciones.
Descripción general¶
El protocolo A2A de Google define un estándar para el descubrimiento y la comunicación entre agentes. Este puente asigna los conceptos de identidad y auditoría de DCP a primitivas de A2A:
- Agent Passports ↔ Agent Cards — lleva pasaportes de DCP en Agent Cards de A2A descubribles, con los límites de confianza y de prueba de posesión de arriba.
- Tareas A2A → intenciones de DCP — convierte las peticiones de tareas A2A entrantes en intenciones de DCP para la evaluación de la política y el registro de auditoría.
- Envoltura de auditoría — adjunta entradas de auditoría de DCP a las ejecuciones de tareas A2A para la trazabilidad.
Funciones¶
| Función | Sentido | Descripción |
|---|---|---|
passportToAgentCard(passport, endpoint) |
DCP → A2A | Convierte un Agent Passport (firmado o simple) en una Agent Card de A2A; uno firmado va en la extensión de DCP |
attachPassportToAgentCard(card, signedPassport) |
DCP → A2A | Pone un pasaporte firmado en capabilities.extensions de una tarjeta existente |
agentCardPassport(card) |
A2A → DCP | El pasaporte firmado que lleva una tarjeta, si lo hay |
verifyAgentCardPassport(card, options?) |
A2A → DCP | Verifica sin conexión el pasaporte que lleva |
agentCardToPassport(card) |
A2A → DCP | El pasaporte que lleva, o un esqueleto para una tarjeta sin él |
wrapA2ATaskWithAudit(task, agentId, intentId) |
A2A + DCP | Envuelve una tarea con una entrada de auditoría de DCP |
a2aTaskToIntent(task, agentId) |
A2A → DCP | Convierte una petición de tarea en una intención de DCP |
addMandateToA2AHandshake(handshake, mandate) |
DCP → A2A | Inyecta un mandato de DCP-09 en el handshake de A2A |
createLifecycleNotification(agentId, event, details) |
DCP → A2A | Crea una notificación de A2A para los eventos de ciclo de vida (DCP-05) |
Metadatos de la Agent Card¶
Los metadatos de DCP se incrustan en el campo metadata de la Agent Card:
{
"dcp_agent_id": "agent:uuid",
"dcp_version": "2.0",
"dcp_security_tier": "standard",
"dcp_owner_rpr_hash": "sha256:...",
"dcp_lifecycle_state": "active",
"dcp_mandate_id": null
}
Estos campos son datos de la tarjeta sin firmar: dcp_security_tier siempre es "standard" (no se calcula), y dcp_owner_rpr_hash contiene el owner_rpr_hash del pasaporte o, para un pasaporte V2, su principal_binding_reference (el human_id del RPR, no un hash). Ayudan al descubrimiento; la identidad solo procede del pasaporte verificado (result.passport).
Uso¶
// Fragment: myPassport and incomingTask come from your application
import { passportToAgentCard, a2aTaskToIntent } from '@dcp-ai/google-a2a';
// Publish a DCP agent as an A2A Agent Card
const card = passportToAgentCard(myPassport, 'https://my-agent.example.com/a2a');
// Convert an incoming A2A task to a DCP Intent
const intent = a2aTaskToIntent(incomingTask, 'agent:my-agent-id');
Notas¶
- El
authentication.schemesde la Agent Card se fija en['dcp-bundle']para señalar que este agente usa la autenticación basada en bundles de DCP. - Las skills del pasaporte se derivan de las capacidades de DCP, con los guiones bajos sustituidos por espacios para obtener nombres legibles.
- Las conversiones a esqueleto (A2A → DCP) de una tarjeta sin la extensión de DCP producen registros parciales que necesitan generación de claves y firma antes de usarse.
- Los campos de la tarjeta que escribe este puente (
authentication,metadata, …) son anteriores a A2A 1.0, cuya tarjeta usasupportedInterfacesysecuritySchemes;capabilities.extensionses válido en ambos. Alinear el resto de la tarjeta con A2A 1.0 es un cambio aparte.