# OpenAI function calling: geef het model een search_web-tool

> Webzoekopdrachten voor OpenAI function calling: een search_web JSON-schema en de Responses API-loop in Python met dezelfde tool in de Agents SDK.

- URL: https://llmwebsearch.com/nl/docs/openai/
- Laatst bijgewerkt: 2026-10-22
- Uitgever: LLMWebSearch (https://llmwebsearch.com)

Beschrijf een `search_web`-functie aan het model, voer de call die het vraagt uit tegen onze API en stuur de bronnen terug. Het model antwoordt dan met bronvermeldingen. Deze pagina toont het JSON-schema, de Responses API-loop en de kortere versie met de OpenAI Agents SDK.

**Snel antwoord — Hoe voeg ik webzoekopdrachten toe aan een OpenAI-model met function calling?**

Declareer een `search_web`-functie met een JSON-schema, en wanneer het model die aanroept, POST je de zoekopdracht naar de `https://llmwebsearch.com/api/v1/search` van **LLMWebSearch**. Stuur de genummerde bronnen terug, met de top 3 pagina's als Markdown, als een `function_call_output`; het model antwoordt en citeert ze. Een zoekopdracht kost 1 credit, vanaf US$ 1,20/1K zoekopdrachten per oktober 2026. Zonder KYC; betalen met crypto.

## Wat je nodig hebt

| Attribuut | Waarde |
| --- | --- |
| Packages | `openai` en `requests` (of `openai-agents` voor de Agents SDK-versie) |
| Sleutels | `OPENAI_API_KEY` voor het model, `LLMWEBSEARCH_API_KEY` voor zoeken |
| Model | Elk model dat function calling ondersteunt, ingesteld in `OPENAI_MODEL` |
| Gebruikte API | Responses API: `client.responses.create` met `tools` en `input` |
| Facturering aan onze kant | Eén credit betaalt één zoekopdracht: tot 20 gerangschikte resultaten, waarbij de pagina's van de eerste 3 worden gelezen en als Markdown teruggegeven. Het lezen van 4 tot 10 pagina's kost 2 credits. Een call die op een fout eindigt, kost niets |

## Hoe ziet het tool-schema eruit?

Een function tool heeft een `name`, een `description` en JSON Schema-`parameters`. Houd de beschrijving concreet: wat de tool teruggeeft, en dat bronnen op nummer geciteerd moeten worden. Twee parameters zijn genoeg voor de meeste agents: de `query`, en hoeveel topresultaten volledig moeten worden `read`.

Het model ziet je API-sleutel nooit. Het stelt alleen argumenten voor; jouw code bepaalt hoe de API wordt aangeroepen en wat er wordt teruggestuurd.

## Hoe werkt de call-loop?

Stuur het bericht van de gebruiker mee met de tools. Als de response items van het type `function_call` bevat, parse je de JSON-`arguments` van elk, voer je de zoekopdracht uit en voeg je een `function_call_output` toe met dezelfde `call_id`. Roep het model dan opnieuw aan met de langere invoerlijst. Als een response geen function call bevat, is de tekst ervan het antwoord.

De loop hieronder stopt na vijf rondes, een vangnet tegen een model dat blijft zoeken. OpenAI's function-calling-gids beschrijft dezelfde `function_call`- en `function_call_output`-items, gelezen op 22 oktober 2026.

*search_tool_loop.py (Responses API)*

```python
import json
import os

import requests
from openai import OpenAI

client = OpenAI()
MODEL = os.environ["OPENAI_MODEL"]  # any model that supports function calling
SEARCH = "https://llmwebsearch.com/api/v1/search"

tools = [
    {
        "type": "function",
        "name": "search_web",
        "description": "Search the live web. Returns numbered sources with URLs; the first `read` include page text. Cite sources as [1], [2].",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "What to search for, as a person would type it."},
                "read": {"type": "integer", "minimum": 0, "maximum": 10, "description": "How many top results to read in full."},
            },
            "required": ["query"],
            "additionalProperties": False,
        },
    }
]


def search_web(query, read=3):
    resp = requests.post(
        SEARCH,
        headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
        json={"q": query, "max_results": 5, "read": read, "max_chars": 5000},
        timeout=60,
    )
    if resp.status_code != 200:
        return "Search failed: " + resp.json().get("error", {}).get("code", str(resp.status_code))
    parts = []
    for i, r in enumerate(resp.json()["results"], start=1):
        text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
        parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
    return "\n\n".join(parts)


input_list = [{"role": "user", "content": "How should I size a Postgres connection pool?"}]
for _ in range(5):
    response = client.responses.create(model=MODEL, tools=tools, input=input_list)
    calls = [item for item in response.output if item.type == "function_call"]
    if not calls:
        print(response.output_text)
        break
    input_list += response.output
    for item in calls:
        args = json.loads(item.arguments)
        output = search_web(args["query"], int(args.get("read", 3)))
        input_list.append({"type": "function_call_output", "call_id": item.call_id, "output": output})

```

## Is er een kortere versie met de Agents SDK?

Ja. De OpenAI Agents SDK maakt van een Python-functie een tool met een decorator en voert de call-loop voor je uit. De tools-documentatie, gelezen op 22 oktober 2026, toont de `@tool`-decorator uit `agents.decorators`, met de beschrijving uit de docstring en de beschrijving van elk argument uit zijn `Args`-sectie. Dezelfde pagina noemt ook de `@function_tool`-vorm.

`Runner.run_sync` voert de agent uit tot hij een definitief antwoord produceert, en roept `search_web` zo vaak aan als het model vraagt.

*search_agent.py (OpenAI Agents SDK)*

```python
import os

import requests
from agents import Agent, Runner
from agents.decorators import tool


@tool
def search_web(query: str, read: int = 3) -> str:
    """Search the live web and return numbered sources with their URLs.

    Args:
        query: What to search for, as a person would type it.
        read: How many top results to read in full, from 0 to 10.
    """
    resp = requests.post(
        "https://llmwebsearch.com/api/v1/search",
        headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
        json={"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000},
        timeout=60,
    )
    resp.raise_for_status()
    parts = []
    for i, r in enumerate(resp.json()["results"], start=1):
        text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
        parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
    return "\n\n".join(parts)


agent = Agent(
    name="Researcher",
    instructions="Answer from search_web results only and cite them as [1], [2].",
    tools=[search_web],
)
result = Runner.run_sync(agent, "How should I size a Postgres connection pool?")
print(result.final_output)

```

## Waarom een API-tool gebruiken in plaats van de ingebouwde webzoekfunctie van OpenAI?

Vooral voor controle over wat het model leest en wat het kost. Onze tool geeft je code de ruwe bronnen, met URL's en paginatekst, zodat jij bepaalt wat in de context komt, het kunt loggen en kunt opslaan. We trainen geen enkel model op je zoekopdrachten of op wat de API teruggeeft, en we voegen geen eigen regel toe tegen het opslaan van resultaten; de rechten van de sites waarvan je pagina's leest, gelden nog steeds.

De prijs ligt ook vast per zoekopdracht in plaats van afhankelijk te zijn van hoeveel opgehaalde inhoud het model leest. De [vergelijking van ingebouwde tools](https://llmwebsearch.com/nl/compare/built-in-web-search-tools/) zet de prijzen per aanroep van OpenAI, Anthropic, Google en anderen naast elkaar, met data.

## Hoe voorkom ik dat het model te veel zoekt?

Zeg het in de instructions: zoek één keer, lees de bronnen, zoek alleen opnieuw als ze elkaar tegenspreken of het punt missen. Beperk het aantal rondes in je eigen loop, zoals het script hierboven doet met vijf.

Houd `max_chars` bescheiden. Drie pagina's van 5.000 tekens is ongeveer 4.000 tokens per zoekopdracht, en elke ronde voegt ze toe aan de input van de volgende modelaanroep.

## OpenAI function calling: veelgestelde vragen

### Werkt dit met de Chat Completions API?

Ja, met het oudere `tools`-formaat van Chat Completions, waarbij de function in een `function`-object zit en resultaten terugkomen als `tool`-berichten. De zoekfunctie zelf verandert niet.

### Kan het model een pagina lezen die het in een bron vindt?

Voeg een tweede function toe, `read_urls`, die URL's naar `https://llmwebsearch.com/api/v1/extract` post. Het lezen van pagina's waarvan je de URL's al hebt, kost 1 credit per begonnen groep van 3 pagina's die met inhoud worden teruggegeven, tot 20 URL's per call; geweigerde of mislukte URL's tellen niet mee.

### Welk model moet ik gebruiken?

Elk model dat function calling ondersteunt. Probeer er twee of drie op je eigen vragen: het antwoord hangt net zo goed van de bronnen af als van het model, en een kleiner model kost minder per ronde.

## Bronnen

1. [Function calling](https://developers.openai.com/api/docs/guides/function-calling) — OpenAI API docs (read 2026-10-22)
2. [Tools (OpenAI Agents SDK)](https://openai.github.io/openai-agents-python/tools/) — OpenAI Agents SDK docs (read 2026-10-22)

---

LLMWebSearch: LLMWebSearch is een webzoek-API voor AI-agents die gerangschikte resultaten teruggeeft met de inhoud van de belangrijkste pagina's als Markdown, betaald met crypto zonder ID-upload. Voorafbetaalde credits vanaf US$ 1,20/1K zoekopdrachten verlopen nooit. Zonder KYC — geen ID, geen selfie, geen documenten. Betalen met crypto.
