Sin KYC — sin ID, sin selfie, sin documentos. Paga con criptomonedas: BTC, USDT, USDC, ETH, SOL, LTC
Idioma: Español
Obtener una clave API

Docs · Function calling · Tool use · Python

OpenAI function calling: una herramienta de búsqueda de Google en 60 líneas de Python

Describe al modelo una función google_search, ejecuta las búsquedas que pida y devuélvele los resultados. El esquema es JSON Schema puro, así que se traslada a Claude y a otros modelos con tool calling.

Última actualización: · 5 min de lectura

Respuesta rápida

¿Cómo le doy a un modelo de OpenAI una herramienta de búsqueda web?

Declara una función google_search con un JSON Schema en tools y luego haz un bucle: cuando el modelo devuelva tool_calls, ejecuta cada búsqueda en https://serpcrypto.com/api/v1/search y añade los resultados como mensajes tool hasta que responda. SerpCrypto cobra 1 crédito por búsqueda exitosa, desde 0,30 US$/1K búsquedas, pagado con criptomonedas sin KYC.

¿Cómo es el esquema de la herramienta?

Una herramienta de función tiene un nombre, una descripción y parámetros en JSON Schema. El modelo solo ve estas tres cosas, así que la descripción debe indicar qué devuelve la herramienta y cuándo usarla. Solo query es obligatorio; país e idioma son opcionales y por defecto usan inglés de EE. UU. en el código.

Definición de la herramienta (formato Chat Completions)
{
  "type": "function",
  "function": {
    "name": "google_search",
    "description": "Search Google for current information. Returns the top results with title, link and snippet. Use it for facts newer than your training data.",
    "parameters": {
      "type": "object",
      "properties": {
        "query": { "type": "string", "description": "The search query, as a person would type it." },
        "gl": { "type": "string", "description": "Two-letter country code of the results, e.g. us, gb, de." },
        "hl": { "type": "string", "description": "Language code, e.g. en, de, pt-BR." }
      },
      "required": ["query"]
    }
  }
}

¿Cómo funciona el bucle de llamada a herramientas?

Envía la pregunta con tools. Si la respuesta contiene tool_calls, ejecuta cada una, añade el mensaje del asistente y un mensaje tool por cada llamada con el tool_call_id correspondiente, y vuelve a llamar al modelo. Cuando una respuesta no tiene llamada a herramienta, es la respuesta final.

El bucle de abajo se detiene tras tres búsquedas. Un límite protege tus créditos si un modelo sigue buscando, y tres búsquedas responden la mayoría de las preguntas factuales.

search_agent.py
"""Tool-calling loop: the model asks for searches, this code runs them on SerpCrypto."""
import json
import os

import requests
from openai import OpenAI

client = OpenAI()  # reads OPENAI_API_KEY
MODEL = os.environ["OPENAI_MODEL"]  # any OpenAI chat model with tool calling
API_URL = "https://serpcrypto.com/api/v1/search"

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "google_search",
            "description": "Search Google for current information. Returns the top results with title, link and snippet.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "The search query."},
                    "gl": {"type": "string", "description": "Two-letter country code, e.g. us."},
                    "hl": {"type": "string", "description": "Language code, e.g. en."},
                },
                "required": ["query"],
            },
        },
    }
]


def google_search(query, gl="us", hl="en"):
    r = requests.get(
        API_URL,
        params={"q": query, "gl": gl, "hl": hl},
        headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
        timeout=90,
    )
    if r.status_code != 200:
        return f"Search failed with HTTP {r.status_code}."
    items = r.json().get("organic_results", [])[:5]
    return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in items) or "No results."


def ask(question, max_searches=3):
    messages = [{"role": "user", "content": question}]
    for _ in range(max_searches + 1):
        reply = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
        msg = reply.choices[0].message
        if not msg.tool_calls:
            return msg.content
        messages.append(msg)
        for call in msg.tool_calls:
            args = json.loads(call.function.arguments)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": google_search(**args)})
    return "Stopped: search limit reached."


print(ask("Which countries changed their data protection laws in 2026? Cite sources."))

¿Funciona el mismo esquema con Claude y otros modelos?

Sí, con un wrapper distinto. El uso de herramientas de Claude acepta el mismo JSON Schema en input_schema, junto a name y description. La mayoría de las otras APIs de llamada a funciones también aceptan JSON Schema para los parámetros; solo cambian los nombres de los campos externos. La función de búsqueda en sí no cambia, porque solo llama al endpoint SerpCrypto.

La misma herramienta para Claude (Messages API)
{
  "name": "google_search",
  "description": "Search Google for current information. Returns the top results with title, link and snippet.",
  "input_schema": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "The search query." },
      "gl": { "type": "string", "description": "Two-letter country code, e.g. us." },
      "hl": { "type": "string", "description": "Language code, e.g. en." }
    },
    "required": ["query"]
  }
}

¿Qué debería devolver la herramienta al modelo?

Texto corto con enlaces. Cinco resultados con título, enlace y snippet suelen bastar para que el modelo responda y cite. Devolver el JSON completo funciona, pero cuesta más tokens y le da al modelo más ruido que leer.

Añade el texto del AI Overview cuando esté presente si quieres que el modelo vea el propio resumen de Google, y conserva los enlaces de las fuentes para que la respuesta pueda citar páginas en lugar del overview.

¿Cómo mantengo predecibles los costes de búsqueda?

Cuenta las llamadas a herramientas: cada una que se realiza con éxito es un crédito. Limita las búsquedas por pregunta, como hace el bucle, y registra cada llamada con su consulta para ver qué pide el modelo. En el pack 100.000 búsquedas la tarifa es 0,56 US$/1K búsquedas, y Los créditos de búsqueda prepagados no caducan nunca: las consultas sin usar se quedan en tu cuenta hasta que las uses.

Los errores no cuestan nada: 1 crédito = 1 consulta correcta, que devuelve una página de resultados en cualquier motor compatible. Una consulta fallida no se cobra.

Preguntas sobre llamada a funciones

¿Puedo usar la Responses API en lugar de Chat Completions?

Sí. La Responses API acepta herramientas de función con el mismo JSON Schema, con name, description y parameters en el nivel superior de cada herramienta. La función de búsqueda y la idea del bucle no cambian.

¿Por qué no usar la búsqueda web integrada del proveedor del modelo?

Las herramientas de búsqueda integradas eligen sus propias fuentes y ajustes. Una función en SerpCrypto te da resultados de Google para el país y el idioma que elijas, como JSON que puedes registrar, a un precio conocido por búsqueda.

¿Puede el modelo elegir el país?

Sí. gl es un parámetro de la herramienta, así que el modelo puede definirlo a partir de la pregunta, por ejemplo gb para una pregunta sobre el Reino Unido. Mantén un valor predeterminado en tu código para preguntas que no nombran ningún país.

¿Necesito una tarjeta de crédito para obtener la clave API de búsqueda?

No. Los créditos de SerpCrypto se pagan con BTC, USDT, USDC, ETH, SOL, LTC, sin identificación, sin selfie y sin documentos. Inicio de sesión con el número de cuenta; el email es opcional.

Desde 0,30 US$/1K búsquedas · sin KYC

Obtener una clave API