Una propuesta, no una ejecución
Imagina que una persona pregunta: «¿Cuánta proteína tiene el arroz?». El modelo puede responder con una tool call: search_foods y el argumento {"query":"arroz"}. Esa salida es datos del proveedor, no una llamada directa a una función de la app. El modelo no conoce el catálogo local, no tiene acceso a su almacenamiento y no puede invocar código por sí mismo.
El harness es el programa que recibe esa propuesta, decide si la acepta y conecta el nombre con una función local. El identificador de la llamada se conserva aparte para asociar después el resultado con la petición correcta. OpenAI, Anthropic y Google usan formatos distintos para transportar la tool call, pero una vez parseada, el despachador trabaja con el mismo par: name y args.
El recorrido completo
La primera barrera comprueba que el nombre esté declarado y que esa clase de acción esté permitida para la consulta. Solo entonces el registro busca el handler. En el ejemplo, search_foods es una lectura: su handler consulta el catálogo y devuelve una cadena con los resultados. Una escritura local exige además coordinar el efecto y confirmar que se guardó antes de comunicar éxito.
Elegir la función correcta
Un registro relaciona nombres públicos con funciones. Es la frontera exacta entre «el modelo quiere hacer esto» y «la aplicación ejecuta esta función». El ejemplo reducido muestra la decisión central:
const handlers = {
search_foods: searchFoods,
read_measurement: readMeasurement,
};
const handler = Object.hasOwn(handlers, call.name)
? handlers[call.name]
: undefined;
if (!handler) return "Tool no reconocida";
return await handler(call.args, context, dependencies);Comprobar que la propiedad pertenece al registro importa: un objeto JavaScript también hereda nombres como constructor y toString. Una búsqueda ingenua podría confundirlos con handlers. Mantener el registro fijo durante la ejecución garantiza que un mismo nombre elija siempre la misma función.
El schema que se anuncia al proveedor describe la forma esperada de los argumentos, pero no convierte una respuesta del modelo en entrada fiable. Cada handler debe validar los datos de su dominio antes de escribir. Añadir una validación genérica en la frontera del despachador es una mejora separada; no hay que atribuírsela a este registro.
Errores y efectos
Si el nombre no está declarado, el harness devuelve un error controlado y no ejecuta ninguna función. Si un handler falla, el turno debe recibir una respuesta útil en lugar de romper todo el chat. Para una lectura basta con devolver el dato o el error. Para una escritura, «se llamó al handler» no equivale a «se guardó»: el efecto se confirma después de persistirlo y los fallos ambiguos no se reintentan a ciegas.
el modelo propone la acción; el código de la aplicación decide la autorización, ejecuta el handler y comprueba el resultado. El nombre de la tool nunca concede permiso por sí solo.
Devolver el resultado
El handler produce una salida textual. El bucle del proveedor la empaqueta junto con el identificador original: function_call_output en OpenAI, tool_result en Anthropic o function_result en Google Interactions. Después solicita otra respuesta al modelo. Así, el modelo puede explicar a la persona lo que encontró; no necesita inventar lo que había en el catálogo.
Tests del contrato
La prueba central recorre los nombres declarados con argumentos válidos, verifica que cada uno llegue a su comportamiento esperado y devuelva texto, y compara la lista con los handlers registrados. Otras pruebas cubren nombres desconocidos, incluidos los que hereda un objeto JavaScript, y comprueban que ninguna dependencia de escritura se invoca. Repetir el mismo caso con un contexto nuevo detecta cambios accidentales de ruta sin depender de un modelo remoto.
Aprender a construir un agente completo
Este artículo forma parte de una serie sobre cómo construir un agente o harness usando una app de gimnasio como caso práctico. El paso anterior fue reconstruir una llamada completa desde el stream; aquí vimos dónde se transforma en código. El siguiente límite es validar sistemáticamente los argumentos antes de cualquier efecto.
Ver el índice completo de la serie sobre el agente de Gymnasia.