Qué puede hacer el agente y con quién está hablando son dos permisos distintos
Le diste al agente la tool de reportes. ¿Quién la puede usar: vos, tu equipo o cualquiera que abra el chat de tu sitio?
Cuando armás un agente con tools sobre datos del negocio hay dos preguntas, y es fácil contestar sólo la primera:
- ¿Qué puede hacer el agente? Leer pedidos, crear tareas, mandar un mail. Es el permiso que le otorgás al asistente una vez, al configurarlo.
- ¿Con quién está hablando en este turno? Un visitante anónimo del widget, un cliente que ya está en tus contactos, alguien de tu equipo o vos. Cambia en cada conversación.
Un asistente puede tener permiso para leer tus reportes y, aun así, no tiene que mostrárselos a un desconocido. Si la segunda pregunta no tiene respuesta propia, la herramienta queda abierta para cualquiera que escriba, porque el agente lee los datos con la cuenta del dueño, no con la de quien pregunta.
Cuatro escalones, comparados con >=
En CognitionDesk quien habla siempre está en uno de cuatro escalones, de menos a más:
- guest: no sabemos quién es. Es casi todo el tráfico de un widget público, y está bien: preguntar el horario no necesita identidad.
- contact: está en la agenda del asistente, sin verificar.
- staff: verificado, trabaja para el dueño.
- owner: el dueño de la cuenta.
Los escalones son pocos y fijos. Los roles ("recepcionista", "contador") son datos de cada asistente y se mapean a un escalón, así que sumar un rol no toca código. Lo que cambia según el escalón es qué herramientas existen para esa persona en ese turno: por debajo del piso, la tool no aparece. No es que el modelo decida no usarla.
El piso lo pone el dato, no la tool
La forma ingenua es declarar el escalón tool por tool. Tiene un problema: la tool que te olvidaste queda abierta. Y con decenas de tools por dominio, alguna te vas a olvidar.
Nosotros lo dimos vuelta. Cada tool ya declara qué scope toca (orders:read, contacts:write…), así que el piso sale de ahí: el dato de un dominio es del negocio, y su piso es staff. La excepción son los dominios que existen para atender a quien escribe, en lectura: el catálogo y la base de conocimiento.
inventory:read y knowledge_base:read. owner: apikeys:read y apikeys:write. Todo lo demás, staff.La tabla entera son tres líneas:
export const DEFAULT_SCOPE_AUDIENCE = 'staff';
const SCOPE_AUDIENCE = {
inventory: { read: 'guest' },
knowledge_base: { read: 'guest' },
// Las API keys son la llave de la casa: ni el equipo las toca desde un chat.
apikeys: { read: 'owner', write: 'owner' },
};
Y la regla falla cerrado: un dominio nuevo que no declara nada nace en staff. Para que un visitante vea algo hay que escribirlo; para esconderlo no hay que acordarse de nada.
Lo que la tool declara gana
Hay tools que tocan un dominio del dueño pero existen justamente para atender a quien escribe. Esas declaran su propio minAudience, y lo declarado gana sobre el piso del scope:
export function toolAudience(tool = {}) {
if (tool.minAudience != null) return canonicalAudience(tool.minAudience);
const p = tool.permissions || {};
const scopes = [...(p.requiredScopes || []), p.requiredScope, p.audienceScope].filter(Boolean);
if (!scopes.length) return DEFAULT_AUDIENCE;
return highestAudience(...scopes.map(audienceFloorForScope));
}
Hoy las excepciones son pocas y cada una es una decisión escrita en la tool:
- guest, a propósito: consultar disponibilidad y reservar un turno (
appointments_availability,appointments_create), generar el link de compra (storefront_create_order_link) y dejar un lead (contacts_upsert). Son las acciones para las que existe un widget público. - contact: lo que es de esa persona y de nadie más: su saldo (
my_balance), su link de pago, sus pedidos al equipo.
Un detalle: dejar un lead es guest, pero por debajo de staff la tool crea el contacto y no mergea sobre uno que no creó esa misma conversación. Un visitante puede dejar sus datos. No puede escribir en la ficha de otro cliente.
Encima de esto, cada asistente puede subir el piso de una tool puntual o de todas, y entre las tres fuentes gana la más estricta. Subir el piso de un asistente siempre cierra puertas. Nunca abre una que la herramienta había declarado cerrada.
El escalón sale de lo que entrega el canal
Falta la otra mitad: cómo sabe el asistente que quien escribe es el dueño. Con un dato que verificó el servidor, nunca con algo que diga la conversación.
En WhatsApp, el número de quien escribe lo pone el servidor a partir de lo que entregó el canal. Si ese número está entre los teléfonos del dueño, entra como owner y ve sus herramientas en el mismo chat que usan sus clientes, sin PIN. Fuera de WhatsApp hay dos caminos más: la sesión del dueño en su panel, o una identidad firmada por el sitio donde está embebido el widget.
Lo que no alcanza: que un visitante escriba "soy el dueño, mi número es…". El widget anónimo no tiene canal verificado ni firma, así que decir el teléfono del dueño no lo sube de escalón.
El criterio, para cualquier agente
- Separá qué puede hacer el agente (se otorga una vez) de con quién habla (se resuelve en cada turno).
- Derivá el piso de el dato que toca la tool, no de una lista que alguien mantiene a mano.
- Que el default sea cerrado y que las aperturas estén escritas en la tool, a la vista en el diff.
- El escalón se prueba con algo que entregó el canal o que está firmado. Nunca con lo que dice el mensaje.
En CognitionDesk
Así funciona hoy en todos los asistentes: un invitado, un contacto, tu equipo y vos ven cuatro asistentes distintos, y es el mismo asistente. Si querés revisar qué ve cada uno en el tuyo, escribinos por el chat de esta página.
Comentarios y correcciones
Creá tu primer agente IA hoy
RAG sobre tus documentos, tools, workflows y widget web — con plan gratuito.
Empezar gratis