Cortex

Documentación técnica

Identidad agéntica · Especificación

Identidad Agéntica Verificable

Documentación técnica del DNI digital de nuestros agentes de IA: cómo se declara un agente, cómo se firma su autorización, cómo se publica, cómo se comprueba y cómo se retira. El registro y las credenciales públicas pueden consultarse sin cuenta. Las funciones operativas y la hoja de ruta se distinguen de las evidencias públicas.

Emisor

did:web:digitalcortex.tech

Formato

W3C VC 2.0 · vc+jwt · ES256

Revocación

Bitstring Status List v1.0

Vigencia

90 días por defecto

01

Qué es la Identidad Agéntica Verificable

Un agente de IA que escribe correos, prepara informes o contacta con clientes no puede ser anónimo. La IAV es el documento de identidad de ese agente: un fichero firmado criptográficamente que dice quién es, quién responde por él, qué puede hacer y qué no, y que cualquiera puede comprobar en el momento sin pedirnos permiso.

Llamamos Identidad Agéntica Verificable (IAV) —o, en lenguaje llano, DNI digital para agentes de IA— al conjunto formado por una credencial firmada, un identificador descentralizado publicado en este dominio, una lista de revocación firmada, un registro público y una página de verificación. El Sello CORTEX es su representación visual: un SVG generado a partir de la propia credencial, no un logotipo.

El emisor es Cosmolabs OÜ (Tallinn, Estonia, registro 17106582), que opera la marca CORTEX y responde de los agentes que identifica. Contacto: legal@digitalcortex.tech.

La política pública que rige la emisión está en /identidad-agentica y es la URL que las propias credenciales llevan dentro, en termsOfUse.id. Un ejemplo vivo: /verify/argos. Para una explicación divulgativa, sin código, está nextai.pro/dni-digital-agentes-ia.

Problema

Atribución

Quien recibe un mensaje de un agente no sabe de quién es el agente ni a quién reclamar. La credencial nombra a la sociedad responsable y su canal de contacto.

Problema

Alcance

Un agente puede decir que está autorizado a cualquier cosa. La credencial lista lo permitido y lo expresamente prohibido, firmado por quien lo delega.

Problema

Integridad

La credencial se vincula al hash del manifiesto registrado. Cambios en sistemas externos al registro requieren comprobaciones adicionales; el hash no observa por sí solo la ejecución.

Problema

Retirada

Revocar actualiza una lista firmada. La consulta debe obtener su versión vigente y los conectores deben aplicar el resultado para retirar acceso efectivo.

02

Arquitectura en cuatro bloques

Cuatro piezas, cada una con un único trabajo. La clave privada vive en un módulo de gestión de claves (KMS) externo y nunca en el servidor web; todo lo demás es público a propósito.

01EmisorClave ES256 en KMSdid:web:digitalcortex.techCosmolabs OÜ02CredencialW3C VC 2.0JWS typ vc+jwtatada al manifestHash03Publicacióndid.json + registrostatus list firmadasello SVG04Verificación8 comprobacionespública, sin login/verify/<agente>LA CLAVE PRIVADA NUNCA SALE DEL KMS · TODO LO DEMÁS ES PÚBLICO Y COMPROBABLE POR CUALQUIERA
Emisión → credencial → publicación → verificación. Cada paso deja un artefacto público distinto.
BloqueQué haceDónde vive
Emisor en KMSCustodia la clave ES256 y firma. La clave privada no sale nunca del KMS; el backend de firma se registra en cada credencial (KMS_GCP, KMS_AWS o DEV_LOCAL para pruebas).KMS externo (GCP Cloud KMS o AWS KMS) + motor de emisión
Credencial W3C VC 2.0Construye la credencial y la firma como JWS compacto con typ vc+jwt, atándola al hash del manifiesto del agente y a un índice de la lista de revocación.Función de emisión, restringida al titular del sistema
PublicaciónSirve el documento DID del emisor y de cada agente, el registro público, la credencial vigente, la lista de estado firmada y el sello.digitalcortex.tech (ficheros estáticos + funciones públicas)
VerificaciónEjecuta las comprobaciones una por una y devuelve el detalle, en JSON y en una página pública. Sin login, sin clave de API./functions/credentialVerify y /verify/<agente>
Documento DID del emisor (extracto real)
{
  "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/jwk/v1"],
  "id": "did:web:digitalcortex.tech",
  "verificationMethod": [{
    "id": "did:web:digitalcortex.tech#Cf3q-SmjX9b0cdB3PbbvnnvVudiVXiPkt-9guZgAIGY",
    "type": "JsonWebKey",
    "controller": "did:web:digitalcortex.tech",
    "publicKeyJwk": { "kty": "EC", "crv": "P-256", "x": "SMkWL4v6…", "y": "7WzmL-2Z…",
                      "kid": "Cf3q-SmjX9b0cdB3PbbvnnvVudiVXiPkt-9guZgAIGY", "alg": "ES256", "use": "sig" }
  }],
  "assertionMethod": ["did:web:digitalcortex.tech#Cf3q-SmjX9b0cdB3PbbvnnvVudiVXiPkt-9guZgAIGY"],
  "service": [
    { "id": "did:web:digitalcortex.tech#status-list",    "type": "BitstringStatusList",
      "serviceEndpoint": "https://digitalcortex.tech/functions/statusList" },
    { "id": "did:web:digitalcortex.tech#agent-registry", "type": "AgentRegistry",
      "serviceEndpoint": "https://digitalcortex.tech/functions/agentRegistry" },
    { "id": "did:web:digitalcortex.tech#policy",         "type": "IssuerPolicy",
      "serviceEndpoint": "https://digitalcortex.tech/identidad-agentica" }
  ]
}

03

Estándares utilizados

Nada propietario en el formato. Si mañana desapareciéramos, la credencial seguiría siendo verificable con herramientas de terceros.

EstándarPara quéDetalle de implementación
W3C VC Data Model 2.0Estructura de la credencial@context: ["https://www.w3.org/ns/credentials/v2"], type: ["VerifiableCredential", "AgentDelegationCredential"], validFrom/validUntil, termsOfUse, credentialStatus.
VC-JOSE-COSECómo se aseguraJWS compacto con typ: "vc+jwt". El payload es la credencial completa, no un JWT con claims sueltos.
ES256FirmaECDSA sobre P-256 con SHA-256. Es el único algoritmo aceptado por el verificador.
W3C DID Core · did:webIdentificadoresEmisor: did:web:digitalcortex.tech. Agentes: did:web:digitalcortex.tech:agents:<slug>, con controller = el emisor (un agente no controla su propia identidad).
RFC 7638Identificador de claveEl kid es la huella JWK (SHA-256 del JSON canónico {crv,kty,x,y}, base64url). Así el kid no se puede falsear: se deriva de la propia clave.
W3C Bitstring Status List v1.0RevocaciónUn bit por credencial, GZIP, multibase base64url con prefijo u. La lista es a su vez una credencial firmada.
JSON-LDSemánticaLos contextos son los oficiales del W3C; no publicamos vocabulario propio.

04

Endpoints públicos

Todo lo necesario para verificar por tu cuenta, sin credenciales de acceso, con CORS abierto (Access-Control-Allow-Origin: *).

Método y rutaContent-TypeRespuesta (abreviada)
GET /.well-known/did.jsonapplication/jsonDocumento DID del emisor: verificationMethod (JWK ES256), assertionMethod y service (status-list, agent-registry, policy).
GET /agents/<slug>/did.jsonapplication/jsonDocumento DID del agente: controller = emisor y tres service (credential, seal, verify).
GET /.well-known/agents.jsonapplication/jsonInstantánea estática del registro; incluye el campo live apuntando al registro en vivo.
GET /functions/agentRegistryapplication/json (cache 120 s)
{ "issuer": { "did": "did:web:digitalcortex.tech", … },
  "updated": "2026-…", "count": 1,
  "agents": [ { "did": "…:agents:argos", "name": "Argos",
    "status": "active",
    "credential": { "id": "CRD-2026-0001", "expiresAt": "…" },
    "links": { "didDocument": …, "credential": …, "seal": …, "verify": … } } ] }
GET /functions/agentCredential?slug=application/vc+jwt (cache 300 s)El JWS compacto tal cual, en texto. Cabecera X-Credential con el identificador legible (p. ej. CRD-2026-0001). 404 si no hay credencial vigente.
GET /functions/credentialVerify?slug=application/json (cache 30 s)Resultado de las comprobaciones, una por una. Acepta ?did=, ?c=, ?skill= y POST { jwt }. Esquema completo en la sección 08.
GET /functions/statusListapplication/vc+jwt (cache 60 s)Lista de revocación vigente, firmada. Cabecera X-Status-List-Version. &format=json devuelve metadatos (versión, revoked_count, published_at, issuer_kid) en lugar del JWT.
GET /functions/agentSeal?slug=image/svg+xml (cache 60 s)El sello, regenerado en el momento desde la credencial. Cabeceras X-Credential y X-Credential-Status. &format=json devuelve metadatos; &c=CRD-… pide el sello de una credencial concreta.
Base: https://digitalcortex.tech. Las funciones son proxies delgados al motor de emisión; la clave privada no está en ninguno de estos servicios.
SituaciónHTTPCuerpo
Falta el parámetro obligatorio400{ "error": "Indica ?slug=" }
Agente no público o inexistente404{ "valid": false, "reason": "Agente desconocido para este emisor" }
Agente sin credencial vigente200 / 404El verificador responde 200 con valid: false y explica el estado; la credencial y el sello devuelven 404.
Fallo interno del verificador500{ "valid": false, "error": "VERIFIER_ERROR" }
Otros fallos internos500REGISTRY_ERROR, SEAL_ERROR, CREDENTIAL_ERROR, STATUS_LIST_ERROR.
Códigos y cuerpos de error observables en los endpoints públicos.

05

El manifiesto del agente

Antes de emitir nada hay que declarar qué es el agente. El manifiesto es la instantánea versionada de los campos declarados en el registro; la credencial no delega en «un agente llamado Argos», delega en una versión concreta de esa configuración.

El manifiesto se publica como una versión inmutable (append-only): cada publicación crea un registro nuevo con su número de versión, su changelog y su hash, y marca la anterior como sustituida. Sin manifiesto publicado y vigente, la emisión de credencial se rechaza con el código NO_MANIFEST — a propósito.

Campos del manifiesto

CampoTipo / valoresQué significa
nametextoNombre público del agente. Aparece en la credencial y en el sello.
slugtexto, [a-z0-9_-]+Identificador en URLs y en el DID. Se valida al emitir: un slug inválido para un DID bloquea la emisión.
roletextoFunción declarada, p. ej. «Lead NextAI».
missiontextoObjetivo permanente del agente, en una frase.
manifestotextoPrincipio operativo con el que se le juzga.
domain_scopelista de personal · cosmo_labs · soulbyte · nextaiDominios de la organización en los que opera. El primero se usa como domainCode de la credencial y determina la paleta del sello.
autonomy_maxA0 · A1 · A2 · A3 · A4 · A5Techo de autonomía. Ver la sección 06.
is_lead · is_overseer · is_independentbooleanosPosición del agente en la jerarquía operativa.
health_statushealthy · degraded · offlineEstado operativo declarado.
publicbooleanoSi el agente aparece en el registro público. Un agente no público no existe para el exterior: ni registro, ni credencial, ni sello.
current_version · manifest_hashtextoLos escribe la publicación del manifiesto; son el puntero a la versión vigente.
did · credential_status · active_credential_idtexto · none|active|expired|revoked · textoLos escribe la emisión o la revocación, no el autor del manifiesto.

El alcance (scope), el riesgo máximo sin aprobación, el límite de importe y el TTL no viven en el manifiesto: son parámetros de la emisión, y por eso pueden endurecerse sin tocar la configuración del agente.

Parámetros de la emisión

ParámetroValoresQué hace
scope_skillslista de skill_id, no vacíaLo que el agente está autorizado a hacer. Una lista vacía se rechaza: una credencial sin alcance no delega nada.
scope_prohibitedlista de skill_id o accionesLo expresamente prohibido. Solaparse con scope_skills se rechaza.
max_risk_without_approvalLOW · MEDIUM · HIGH (por defecto LOW)Riesgo máximo que puede ejecutar sin aprobación humana. Por encima, la comprobación de alcance devuelve REQUIRE_APPROVAL.
max_transaction_eurnúmero o nullLímite de importe. null significa que el agente no puede mover dinero.
ttl_daysnúmero, máximo 365 (por defecto 90)Vigencia de la credencial. Ver la sección 10.
publicbooleanoPublica o retira al agente del registro público.

Taxonomía de acciones

Las acciones se identifican con el skill_id del catálogo de skills del emisor, en notación dominio.verbo. No es una lista cerrada en el código: cada skill del catálogo declara su risk_level (LOW, MEDIUM, HIGH, PROHIBITED), su estado (DRAFT, ACTIVE, QUARANTINED, DEPRECATED), sus herramientas y conectores necesarios, si es idempotente y qué evidencia exige. Al emitir se avisa —sin bloquear— si una skill del alcance no existe o no está activa.

Las acciones documentadas hoy, tal y como aparecen en el alcance de referencia:

skill_idUso típico en una credencial
lead.researchPermitida: investigar una cuenta o un contacto a partir de fuentes públicas.
outreach.draftPermitida: redactar un borrador de mensaje, sin enviarlo.
outreach.sendProhibida: enviar comunicación externa en nombre de la organización.
payment.executeProhibida: ejecutar un pago.
contract.signProhibida: firmar o aceptar un contrato.

El manifestHash: cómo se calcula y qué lo invalida

El hash es SHA-256 en hexadecimal sobre una serialización JSON canónica del manifiesto: claves ordenadas alfabéticamente en todos los niveles de anidamiento, sin espacios, con los valores undefined descartados. Antes de calcularlo se retiran los campos volátiles del almacenamiento (id, created_date, updated_date, created_by, is_sample), que cambiarían el hash sin que cambiase el agente.

Serialización canónica (equivalente en JavaScript)
function canonical(v) {
  if (v === null || typeof v !== 'object') return JSON.stringify(v ?? null);
  if (Array.isArray(v)) return '[' + v.map(canonical).join(',') + ']';
  return '{' + Object.keys(v).sort()
    .filter(k => v[k] !== undefined)
    .map(k => JSON.stringify(k) + ':' + canonical(v[k])).join(',') + '}';
}
// manifest_hash = SHA-256(canonical(manifiesto)) en hexadecimal, 64 caracteres

La comprobación manifestBinding compara el hash firmado con el manifiesto registrado como vigente. Cambiar sus campos exige publicar una nueva versión y reemitir. Esta comprobación no inspecciona la configuración efectiva del sistema en ejecución: cambios externos en prompts, modelos, herramientas o permisos requieren controles adicionales. El alcance de la emisión se firma por separado y no forma parte de ese hash.

Ejemplo: el manifiesto de Argos

Instantánea del manifiesto (versión 1.0.0)
{
  "human_id": "AGT-2026-0004",
  "name": "Argos",
  "slug": "argos",
  "role": "Lead NextAI",
  "mission": "Conducir NextAI entregando valor medible a cada cliente.",
  "manifesto": "Vigilancia panorámica sobre cada compromiso con cliente.",
  "autonomy_max": "A4",
  "domain_scope": ["nextai"],
  "is_lead": true,
  "is_overseer": false,
  "is_independent": false,
  "health_status": "healthy",
  "public": true
}

// manifest_hash = SHA-256(canonical(…)) → 64 caracteres hexadecimales
// Se publica con { subject_type: "AGENT", version: "1.0.0", changelog: "Primera versión" }

La instantánea se toma del registro del agente antes de escribirle la nueva versión, de modo que el hash no dependa de sí mismo. Puedes comprobar el hash vigente de cualquier agente público en la respuesta del verificador, campo credential.manifestHash.

06

Niveles de autonomía A0–A5

La autonomía no es un adjetivo de marketing: es un techo declarado en el manifiesto, firmado en la credencial y pintado en el sello.

NivelNombreQué permite
A0ObservarLeer, buscar, recopilar, detectar y medir. No produce ningún cambio.
A1AnalizarClasificar, resumir, estimar y detectar riesgos.
A2PrepararCrear borradores, propuestas, opciones y planes, sin ejecutarlos.
A3Ejecutar internoCambios internos reversibles dentro de su dominio.
A4Ejecutar con aprobaciónAcción persistente o externa, siempre con una aprobación humana válida.
A5ProhibidoMover dinero de forma autónoma, borrar la auditoría o escalar privilegios. No es un nivel alcanzable: es la clase de acciones vedadas.

07

Anatomía de la credencial

Un JWS compacto de tres partes separadas por puntos. La segunda parte no es un JWT con claims sueltos: es la credencial W3C completa.

Cabecera protegida

Base64url del primer segmento, decodificado
{
  "alg": "ES256",
  "typ": "vc+jwt",
  "kid": "did:web:digitalcortex.tech#Cf3q-SmjX9b0cdB3PbbvnnvVudiVXiPkt-9guZgAIGY"
}

El kid apunta a un verificationMethod del documento DID del emisor; el fragmento tras # es la huella JWK de la propia clave (RFC 7638). El verificador exige typ = "vc+jwt" y un kid que contenga #, y rechaza cualquier otra combinación antes incluso de mirar la firma.

Payload: la credencial

Payload ilustrativo (campos abreviados; consultar la credencial pública para los valores vigentes)
{
  "@context": ["https://www.w3.org/ns/credentials/v2"],
  "id": "urn:uuid:8f1c9a52-…",
  "type": ["VerifiableCredential", "AgentDelegationCredential"],
  "issuer": {
    "id": "did:web:digitalcortex.tech",
    "name": "Cosmolabs OÜ",
    "registryCode": "17106582",
    "jurisdiction": "EE",
    "contact": "legal@digitalcortex.tech"
  },
  "validFrom":  "2026-09-10T09:00:00.000Z",
  "validUntil": "2026-12-09T09:00:00.000Z",
  "termsOfUse": [{
    "type": "IssuerPolicy",
    "id": "https://digitalcortex.tech/identidad-agentica",
    "policy": "Esta credencial acredita únicamente que el emisor autoriza al agente identificado a operar dentro
               del alcance declarado, mientras esté vigente y no revocada. … Su validez debe comprobarse en tiempo
               real en la URL de verificación incluida en la propia credencial. El sello visual derivado puede
               reproducirse íntegro y sin alteraciones con fines informativos."
  }],
  "credentialStatus": {
    "id": "https://digitalcortex.tech/functions/statusList#48213",
    "type": "BitstringStatusListEntry",
    "statusPurpose": "revocation",
    "statusListIndex": "48213",
    "statusListCredential": "https://digitalcortex.tech/functions/statusList"
  },
  "credentialSubject": {
    "id": "did:web:digitalcortex.tech:agents:argos",
    "type": "AIAgent",
    "name": "Argos",
    "slug": "argos",
    "role": "Lead NextAI",
    "domainCode": "nextai",
    "autonomyLevel": "A4",
    "manifestVersion": "1.0.0",
    "manifestHash": "…64 caracteres hexadecimales…",
    "scope": {
      "skills": ["lead.research", "outreach.draft"],
      "prohibited": ["outreach.send", "payment.execute", "contract.sign"],
      "maxRiskWithoutApproval": "LOW",
      "domains": ["nextai"],
      "maxTransactionEur": null
    },
    "principal": {
      "type": "Organization",
      "legalName": "Cosmolabs OÜ",
      "registryCode": "17106582",
      "jurisdiction": "EE",
      "address": "Ahtri tn 12, 15551 Tallinn, Estonia",
      "contact": "legal@digitalcortex.tech",
      "accountableRole": "Administrador"
    },
    "disclosure": {
      "statement": "Argos es un sistema de inteligencia artificial operado por Cosmolabs OÜ. No es una persona.
                    De sus acciones dentro del alcance autorizado responde Cosmolabs OÜ.",
      "regulation": "Reglamento (UE) 2024/1689 (AI Act), art. 50 — transparencia",
      "dataProtection": "Esta credencial y su sello no contienen datos personales de personas físicas.
                         Contacto: legal@digitalcortex.tech",
      "verifyUrl": "https://digitalcortex.tech/verify/argos",
      "policyUrl": "https://digitalcortex.tech/identidad-agentica"
    }
  }
}

// Firma (tercer segmento del JWS), abreviada: MEUCIQD…
CampoPapel
idIdentificador único de esta credencial concreta (urn:uuid). Se reemplaza en cada reemisión.
issuerDatos registrales públicos del emisor. Si existe LEI, se añade el campo lei.
validFrom / validUntilVentana de vigencia. La diferencia es el TTL de emisión.
termsOfUseCondiciones bajo las que el emisor publica la credencial, incluida la URL de la política (VC 2.0 §5.2).
credentialStatusEntrada en la lista de revocación: índice del bit y URL canónica de la lista firmada.
credentialSubject.scopeLo permitido, lo prohibido, el riesgo máximo y el límite de importe.
credentialSubject.principalQuién responde: la sociedad, sus datos registrales y el rol responsable. Nunca una persona física.
credentialSubject.disclosureEl aviso de transparencia listo para copiar, con la referencia normativa y las URLs de verificación y política.

Minimización de datos

La credencial y el sello no contienen datos personales de personas físicas: ni de quien opera el agente, ni de terceros. La rendición de cuentas pública se expresa como organización + rol + canal de contacto (accountableRole), porque la persona concreta consta en el registro mercantil, no en un documento que va a circular. El verificador filtra además cualquier campo de persona responsable aunque una credencial antigua lo llevara dentro.

08

Verificación: las ocho comprobaciones

El verificador no devuelve un semáforo. Devuelve qué comprobó, en qué orden y con qué resultado, porque enseñar el trabajo es la mitad del valor.

Siete comprobaciones las ejecuta el verificador del emisor sobre la credencial; la octava la añade la página pública resolviendo el documento DID en este dominio. La cadena se detiene en la primera que falla: si la firma no es válida, no tiene sentido mirar la vigencia.

#ComprobaciónQué compruebaCuándo falla
1formatQue es un JWS compacto, con typ: "vc+jwt" y un kid que apunta a un verificationMethod (contiene #).«No es un JWS compacto válido», «typ esperado vc+jwt, recibido …» o «Falta kid o no apunta a un verificationMethod».
2keyDeclaredQue la clave que firmó es la que el emisor declara públicamente en assertionMethod de su documento DID.«La credencial la firma otro DID, no did:web:digitalcortex.tech» o «La clave … no es la declarada en el documento DID».
3signatureQue la firma ES256 es matemáticamente válida sobre cabecera y payload con esa clave pública.«Firma inválida». Cualquier byte alterado en la credencial cae aquí.
4issuerMatchQue el emisor declarado dentro de la credencial coincide con el que efectivamente la firmó.«La credencial declara emisor X pero la firmó Y».
5validityQue la fecha actual está entre validFrom y validUntil.«Aún no válida (desde …)» o «Caducada el …». Si pasa, el detalle indica cuántos días quedan.
6revocationQue existe lista de revocación publicada, que está firmada por la misma clave, que es la que la credencial referencia y que el bit de esta credencial está a 0.«No hay lista de revocación publicada», «La lista de revocación no está firmada por el emisor», «La lista publicada no es la que referencia la credencial» o «REVOCADA (índice N)».
7manifestBindingQue el hash del manifiesto que lleva dentro la credencial coincide con el del manifiesto que el emisor tiene registrado como vigente.«El agente fue modificado: la credencial autoriza un hash y el emisor tiene registrado como vigente otro».
8did_documentQue /.well-known/did.json está publicado en este dominio y declara exactamente la clave que firmó.«Documento no publicado todavía» o «El documento publicado no declara la clave que firmó».
Identificadores tal y como aparecen en el objeto checks de la respuesta JSON.

La API del verificador

Forma de llamadaQué verifica
GET ?slug=argosLa credencial vigente de ese agente público.
GET ?did=did:web:digitalcortex.tech:agents:argosLo mismo, identificando por DID.
GET …&c=CRD-2026-0001Además dice si esa credencial concreta (la que codifica el QR de un sello) sigue siendo la vigente.
GET …&skill=outreach.sendAñade la comprobación de alcance.
POST { jwt }Verifica cualquier credencial emitida por este emisor, la tengas de donde la tengas.
GET /functions/credentialVerify?slug=argos&c=CRD-2026-0001
{
  "valid": true,
  "checks": {
    "format":          { "ok": true, "detail": "JWS con typ=vc+jwt y kid presente" },
    "keyDeclared":     { "ok": true, "detail": "La clave está declarada en assertionMethod del emisor" },
    "signature":       { "ok": true, "detail": "Firma ES256 válida" },
    "issuerMatch":     { "ok": true, "detail": "Emitida por Cosmolabs OÜ (did:web:digitalcortex.tech)" },
    "validity":        { "ok": true, "detail": "En vigor, caduca en 83 días" },
    "revocation":      { "ok": true, "detail": "No revocada" },
    "manifestBinding": { "ok": true, "detail": "Manifiesto 1.0.0 (a91c4f22e8…3b7d) sin cambios" }
  },
  "credential": { "humanId": "CRD-2026-0001", "id": "urn:uuid:8f1c9a52-…",
                  "issuedAt": "…", "expiresAt": "…",
                  "manifestVersion": "1.0.0", "manifestHash": "…", "signingBackend": "KMS_GCP" },
  "reference":  { "requested": "CRD-2026-0001", "isCurrent": true },
  "didDocument": { "published": true, "matches": true,
                   "url": "https://digitalcortex.tech/.well-known/did.json" },
  "agent":      { "did": "did:web:digitalcortex.tech:agents:argos", "name": "Argos",
                  "slug": "argos", "role": "Lead NextAI", "domain": "nextai",
                  "autonomyLevel": "A4", "manifestVersion": "1.0.0",
                  "scope": { }, "disclosure": { } },
  "principal":  { "type": "Organization", "legalName": "Cosmolabs OÜ" },
  "termsOfUse": [ ],
  "issuer":     { "id": "did:web:digitalcortex.tech", "name": "Cosmolabs OÜ" },
  "validity":   { "from": "…", "until": "…" }
}

Cuando algo falla, valid es false, reason trae el motivo en texto legible y checks contiene solo las comprobaciones ejecutadas hasta la que falló, con esa última marcada ok: false. Si el sello escaneado apunta a una credencial que ya no es la vigente, reference.isCurrent es false y reference.note explica si fue revocada o sustituida y cuál es la vigente ahora.

EstadoQué significaDónde se ve
ACTIVECredencial vigente: firmada, en fecha y no revocada.Sello (X-Credential-Status), registro (status: active), verificador (valid: true).
EXPIREDPasó validUntil sin reemisión. El sello se apaga y muestra el banner CADUCADA.Sello y registro (status: expired).
REVOKEDEl emisor puso su bit a 1 en la lista de estado. El sello muestra REVOCADA.Sello, registro (status: revoked) y comprobación revocation.
SUPERSEDEDSustituida por una reemisión. Su bit también se pone a 1: una credencial sustituida que siguiera verificando sería un agujero.Registro (status: superseded) y reference.note del verificador.

Verificar por tu cuenta en tres pasos

No hace falta confiar en nuestra página. Con curl y jose en Node (v18 o superior, sin más dependencias) tienes la verificación completa en unas veinte líneas.

Pasos 1 y 2 — descargar la credencial y la clave pública del emisor
# 1 · la credencial vigente del agente (JWS compacto, typ vc+jwt)
curl -s "https://digitalcortex.tech/functions/agentCredential?slug=argos" -o argos.jwt

# 2 · el documento DID del emisor, con su clave pública
curl -s "https://digitalcortex.tech/.well-known/did.json" -o did.json
Paso 3 — verificar firma, vigencia y revocación (Node + jose)
import { readFileSync } from 'node:fs';
import { gunzipSync } from 'node:zlib';
import { importJWK, compactVerify, decodeProtectedHeader } from 'jose';

const jws = readFileSync('argos.jwt', 'utf8').trim();
const did = JSON.parse(readFileSync('did.json', 'utf8'));

// 1 · formato
const { alg, typ, kid } = decodeProtectedHeader(jws);
if (typ !== 'vc+jwt' || alg !== 'ES256') throw new Error('Formato inesperado');

// 2 · la clave está declarada por el emisor
const vm = did.verificationMethod.find((m) => m.id === kid);
if (!vm || !did.assertionMethod.includes(kid)) throw new Error('kid no declarado');
const key = await importJWK(vm.publicKeyJwk, 'ES256');

// 3 · firma — compactVerify lanza si no casa
const { payload } = await compactVerify(jws, key);
const vc = JSON.parse(new TextDecoder().decode(payload));

// 4 · emisor coherente   5 · vigencia
const now = new Date();
if (vc.issuer.id !== 'did:web:digitalcortex.tech') throw new Error('Emisor incoherente');
if (new Date(vc.validFrom) > now || new Date(vc.validUntil) < now) throw new Error('Fuera de vigencia');

// 6 · revocación — la lista va firmada por la MISMA clave
const res = await fetch(vc.credentialStatus.statusListCredential);
const { payload: lp } = await compactVerify(await res.text(), key);
const list = JSON.parse(new TextDecoder().decode(lp));
const bits = gunzipSync(Buffer.from(list.credentialSubject.encodedList.slice(1), 'base64url'));
const i = Number(vc.credentialStatus.statusListIndex);
if ((bits[i >> 3] & (128 >> (i % 8))) !== 0) throw new Error('REVOCADA');

console.log('OK', vc.credentialSubject.name, vc.credentialSubject.autonomyLevel, vc.validUntil);

Falta la séptima comprobación —que el manifiesto del agente no haya cambiado— porque solo el emisor conoce el hash del manifiesto que el emisor tiene registrado como vigente. Se obtiene del verificador, en credential.manifestHash. Es, a propósito, la única pieza que no puedes reproducir por tu cuenta.

Qué NO prueba una verificación

  • No acredita la calidad ni el resultado de ninguna tarea concreta que haya hecho el agente.
  • No sustituye al contrato ni a las condiciones del servicio que rijan entre las partes.
  • No convierte al agente en sujeto de derechos u obligaciones: de sus actuaciones dentro del alcance autorizado responde Cosmolabs OÜ conforme a la legislación aplicable.
  • No prueba que el mensaje que has recibido lo enviara ese agente: prueba que existe un agente identificado con ese alcance. Atribuir un mensaje concreto exige firmar también el mensaje, y eso no forma parte de esta credencial.
  • No es una auditoría externa ni la revisión de un tercero: es una declaración del emisor, verificable en su integridad y en su vigencia.
  • No vale una captura. El resultado es válido en el instante de la consulta. Un sello impreso o una pantalla guardada no acreditan nada: hay que volver a comprobar.

09

El sello: nada es decorativo

El sello es una lectura gráfica de la credencial, generada de forma determinista a partir de ella. Mismo agente y mismo manifiesto, mismo sello; cambia el manifiesto, cambia el sello.

El arte se siembra con manifestHash|did, para diferenciar visualmente las identidades y las versiones del manifiesto. Esa representación no garantiza unicidad visual ni autentica al portador de una copia. No se almacena en ninguna parte: se regenera idéntico en cada petición a partir de la credencial.

ElementoQué codifica
Anillo exterior de 256 marcasLos 256 bits del manifestHash, literalmente: marca larga y clara = 1, marca corta y tenue = 0.
Anillo interior de 128 marcasLa huella del DID del agente.
Nebulosa centralUn campo de flujo de cientos de líneas de corriente sembrado con el hash y el DID. Es la huella del hash hecha imagen.
Rombos claros en órbitaLas acciones permitidas (scope.skills), cada una etiquetada con su skill_id en radial.
Rombos rojos tachadosLas acciones expresamente prohibidas (scope.prohibited).
Barra de cinco segmentosEl nivel de autonomía, de A1 a A5. El quinto segmento se pinta en rojo: es la frontera de lo prohibido.
Sigilo hexagonal centralPolígonos derivados del hash, más la inicial del nombre del agente sobre el núcleo luminoso.
Anillos tipográficosArriba, DID e identificador de credencial. Abajo, fecha de caducidad, emisor, versión del manifiesto y prefijo de su hash.
Código QRLa URL de verificación de esa credencial concreta: /verify/<slug>?c=<CRD-…>. No es un enlace genérico.
AnimaciónSolo si la credencial está vigente. Revocada o caducada: estático, atenuado al 42 % y con banner REVOCADA o CADUCADA. Respeta prefers-reduced-motion.
PaletaLa determina el domainCode del agente (nextai, cosmo_labs, soulbyte, personal). Identifica el dominio, no adorna.

Formatos y cabeceras

PeticiónDevuelve
GET /functions/agentSeal?slug=argosimage/svg+xml; charset=utf-8 — el SVG completo, animado si la credencial está vigente.
GET /functions/agentSeal?slug=argos&c=CRD-2026-0001El sello de esa credencial concreta. Si ya no es la vigente, sale atenuado y con banner.
GET /functions/agentSeal?slug=argos&format=jsonMetadatos estructurados (compatibles con ERC-721 y con el fichero de registro ERC-8004): name, description, image, animation_url, external_url y attributes con rol, dominio, autonomía, número de acciones permitidas y prohibidas, riesgo máximo sin aprobación, estado, versión y hash del manifiesto, emisor y fecha de caducidad.
CabeceraValor
X-CredentialIdentificador legible de la credencial pintada, p. ej. CRD-2026-0001.
X-Credential-StatusACTIVE, EXPIRED o REVOKED. Es el estado real en el momento de servir.
Cache-Controlpublic, max-age=60 si está vigente; 300 si no lo está (una credencial revocada ya no va a cambiar).
Access-Control-Allow-Origin* — puedes incrustarlo desde cualquier dominio.

Condiciones de uso del sello

  • Puede reproducirse íntegro y sin alteraciones, con fines informativos.
  • Siempre acompañado de su QR o con la URL de verificación visible. Recortar o sustituir el QR está prohibido.
  • El sello que servimos se apaga solo cuando la credencial se revoca o caduca: nunca miente sobre el estado. Una copia antigua guardada como imagen no prueba nada.
  • Está prohibido presentar como vigente una identidad revocada o caducada, o hacer pasar por agente de CORTEX a un sistema que no lo sea. Avisos a legal@digitalcortex.tech.

10

Ciclo de vida y revocación

Una autorización sin fecha de caducidad y sin forma de retirarla no es una autorización: es una declaración de intenciones.

MomentoQué ocurre
EmisiónSolo el titular del sistema puede emitir. Exige manifiesto publicado y vigente (si no, NO_MANIFEST) y que el hash del agente coincida con el de esa versión (si no, MANIFEST_MISMATCH). Se asigna un índice aleatorio —nunca secuencial, para que el índice no filtre la fecha de emisión— en la lista de estado y se firma en el KMS.
RenovaciónEl TTL por defecto es de 90 días (configurable, máximo 365). Renovar es reemitir: nueva credencial, nuevo urn:uuid, nuevo índice y nuevas fechas.
Reemisión por cambio de manifiestoCambiar el manifiesto registrado cambia su hash y requiere actualizar la vinculación manifestBinding. Hay que publicar la nueva versión del manifiesto y reemitir.
SustituciónAl emitir, cualquier credencial anterior activa pasa a SUPERSEDED y su bit se pone a 1 en la lista. Solo hay una credencial vigente por agente.
RevocaciónExige un motivo —una revocación sin motivo no es auditable—, pone el bit a 1, firma y publica una versión nueva de la lista de estado, y marca al agente como credential_status: revoked.
CaducidadAl pasar validUntil sin reemisión, la comprobación validity falla y el estado pasa a EXPIRED. No requiere ninguna acción del emisor.

Cómo funciona la lista de revocación

Un bit por credencial, el más significativo primero dentro de cada byte, sobre una lista de 131.072 bits (16 KB). Se comprime con GZIP y se codifica en multibase base64url sin relleno, con prefijo u. La lista es a su vez una credencial firmada: si no lo fuera, cualquiera podría servir una lista vacía y «des-revocar» agentes.

Cada publicación crea una versión nueva y marca la anterior como sustituida; la vigente viaja en la cabecera X-Status-List-Version. La caché es de 60 segundos con revalidación en segundo plano: ese valor no es una garantía de propagación global ni de retirada efectiva de acceso. Los índices no se reutilizan jamás, aunque la credencial que los ocupaba haya caducado.

Qué ve un tercero tras una revocación

  • El verificador devuelve valid: false con la comprobación revocation en rojo y el detalle «REVOCADA (índice N)».
  • La página /verify/<agente> muestra «Credencial revocada» y el sello atenuado.
  • El sello servido desde este dominio deja de animarse, se atenúa y pinta el banner REVOCADA, con la cabecera X-Credential-Status: REVOKED.
  • El registro sigue listando al agente con status: "revoked" y su fecha de revocación: un registro que solo enseña lo vigente es un escaparate, no un registro.
  • La credencial en sí deja de servirse: /functions/agentCredential responde 404. Quien conserve una copia del JWT podrá seguir comprobando la firma, y precisamente por eso la consulta de la lista de revocación es obligatoria en cualquier verificación seria.

11

Integración para terceros y clientes

Si trabajas con un agente identificado por CORTEX, o si quieres identificar los tuyos con el mismo enfoque, esto es lo que necesitas.

Mostrar el sello en una web

El sello es un SVG servido con CORS abierto: basta una etiqueta img envuelta en un enlace a la página de verificación. No lo copies a tu servidor: si lo sirves desde el nuestro, se apaga solo cuando la credencial deja de estar vigente.

HTML
<a href="https://digitalcortex.tech/verify/argos"
   rel="noopener" target="_blank"
   title="Verificar la identidad de este agente de IA">
  <img src="https://digitalcortex.tech/functions/agentSeal?slug=argos"
       alt="Sello de identidad del agente de IA Argos, emitido por Cosmolabs OU"
       width="240" height="240" loading="lazy" />
</a>

Si necesitas saber el estado sin renderizar la imagen, una petición HEAD al mismo endpoint devuelve X-Credential-Status. Para integraciones programáticas, usa el verificador y lee valid y checks.

Firma de correo

En la firma de los correos que envía un agente, tres líneas bastan y son verificables: qué es, quién responde y dónde comprobarlo. El texto exacto del aviso ya viene dentro de la credencial, en credentialSubject.disclosure.statement, y la URL en disclosure.verifyUrl.

Bloque de firma
Argos · Agente de IA de Cosmolabs OU (CORTEX)
Sistema de inteligencia artificial. No es una persona.
Identidad verificable: https://digitalcortex.tech/verify/argos

Aviso de transparencia en el primer mensaje

El art. 50 del Reglamento (UE) 2024/1689 exige que quien interactúa con un sistema de IA lo sepa. La práctica que seguimos: el aviso aparece en el primer mensaje de cada conversación, en lenguaje claro, con el nombre de la sociedad responsable y un enlace donde comprobarlo. En canales con cabeceras propias, además, un encabezado legible por máquinas.

Primer mensaje (texto) y cabecera (HTTP / correo)
Hola, soy Argos, un sistema de inteligencia artificial operado por Cosmolabs OU.
No soy una persona. Puedes comprobar mi identidad, quien responde por mi y que
tengo permitido hacer en https://digitalcortex.tech/verify/argos

X-AI-Agent: did:web:digitalcortex.tech:agents:argos
X-AI-Agent-Verify: https://digitalcortex.tech/verify/argos

Comprobar un agente desde tu sistema

Quiero…Llamada
Saber si un agente está autorizado ahoraGET /functions/credentialVerify?slug=<slug>
Saber si puede hacer una acción concretaGET /functions/credentialVerify?slug=<slug>&skill=<skill_id>
Verificar una credencial que me han entregadoPOST /functions/credentialVerify con { jwt }
Listar todos los agentes públicos y su estadoGET /functions/agentRegistry
Comprobar revocaciones por mi cuentaGET /functions/statusList (y su versión en X-Status-List-Version)

Cachea con cabeza: el verificador se sirve con max-age=30 y la lista de estado con max-age=60. No caches un resultado de verificación más allá de eso, porque una revocación debe verse en menos de un minuto.

Emitir con el mismo enfoque

Nada de esto es propietario. Si quieres identificar tus propios agentes con los mismos estándares, necesitas cuatro cosas:

  1. Una clave de firma ES256 en un KMS (o en un HSM). La clave privada no debe estar nunca en el servidor web ni en un equipo personal.
  2. Un documento DID publicado en tu dominio: did:web:tudominio.tld → https://tudominio.tld/.well-known/did.json, con tu clave pública en verificationMethod y referenciada en assertionMethod. Para los agentes, con path: did:web:tudominio.tld:agents:<slug> → https://tudominio.tld/agents/<slug>/did.json, sin .well-known.
  3. Credenciales W3C VC 2.0 firmadas como JWS typ: vc+jwt, con credentialStatus apuntando a tu propia Bitstring Status List firmada.
  4. Un verificador público. Sin una URL donde un tercero compruebe en el momento, la credencial no sirve de nada.

Publicaremos la especificación completa de la credencial de delegación agéntica y del sello con licencia abierta. Mientras tanto, esta página documenta el formato con el detalle suficiente para reimplementarlo, y todos los artefactos de un agente real están accesibles para inspección. Si estás construyendo algo parecido y quieres que los formatos converjan, escribe a legal@digitalcortex.tech.

12

Anclaje en blockchain (hoja de ruta)

Nada de lo que sigue está desplegado hoy. Se documenta para que se vea hacia dónde va el diseño y, sobre todo, qué problema resolvería y cuál no.

Fase prevista 1 · Atestaciones EAS en Base

La idea: por cada emisión y cada revocación, escribir una atestación en el Ethereum Attestation Service desplegado en Base, con el hash del JWT de la credencial, el manifestHash, el DID del agente y las fechas. Una atestación cuesta céntimos y es pública.

Campo previstoContenido
credentialHashSHA-256 del JWS completo. No revela el contenido, permite probar identidad byte a byte.
manifestHashEl mismo hash que va dentro de la credencial.
agentDiddid:web:digitalcortex.tech:agents:<slug>
issuedAt / validUntilFechas de la ventana de vigencia.
revokedAtEn la atestación de revocación; también revoca la atestación original.

Fase prevista 2 · Anclaje diario del ledger

El registro de auditoría ya está encadenado por hash, pero la base de datos la controla el operador. Un sello diario de la cabeza de cada partición, firmado con una clave que vive fuera del sistema, convierte «reescribí el ledger» en algo detectable: el sello de ayer deja de casar. Llevar ese sello a una cadena pública añade una marca de tiempo que el operador tampoco controla. El proceso es idempotente: si la cabeza no ha cambiado desde el último sello, no se escribe otro.

Fase prevista 3 · Registro ERC-8004

ERC-8004 propone un registro de identidad de agentes on-chain donde cada agente tiene un identificador y una agentURI que apunta a un fichero de registro con sus metadatos. Encaja de forma natural: esa agentURI sería el documento DID del agente publicado en este dominio, y el fichero de registro, los metadatos que ya devuelve hoy /functions/agentSeal?slug=<slug>&format=json.

Fase prevista 4 · Novena comprobación: «Anclado en Base»

Cuando lo anterior esté desplegado, la página de verificación mostrará una comprobación más junto a las ocho actuales: que existe una atestación on-chain para esta credencial, que no ha sido revocada en la cadena y en qué bloque y fecha se escribió. Hasta entonces no aparecerá: una comprobación que no se ejecuta no se pinta.

Qué resolvería el anclaje y qué no

Resolvería: marca de tiempo independiente del operador (no repudio), prueba de que una credencial existía en una fecha aunque el emisor desapareciera, y un punto de consulta que no depende de que nuestro dominio siga en pie. Refuerza, en una palabra, la atribución, el alcance y el no repudio.

No resolvería nada sobre el comportamiento del agente: no hace que esté mejor alineado, ni que sus resultados sean correctos, ni que cumpla lo que promete. Poner un hash en una cadena pública no mejora a un agente; solo hace más difícil mentir después sobre lo que se autorizó y cuándo. Cualquiera que venda lo contrario está vendiendo otra cosa.

13

Estado del sistema

El registro público de agentes, leído en vivo al abrir esta página. Es el mismo JSON que sirve /functions/agentRegistry y el mismo que declara el documento DID del emisor como servicio AgentRegistry.

Cosmolabs OÜ · did:web:digitalcortex.tech

1 agente · actualizado 2026-10-22

AgenteDIDAutonomíaEstadoCredencialComprobar
ArgosLead NextAIdid:web:digitalcortex.tech:agents:argosA4VigenteCRD-2026-0001hasta 2026-12-07/verify/argos

Se listan también los agentes con credencial revocada, caducada o sustituida: un registro que solo enseña lo vigente es un escaparate, no un registro. Los agentes no públicos no aparecen aquí ni en ningún otro sitio — para el exterior, sencillamente no existen.

14

Preguntas frecuentes

¿Lo valida algún organismo oficial?

No. Es una declaración de Cosmolabs OÜ con medios públicos para comprobar su firma, integridad y vigencia. No es una certificación oficial, una auditoría externa ni una garantía de cumplimiento del artículo 50 del AI Act.

¿Qué pasa si cambia la configuración del agente?

La vinculación compara el hash de la credencial con el manifiesto registrado como vigente. Un cambio en ese registro requiere publicar una nueva versión y reemitir. El verificador no inspecciona por sí solo cambios externos en prompts, modelo, herramientas o permisos efectivos.

¿Puedo verificar sin usar vuestra página?

Sí. La credencial usa un JWS ES256 y una clave pública en un documento DID. Puedes comprobar la firma, el emisor, las fechas y la lista de revocación. La vinculación con el manifiesto depende además del registro que publica el emisor. La sección de verificación explica el procedimiento.

¿Cuánto tarda en verse una revocación?

Depende del punto de consulta, las cachés y el comportamiento del cliente. Una cabecera max-age=60 no garantiza una propagación global en 60 segundos. Retirar acceso efectivo exige que cada conector consulte el estado actualizado o que se cancelen sus sesiones y permisos.

¿La credencial contiene datos personales?

El diseño público usa organización, rol y canal de contacto, evitando identificar a personas físicas. No debe incluirse información personal ni datos de clientes en los campos públicos del manifiesto o la credencial.

¿Qué ocurre cuando se rota la clave de firma?

La rotación planificada publica la nueva clave y conserva la anterior durante la transición que requieran las credenciales vigentes. La duración depende de sus fechas, no de un plazo universal de 90 días. Si hay compromiso de clave, se necesita un procedimiento de incidente y revocación específico.

¿Puedo copiar el sello o la credencial?

Son públicos y se pueden reproducir para consulta conforme a la política. Copiar una firma válida no permite modificar el contenido sin invalidarla, pero tampoco autentica a quien presenta esa copia. Verifica el dominio, la vigencia y el contexto de la interacción.

¿Por qué el DID del emisor vive en digitalcortex.tech?

Porque did:web:digitalcortex.tech se resuelve a https://digitalcortex.tech/.well-known/did.json. Los identificadores de agentes añaden su ruta. Este mecanismo vincula el identificador al dominio del emisor.

¿Sirve para agentes de otros proveedores?

Los estándares permiten otros emisores. Las credenciales de este registro las emite Cosmolabs OÜ para los agentes de los que declara responder; no acreditan automáticamente agentes de terceros.

¿Hay token, NFT o blockchain?

El sistema público de referencia funciona fuera de cadena. EAS en Base y ERC-8004 se describen como hoja de ruta. Un futuro anclaje aportaría evidencia de publicación y estado según su diseño; no comprobaría por sí solo la veracidad de la declaración ni la conducta del agente.

¿A4 permite cualquier acción si un humano la aprueba?

No. A0–A5 es una escala interna de autonomía. El nivel máximo no amplía la lista de acciones autorizadas ni anula las prohibiciones firmadas. Los conectores deben aplicar esas restricciones antes de ejecutar.

¿Qué hago si sospecho de un agente que dice ser de CORTEX?

Consulta digitalcortex.tech/verify/<agente> y confirma el canal por una vía independiente. Un QR válido puede haber sido copiado. Si faltan datos, la verificación falla o la interacción resulta sospechosa, contacta con legal@digitalcortex.tech sin enviar claves ni información confidencial.

Responsable de la emisión: Cosmolabs OÜ · código de registro 17106582 · Ahtri tn 12, 15551 Tallinn, Estonia · legal@digitalcortex.tech