API y SDKGuía
Function calling en Python con una API compatible con OpenAI
Envía herramientas, lee tool_calls y devuelve el resultado con role tool: un bucle de function calling en dos pasos en Python con MiniMax-M2.7.

En esta página
El function calling (tool calling) permite que un modelo pida a tu código que ejecute una función. Envías una lista tools con la petición, el modelo responde con tool_calls en lugar de texto, ejecutas la función tú mismo y devuelves su resultado en un mensaje con role: tool. Después el modelo escribe la respuesta final. Esta guía muestra el bucle completo en Python contra el endpoint compatible con OpenAI https:/ con MiniMax-M2.7 (id MiniMaxAI/, contexto de 180K, hasta 8.192 tokens de salida por respuesta).
El tool calling figura como compatible en todos los modelos del catálogo (CheapTokens docs, comprobado el 22 de octubre de 2026). Necesitas una clave de API; si aún no has hecho ninguna petición, empieza por tu primera petición a la API.
Cómo funciona el function calling#
El modelo nunca ejecuta nada. Solo produce una petición estructurada: «llama a get_weather con {\"city\": \"Paris\"}». Tu programa hace el trabajo real y le informa. Eso forma un bucle de dos peticiones:
- Petición 1. Envías el mensaje del usuario junto con la lista
tools. El modelo responde en texto o devuelve uno o variostool_calls. - Tu código. Analizas cada llamada, ejecutas la función correspondiente y recoges el resultado.
- Petición 2. Envías de nuevo toda la conversación: los mensajes originales, el mensaje del asistente con
tool_callsy un mensajerole: toolpor cada llamada. El modelo usa los resultados para escribir la respuesta final.
Cada petición reenvía todo el historial, así que los bucles de herramientas consumen más tokens de entrada que una sola pregunta. Si esto es nuevo para ti, lee qué es un token.
Configura el cliente#
Instala el SDK de OpenAI (pip install openai) y guarda tu clave en una variable de entorno en lugar de en el código fuente:
export CHEAPTOKENS_API_KEY="your-key-here"La URL base es https:/. Toma el id del modelo de la documentación de CheapTokens: distintos proveedores nombran de forma distinta el mismo modelo. Esta guía usa MiniMaxAI/.
Declara una función y envía la primera petición#
Una función se describe en el array tools. Cada entrada tiene type: function y un objeto function con un name, un description y parameters escrito como JSON Schema. La descripción es lo que lee el modelo para decidir cuándo llamar a la función, así que redáctala como una frase breve y concreta.
A continuación tienes un script completo. La función del tiempo es un stub con datos falsos, así que el ejemplo no necesita servicios adicionales:
import json
import os
from openai import OpenAI
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'
def get_weather(city: str) -> dict:
# Stub with fake data: replace with a real lookup
fake = {'Paris': 14, 'Tokyo': 19}
return {'city': city, 'temp_c': fake.get(city, 10)}
FUNCTIONS = {'get_weather': get_weather}
tools = [
{
'type': 'function',
'function': {
'name': 'get_weather',
'description': 'Get the current temperature in Celsius for a city.',
'parameters': {
'type': 'object',
'properties': {
'city': {'type': 'string', 'description': 'City name, for example Paris'},
},
'required': ['city'],
},
},
}
]
messages = [{'role': 'user', 'content': 'What is the weather in Paris right now?'}]
# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message
if not message.tool_calls:
print(message.content)
raise SystemExit
# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.tool_calls:
args = json.loads(call.function.arguments)
result = FUNCTIONS[call.function.name](**args)
messages.append({
'role': 'tool',
'tool_call_id': call.id,
'content': json.dumps(result),
})
final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)Tres detalles deciden si el bucle funciona:
call.es una cadena JSON, no un diccionario. Analízala confunction. arguments json.loads.- Cada mensaje
role: tooldebe llevar eltool_call_idde la llamada a la que responde, que escall.id. - El
contentde un mensaje de herramienta es una cadena. Usajson.dumpspara resultados estructurados.
Qué deberías ver#
Si imprimes los campos después de la primera petición, se ven así (el id de la llamada cambia en cada ejecución):
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}Después el script imprime la respuesta final, una frase sencilla del estilo «It is currently 14 °C in Paris.» La redacción cambia de una ejecución a otra; el número procede de tu función.
Varias llamadas y bucles más largos#
Un modelo puede devolver más de una llamada en una sola respuesta, por ejemplo cuando preguntas por el tiempo en dos ciudades. Por eso el ejemplo recorre message. y responde a cada llamada por su propio id. La guía de function calling de OpenAI describe el mismo comportamiento: con el tool_choice predeterminado de auto, el modelo puede llamar a cero, una o varias funciones (OpenAI docs, comprobado el 22 de octubre de 2026; la página no tiene fecha de última actualización y describe la forma más reciente de la Responses API, mientras que esta guía usa la forma de Chat Completions del endpoint /).
Los agentes repiten los dos pasos hasta que el modelo deja de pedir herramientas. Envuelve las peticiones en un bucle y fija siempre un límite de pasos:
for _ in range(5): # safety limit against endless loops
response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = response.choices[0].message
if not message.tool_calls:
print(message.content)
break
messages.append(message)
for call in message.tool_calls:
args = json.loads(call.function.arguments)
result = FUNCTIONS[call.function.name](**args)
messages.append({'role': 'tool', 'tool_call_id': call.id, 'content': json.dumps(result)})Si quieres que la respuesta aparezca token a token, combínalo con streaming en Python.
Por qué MiniMax-M2.7 encaja en los bucles de herramientas#
Un bucle de herramientas envía muchas peticiones con un historial creciente. Para ese patrón CheapTokens ofrece MiniMax-M2.7: contexto de 180K, hasta 8.192 tokens de salida por respuesta, un único precio a cualquier hora del día sin horas punta y un solo saldo para todos los modelos. Contando entrada y salida juntas, es más barato que el precio de referencia de OpenRouter (comparativa de precios de CheapTokens, comprobada el 31 de octubre de 2026).
Precios actuales por 1M de tokens: entrada $0.05, salida $0.15. Como carga de ejemplo (no es una medición), el ida y vuelta de dos peticiones anterior con unos 2.700 tokens de entrada y 350 de salida en total cuesta $0.00019. La lista completa de precios está en la página de precios.
Para probar otro modelo, cambia solo el id; la lista de ids está en la página de modelos.
Si no funciona#
message.estool_ calls None. El modelo respondió en texto. Haz más específica la funcióndescriptiony asegúrate de que la pregunta realmente necesita la función.json.enJSONDecodeError arguments. El modelo generó JSON no válido. Envuelvejson.loadsentry/excepty devuelve el texto del error como resultado de la herramienta, para que el modelo pueda reintentar con argumentos corregidos.- La segunda petición falla o el modelo ignora el resultado. Comprueba que cada llamada tiene exactamente un mensaje
role: toolcon untool_call_idcoincidente, y que el mensaje del asistente contool_callsestá en el historial antes que ellos. KeyErrorenFUNCTIONS[...]. El modelo nombró una función que no registraste. Devuelve una cadena de error breve como resultado de la herramienta en lugar de fallar.- La respuesta se corta. Comprueba
finish_reason: el valorlengthsignifica que se alcanzó el límite de tokens de salida. Consulta por qué una respuesta de IA se detiene a mitad de frase. - Errores 401 o de autenticación. Comprueba que la clave está en
CHEAPTOKENS_y que la URL base termina enAPI_ KEY /v1.
Próximos pasos#
Sustituye el stub por una función real: una consulta a base de datos, una llamada de búsqueda o una calculadora. Añade más entradas a tools y a FUNCTIONS, y mantén corto cada resultado de función, porque vuelve al historial en cada petición siguiente. Para obtener una clave y hacer la primera llamada, abre la documentación de CheapTokens.



