# OpenAI function calling: uno strumento di ricerca Google in 60 righe di Python

> Dai a un modello OpenAI uno strumento di ricerca Google: lo schema JSON e il loop di tool-calling in Python sulla SERP API di SerpCrypto.

- URL: https://serpcrypto.com/it/docs/openai/
- Ultimo aggiornamento: 2026-10-22
- Editore: SerpCrypto (https://serpcrypto.com)

Descrivi al modello una funzione `google_search`, esegui le ricerche che chiede, rimanda indietro i risultati. Lo schema è JSON Schema puro, quindi si trasporta tale e quale su Claude e sugli altri modelli con tool calling.

**Risposta rapida — Come do a un modello OpenAI uno strumento di ricerca web?**

Dichiara una funzione `google_search` con uno schema JSON in `tools`, poi fai un loop: quando il modello restituisce `tool_calls`, esegui ogni ricerca su `https://serpcrypto.com/api/v1/search` e aggiungi i risultati come messaggi `tool` finché non risponde. **SerpCrypto** addebita 1 credito per ogni ricerca riuscita, da 0,30 USD/1K ricerche, pagati in criptovalute senza KYC.

## Com'è fatto lo schema dello strumento?

Una funzione tool ha un nome, una descrizione e parametri in JSON Schema. Il modello vede solo queste tre cose, quindi la descrizione deve dire cosa restituisce lo strumento e quando usarlo. Solo `query` è obbligatorio; country e language sono opzionali e nel codice predefiniscono a US English.

*Definizione dello strumento (formato Chat Completions)*

```json
{
  "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"]
    }
  }
}
```

## Come funziona il ciclo di tool calling?

Invia la domanda con `tools`. Se la risposta contiene `tool_calls`, esegui ognuna di esse, aggiungi il messaggio dell'assistente e un messaggio `tool` per ogni chiamata con il `tool_call_id` corrispondente, poi chiama di nuovo il modello. Quando una risposta non contiene alcuna chiamata a strumenti, è la risposta finale.

Il ciclo qui sotto si ferma dopo tre ricerche. Un limite protegge i tuoi crediti se un modello continua a cercare, e tre ricerche bastano a rispondere alla maggior parte delle domande di fatto.

*search_agent.py*

```python
"""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."))
```

## Lo stesso schema funziona anche con Claude e altri modelli?

Sì, con un wrapper diverso. Il tool use di Claude accetta lo stesso JSON Schema sotto `input_schema`, accanto a `name` e `description`. Anche la maggior parte delle altre API di tool calling accetta JSON Schema per i parametri; cambiano solo i nomi dei campi esterni. La funzione di ricerca resta la stessa, perché chiama solo l'endpoint SerpCrypto.

*Lo stesso strumento per Claude (Messages API)*

```json
{
  "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"]
  }
}
```

## Cosa dovrebbe restituire lo strumento al modello?

Testo breve con i link. Cinque risultati con titolo, link e snippet di solito bastano al modello per rispondere e citare. Restituire l'intero JSON funziona, ma costa più token e dà al modello più rumore da leggere.

Aggiungi il testo di AI Overview quando è presente se vuoi che il modello veda il riepilogo di Google stesso, e mantieni i link alle fonti così la risposta può citare le pagine invece dell'overview.

## Come mantengo prevedibili i costi delle ricerche?

Conta le chiamate agli strumenti: ognuna che va a buon fine è un credito. Limita le ricerche per domanda, come fa il ciclo, e registra ogni chiamata con la sua query così puoi vedere cosa chiede il modello. Sul pack 100.000 ricerche la tariffa è 0,56 USD/1K ricerche, e I crediti di ricerca prepagati non scadono mai: le ricerche non utilizzate restano sul tuo account finché non le usi.

Gli errori non costano nulla: 1 credito = 1 richiesta di ricerca andata a buon fine, che restituisce una pagina di risultati su qualsiasi motore supportato. Una richiesta non riuscita non viene addebitata.

## Domande sul function calling

### Posso usare la Responses API invece di Chat Completions?

Sì. La Responses API accetta function tool con lo stesso JSON Schema, con `name`, `description` e `parameters` al livello superiore di ogni strumento. La funzione di ricerca e l'idea del ciclo non cambiano.

### Perché non usare la ricerca web integrata del provider del modello?

Gli strumenti di ricerca integrati scelgono da soli le proprie fonti e impostazioni. Una funzione su SerpCrypto ti dà i risultati di Google per il paese e la lingua che scegli, in JSON che puoi registrare, a un prezzo noto per ricerca.

### Il modello può scegliere il paese?

Sì. `gl` è un parametro dello strumento, quindi il modello può impostarlo dalla domanda, per esempio `gb` per una domanda sul Regno Unito. Mantieni un valore predefinito nel tuo codice per le domande che non nominano alcun paese.

### Serve una carta di credito per ottenere la chiave API di ricerca?

No. I crediti SerpCrypto si pagano in BTC, USDT, USDC, ETH, SOL, LTC, senza documento d'identità, senza selfie e senza documenti. Login con numero di account; email facoltativa.

---

SerpCrypto: SerpCrypto è un'API SERP per sviluppatori e agenti AI che restituisce i risultati di ricerca di Google e Bing in JSON, con pagamento in criptovalute e senza caricare documenti d'identità. I crediti di ricerca prepagati a partire da 0,30 USD/1K ricerche non scadono mai. Senza KYC — niente documento, niente selfie, niente documenti. Paghi in criptovalute.
