Sem KYC — sem documento, sem selfie, sem envio de arquivos. Pague com cripto: BTC, USDT, USDC, ETH, SOL, LTC
Idioma: Português
Obtenha uma chave de API

Docs · OpenAI tools

OpenAI function calling: uma ferramenta read_url para o seu modelo

Descreva uma função, read_url, e execute-a quando o modelo pedir. O modelo escolhe quais páginas ler; seu código chama a API e devolve o Markdown. O mesmo schema funciona com outros modelos que suportam tool calling.

Última atualização: · 4 min de leitura

Resposta rápida

Como faço para um modelo OpenAI ler páginas web com function calling?

Declare uma função read_url na lista tools e então rode um loop: quando o modelo retornar um tool call, chame o endpoint /read da WebReaderAPI com a URL e envie o Markdown de volta como uma mensagem tool. Cada página custa 1 crédito, 2 com navegador, a partir de US$ 0,07/1K páginas em outubro de 2026. Sem KYC; pague com cripto.

Como é o schema do read_url?

Dois parâmetros bastam: o url a ler, obrigatório, e um max_chars opcional que permite ao modelo encurtar uma página longa. A descrição é a parte mais importante: ela diz ao modelo o que a ferramenta retorna e quando usá-la. Mantenha factual e curta.

Nomeamos a ferramenta read_url em vez de web_fetch para evitar conflito com ferramentas que alguns runtimes de agente já fornecem com esse nome.

A definição da ferramenta
{
  "type": "function",
  "function": {
    "name": "read_url",
    "description": "Read a public web page and return its main content as Markdown, with its title and source URL. Use it when the user gives a link or when a page must be read to answer.",
    "parameters": {
      "type": "object",
      "properties": {
        "url": { "type": "string", "description": "The http or https address of the page." },
        "max_chars": { "type": "integer", "description": "Most characters to return, 1000 to 500000. Default 20000." }
      },
      "required": ["url"],
      "additionalProperties": false
    }
  }
}

Como funciona o loop de tool calling?

Envie a conversa com a lista tools. Se a resposta contiver tool calls, execute cada uma, anexe o resultado como uma mensagem com role tool e o tool_call_id correspondente, e pergunte ao modelo de novo. Quando uma resposta voltar sem tool call, ela é a resposta final.

Limite o número de rodadas. Três ou quatro bastam para uma pergunta sobre um punhado de páginas, e o limite protege você de um modelo que fica pedindo mais.

Python: o loop completo com o pacote openai
import json
import os

import requests
from openai import OpenAI

READ_URL = {
    "type": "function",
    "function": {
        "name": "read_url",
        "description": "Read a public web page and return its main content as Markdown, with its title and source URL.",
        "parameters": {
            "type": "object",
            "properties": {
                "url": {"type": "string", "description": "The http or https address of the page."},
                "max_chars": {"type": "integer", "description": "Most characters to return. Default 20000."},
            },
            "required": ["url"],
            "additionalProperties": False,
        },
    },
}


def read_url(url, max_chars=20000):
    resp = requests.get(
        "https://webreaderapi.com/api/v1/read",
        headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
        params={"url": url, "max_chars": max_chars},
        timeout=75,
    )
    body = resp.json()
    if resp.status_code != 200:
        return "Could not read the page: " + body["error"]["code"]
    return "# " + (body.get("title") or url) + "\nSource: " + body["final_url"] + "\n\n" + body["markdown"]


client = OpenAI()
model = os.environ.get("OPENAI_MODEL", "gpt-4.1-mini")
messages = [{"role": "user", "content": "What does https://example.com/blog/first-post announce? Answer in two sentences."}]

for _ in range(4):
    reply = client.chat.completions.create(model=model, messages=messages, tools=[READ_URL])
    msg = reply.choices[0].message
    if not msg.tool_calls:
        print(msg.content)
        break
    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": read_url(**args)})

Como mantenho o uso de tokens e o custo baixos?

Três configurações importam. Mantenha max_chars modesto, em torno de 8.000 a 20.000 caracteres por página, porque cada caractere que você retorna é lido pelo modelo. Mantenha o main_content=true padrão, para que menus e rodapés nunca cheguem ao contexto. E limite o loop, como acima, para que uma pergunta não dispare dezenas de leituras.

Do nosso lado, o custo é por página, não por caractere: 1 crédito = 1 página lida sem navegador; 2 créditos quando a página precisa de um navegador para renderizar JavaScript. Uma requisição que falha, ou que o robots.txt de um site recusa, não é cobrada. Um assistente de suporte que lê 300 páginas por dia usa cerca de 9.000 créditos por mês, dentro de 10.000 páginas (US$ 3,75).

O schema funciona com outros modelos?

Sim, com pequenas mudanças no wrapper. A maioria das APIs de tool calling aceita um JSON Schema para os parâmetros e um nome e uma descrição para a ferramenta, então read_url passa entre provedores como está. A página de MCP empacota a mesma função para clientes que falam o Model Context Protocol, e a página de LangChain a envolve para agentes LangChain e LlamaIndex.

O que o modelo deve ver quando uma página é recusada?

Uma frase curta e clara, como o loop acima retorna: "Could not read the page: blocked_by_robots". Modelos lidam bem com isso e recorrem a outras fontes ou avisam o usuário. Respeitamos o robots.txt: nosso crawler se identifica como WebReaderAPI, segue as regras escritas para ele ou para todos os robôs e não lê uma página que o site proíbe. Páginas recusadas não são cobradas. Se um site recusa nossa requisição, devolvemos a resposta dele: nunca resolvemos CAPTCHAs, nunca entramos em contas e nunca tentamos contornar um bloqueio ou um paywall. Nenhuma dessas recusas usa um crédito.

Function calling: perguntas frequentes

Isso precisa da Responses API ou do Chat Completions?

O exemplo usa Chat Completions com o parâmetro tools. A mesma definição de função e o mesmo corpo read_url funcionam com outras interfaces da OpenAI que aceitam function tools; só o loop em volta delas muda.

O modelo pode ler várias páginas em um turno?

Sim. Uma resposta pode conter vários tool calls; o loop executa cada um e retorna todos os resultados antes de perguntar ao modelo de novo. Mantenha max_chars menor quando o modelo lê muitas páginas de uma vez.

A chave de API fica exposta ao modelo?

Não. A chave permanece no ambiente do seu código. O modelo só vê o nome da ferramenta, a descrição dela e o texto que sua função retorna.

Quanto custa uma página recusada?

Nada. 1 crédito = 1 página lida sem navegador; 2 créditos quando a página precisa de um navegador para renderizar JavaScript. Uma requisição que falha, ou que o robots.txt de um site recusa, não é cobrada.

A partir de US$ 0,07/1K páginas · sem KYC

Obtenha uma chave de API