Verificación de identidad

Verifica quién está chateando firmando un JWT para tus usuarios con sesión iniciada. Agentkit verifica el token y vincula la conversación a un Contacto.

La verificación de identidad te permite indicarle a Agentkit quién está chateando. Tu backend firma un JWT de corta duración para el usuario con sesión iniciada, el widget le entrega ese token a Agentkit, y Agentkit lo verifica y vincula la conversación a un Contacto.

Es enriquecimiento y protección antisuplantación, nunca una puerta de acceso. Un token ausente, vencido o inválido simplemente significa que el visitante chatea de forma anónima: el chat nunca se bloquea.

Nota: los tokens de identidad transportan datos privados del usuario. Fírmalos siempre en tu servidor, nunca en JavaScript del lado del cliente; firmar en el navegador expondría tu clave secreta.

Cómo funciona

  1. Un usuario inicia sesión en tu app.
  2. Tu backend genera un JWT de corta duración, firmado con la clave de identidad de tu chatbot.
  3. Le entregas el token al widget (antes de que se cargue o en tiempo de ejecución).
  4. El widget envía el token con cada solicitud de chat.
  5. Agentkit verifica la firma y los claims, y luego crea o actualiza un Contacto identificado por el subject del token y vincula la conversación a él.

Habilitar la verificación

  1. Abre tu agente y ve a Configuración → Identidad.
  2. Activa Verificar visitantes con sesión iniciada (JWT).
  3. Copia la Clave de firma.

La clave de firma es exclusiva del servidor: guárdala en una variable de entorno y nunca la expongas en código del cliente. Regenerar la clave invalida de inmediato todos los tokens firmados con la anterior.

Especificación del token

Firma el token con el algoritmo HS256. Otros algoritmos (incluidos alg: none y las claves asimétricas) se rechazan.

Claims

ClaimObligatorioNotas
sub (o user_id)El id inmutable de usuario de tu app. Usa un id interno estable, nunca un correo electrónico, un nombre de usuario ni un id de Agentkit. Si sub y user_id están ambos presentes, deben coincidir.
expHora de expiración. Usa tokens de corta duración (~1 hora). Los tokens cuyo exp esté a más de 24 horas en el futuro se rechazan.
audRecomendadoVincula el token a este agente: agentkit:chatbot:{chatbotId}. Si está presente, debe coincidir.
emailNoSe guarda en el Contacto.
nameNoSe guarda en el Contacto.
phonenumberNoSe guarda en el campo phone del Contacto.
custom_attributesNoObjeto para cualquier dato adicional (plan, empresa, ids de Stripe, …).

Del token solo se leen email, name, phonenumber y custom_attributes. Cualquier otro claim de nivel superior se ignora; coloca los datos adicionales o de integración dentro de custom_attributes.

Límites

  • email, name, phonenumber: hasta 1024 caracteres cada uno.
  • custom_attributes: hasta 8192 bytes, 50 claves y 5 niveles de anidamiento.

Un token que infrinja estos límites se verifica como anónimo (el fallo queda registrado) en lugar de bloquear el chat.

Firmar el token

Cualquier biblioteca de JWT funciona (jsonwebtoken, PyJWT, …); solo necesitas un token HS256 con los claims anteriores. Este ejemplo usa jose, que también funciona en edge runtimes (Vercel Edge, Cloudflare Workers, Deno):

// On YOUR backend, mint a short-lived JWT for your logged-in user.
import { SignJWT } from 'jose';

const secret = new TextEncoder().encode(
  process.env.AGENTKIT_CHATBOT_IDENTITY_SECRET,
);

const token = await new SignJWT({
  // Optional private profile claims — stored on the Contact, never shown to the
  // bot. ONLY these keys are read: email, name, phonenumber, custom_attributes.
  // Put extra/integration data (Stripe ids, plan, company, …) in custom_attributes.
  email: user.email,
  name: user.name,
  phonenumber: user.phone, // maps to the Contact's "phone"
  custom_attributes: {
    plan: user.plan,
    stripe_id: user.stripeCustomerId,
  },
})
  .setProtectedHeader({ alg: 'HS256' })
  .setSubject(user.id) // immutable id from YOUR system (not email/username)
  .setIssuedAt()
  .setExpirationTime('1h') // short-lived; this is a browser bearer token
  .setAudience('agentkit:chatbot:YOUR_CHATBOT_ID')
  .sign(secret);

Este mismo snippet, precargado con el audience de tu agente, se muestra en la página Configuración → Identidad.

# Python example using PyJWT
import jwt, os, time

token = jwt.encode(
    {
        "sub": user.id,
        "email": user.email,
        "name": user.name,
        "phonenumber": user.phone,
        "custom_attributes": {"plan": user.plan},
        "aud": "agentkit:chatbot:YOUR_CHATBOT_ID",
        "iat": int(time.time()),
        "exp": int(time.time()) + 3600,
    },
    os.environ["AGENTKIT_CHATBOT_IDENTITY_SECRET"],
    algorithm="HS256",
)

Pasar el token al widget

Configura el token antes de que se cargue el script del widget (por ejemplo, inyéctalo en la página desde el servidor):

<script>
  window.agentkitUserConfig = { token: 'YOUR_SIGNED_TOKEN' };
</script>

En aplicaciones de una sola página (SPA), actualiza o borra la identidad en tiempo de ejecución, por ejemplo después de un inicio o cierre de sesión:

// After the user logs in (or the token is refreshed):
window.agentkit('identify', { token: newToken });

// After the user logs out:
window.agentkit('resetUser');

El widget adjunta el token a cada solicitud de chat automáticamente; no necesitas configurar ningún encabezado tú mismo.

Privacidad

Los campos de perfil verificados (email, name, phonenumber, custom_attributes) se guardan en el Contacto únicamente en el servidor. Nunca se inyectan en el prompt del agente ni en el contexto de RAG, y nunca se devuelven en ningún endpoint público. El agente no "ve" con quién está hablando.

Comportamiento de la verificación

La verificación nunca bloquea un chat. El visitante siempre puede hablar con el agente; la única diferencia es si se vincula o no un Contacto.

SituaciónResultado
Sin tokenVisitante anónimo. No se vincula ningún Contacto. (No es un error.)
Token válidoVerificado. Se crea o actualiza el Contacto y se vincula a la conversación.
Firma inválida o token malformadoAnónimo. El fallo queda registrado.
Token vencidoAnónimo. El fallo queda registrado.
aud no coincide con este agenteAnónimo. El fallo queda registrado.
Los claims del perfil superan los límitesAnónimo. El fallo queda registrado.

Los demás controles de acceso siguen aplicando

La verificación de identidad es independiente de quién puede cargar el widget. Los ajustes de restricciones de dominio y de visibilidad se siguen aplicando por separado.

Próximos pasos