¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

El bucle de llamadas a herramientas

Después de esta lección: Puedo ejecutar el bucle de preguntar, llamar, responder y volver a preguntar.

Lección de 60 min2 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

El bucle detrás de todo modelo con herramientas

Una llamada a una herramienta es solo la mitad de una conversación. El modelo pide una llamada, tu programa la ejecuta, y el modelo debe ver el resultado antes de poder responder. Por eso el intercambio es un bucle.

Todo asistente que usa herramientas ejecuta este bucle, y siempre debe tener una forma de pararse.

Al final de esta lección

Nota

Puedo ejecutar el bucle de preguntar, llamar, responder y volver a preguntar.

Palabras clave

PalabraQué significa
Buclepasos que el programa repite hasta una condición de parada
Historialla lista de mensajes que se envía en cada pregunta
Resultado de herramientael mensaje que lleva al modelo la respuesta de una llamada
Pasouna pregunta y su respuesta
Límite de pasosel máximo de pasos que puede dar un bucle

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

El bucle vuelve a preguntar tras cada llamada

Envía los mensajes y las herramientas al modelo. Si la respuesta trae tool_calls, ejecuta cada llamada, añade los resultados a los mensajes y pregunta otra vez. Si la respuesta son palabras, es la respuesta final y el bucle termina.

El modelo no guarda nada entre una pregunta y otra. Cada pregunta lleva todo el historial.

Ejemplo resuelto: el historial tras cada paso

PasoQué ocurreMensajes que se envían después
InicioEl usuario pregunta por una perauser
1El modelo pide get_priceuser, assistant
1Tu programa añade el resultadouser, assistant, tool
2El modelo responde con palabrasuser, assistant, tool, assistant

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Guarda un ayudante que llama al modelo

Comando
docker exec -w /home/node/project agent node -e "const ask=async(m,t,c)=>{const r=await fetch((process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions',{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify({model:'lab',messages:m,tools:t,tool_choice:c,max_tokens:120})});const j=await r.json();if(r.ok)return j.choices[0].message;throw Error(r.status+' '+j.error.message)};require('fs').writeFileSync('ai.cjs','exports.ask='+ask+';');console.log('Guardado ai.cjs: ask(messages, tools) devuelve el mensaje del modelo.')"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un resultado de herramienta lleva el id

Después de una llamada añades un mensaje con el rol tool. Lleva el tool_call_id de la petición a la que responde y el resultado como texto.

El modelo usa el id para unir cada resultado con su petición. Sin él, una respuesta con dos llamadas no podría recibir sus dos resultados.

Ejecuta el bucle, como mucho tres pasos

Comando
docker exec -w /home/node/project agent node -e "const{ask}=require('./ai.cjs');const P={manzana:40,pera:45};const T=[{type:'function',function:{name:'get_price',description:'Precio de un artículo.',parameters:{type:'object',properties:{item:{type:'string'}}}}}];let rec=0;const fake=m=>m.at(-1).role=='tool'?{role:'assistant',content:'Cuesta 45 céntimos.'}:{role:'assistant',tool_calls:[{id:'c1',function:{name:'get_price',arguments:JSON.stringify({item:'pera'})}}]};(async()=>{const m=[{role:'user',content:'¿Cuánto cuesta una pera?'}];for(let s=1;s<4;s++){let a;try{if(rec)throw 0;a=await ask(m,T)}catch(e){rec||console.log('Sin modelo ('+e.message+'). Muestra grabada:');rec=1;a=fake(m)}m.push(a);if(a.tool_calls==null){console.log('Respuesta: '+a.content);return}for(const c of a.tool_calls){const v=P[JSON.parse(c.function.arguments).item];console.log('Paso '+s+': '+c.function.name+' -> '+v);m.push({role:'tool',tool_call_id:c.id,content:String(v)})}}console.log('Límite alcanzado')})()"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un límite de pasos frena el bucle

Un modelo puede pedir una llamada una y otra vez. Cada paso cuesta tiempo y crédito, así que cuentas los pasos y paras en un límite. Tres es un buen comienzo.

Cuando el límite llega primero, tu programa lo dice. No finge tener una respuesta.

Un error frecuente

Advertencia

Mucha gente cree que el modelo recuerda las preguntas anteriores. No es así. Solo ve los mensajes que tú envías. Si te dejas el resultado de la herramienta, el modelo no puede saber qué devolvió la llamada: conserva todos los mensajes.

Para ir más lejos: cambia la pregunta

Cambia la pregunta de la ejecución a ¿Cuánto cuestan una manzana y una pera?. Ejecútala tres veces y cuenta los pasos cada vez.

Después cambia s<4 por s<2. Escribe qué imprime el programa cuando el límite llega primero.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.