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

Guia · Python · cerca de 60 linhas, qualquer LLM

Crie um agente de deep research em Python com uma API de pesquisa na web

Deep research é um loop, não um modelo. Este guia monta um que você lê em poucos minutos: ele planeja consultas, pesquisa na web com o texto da página incluído, mantém cada fonte uma única vez, procura lacunas e escreve uma resposta com citações numeradas.

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

Resposta rápida

Como crio um agente de deep research em Python?

Escreva um loop que pede ao LLM consultas de pesquisa, executa cada uma por uma API de pesquisa na web que retorna o texto da página, mantém cada fonte uma única vez, pede consultas de acompanhamento e então escreve uma resposta com citações. Com o LLMWebSearch, cada pesquisa retorna as 3 primeiras páginas em Markdown por um crédito; o script abaixo executa seis pesquisas por pergunta. A partir de US$ 1,20/1K pesquisas, sem KYC, pagar com cripto.

O que o agente vai fazer?

  1. Plano

    Peça ao modelo quatro consultas curtas que, juntas, cubram a pergunta.

  2. Pesquisar

    Execute cada consulta com o read=3, para que as três primeiras páginas voltem em Markdown.

  3. Mantenha cada fonte uma única vez

    Armazene os resultados por URL e ignore páginas já coletadas ou sem texto.

  4. Encontre lacunas

    Mostre ao modelo os títulos encontrados até agora e peça duas consultas sobre o que está faltando.

  5. Escreva

    Numere até 12 fontes e peça uma resposta que as cite como [1], [2].

O que preciso antes de começar?

Três coisas:

  • Uma chave de API do LLMWebSearch na variável de ambiente LLMWEBSEARCH_API_KEY. As chaves aparecem no dashboard após seu primeiro pacote.
  • Qualquer endpoint de chat compatível com OpenAI, definido com LLM_BASE_URL, LLM_API_KEY e LLM_MODEL. Modelos hospedados e servidores locais funcionam.
  • Python 3.9 ou superior com o pacote requests.

O script usa HTTP simples para os dois serviços, então você pode trocar o modelo sem alterar o código de pesquisa.

Python: deep_research.py
import os

import requests

SEARCH = "https://llmwebsearch.com/api/v1/search"
SEARCH_HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
# Any OpenAI-compatible chat endpoint works here: set your own base URL, key and model name.
LLM_URL = os.environ.get("LLM_BASE_URL", "https://llm.example.com/v1") + "/chat/completions"
LLM_HEADERS = {"Authorization": "Bearer " + os.environ.get("LLM_API_KEY", "")}
MODEL = os.environ.get("LLM_MODEL", "your-model-name")


def ask_llm(prompt):
    body = {"model": MODEL, "messages": [{"role": "user", "content": prompt}]}
    resp = requests.post(LLM_URL, headers=LLM_HEADERS, json=body, timeout=120)
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]


def plan_queries(question, n=4):
    text = ask_llm(f"Write {n} short web search queries, one per line, to answer: {question}")
    queries = [line.strip("-*0123456789. ").strip() for line in text.splitlines()]
    return [q for q in queries if q][:n]


def search(query):
    body = {"q": query, "max_results": 5, "read": 3, "max_chars": 5000}
    resp = requests.post(SEARCH, headers=SEARCH_HEADERS, json=body, timeout=60)
    resp.raise_for_status()
    return resp.json()["results"]


def research(question, rounds=2):
    sources = {}  # url -> result, so the same page is never cited twice
    queries = plan_queries(question)
    for _ in range(rounds):
        for query in queries:
            for r in search(query):
                if r.get("content_status") == "ok" and r["url"] not in sources:
                    sources[r["url"]] = r
        notes = "\n".join(f"- {r['title']}" for r in sources.values())
        queries = plan_queries(f"{question}\nAlready found:\n{notes}\nWhat is still missing?", n=2)
    numbered = list(sources.values())[:12]
    context = "\n\n".join(
        f"[{i}] {r['title']} ({r['url']})\n{r['content']}" for i, r in enumerate(numbered, 1)
    )
    prompt = (
        "Answer the question using only the sources below. Cite them as [1], [2]. "
        "Say so when the sources disagree or do not cover a point.\n\n"
        f"Question: {question}\n\nSources:\n{context}"
    )
    return ask_llm(prompt), [r["url"] for r in numbered]


if __name__ == "__main__":
    answer, urls = research("What changed in the EU rules for general-purpose AI models in 2025?")
    print(answer)
    for i, url in enumerate(urls, 1):
        print(f"[{i}] {url}")

Como funciona cada parte?

plan_queries pede ao modelo consultas curtas, uma por linha, e remove marcadores de lista. Consultas curtas se encaixam melhor em como os mecanismos de pesquisa classificam páginas do que perguntas completas.

search chama POST https://llmwebsearch.com/api/v1/search com max_results=5, read=3 e max_chars=5000. A resposta lista cinco resultados; os três primeiros trazem o texto da página em content.

research executa as rodadas. Ele mantém as fontes em um dicionário com chave por URL, então uma página encontrada por duas consultas conta uma vez. Só são mantidos os resultados com content_status igual a ok, porque a resposta precisa se apoiar em texto que o modelo consegue ler.

Após cada rodada, o modelo vê os títulos coletados até agora e propõe duas novas consultas sobre o que está faltando. O prompt final numera até doze fontes e define as regras de citação.

Quanto custa um relatório?

Seis pesquisas por pergunta com as configurações padrão: quatro na primeira rodada e duas na segunda. Com read em 3, isso dá seis créditos. Portanto, 25.000 pesquisas a US$ 41,25 cobre mais de 4.000 relatórios.

As chamadas ao modelo custam à parte na sua conta de LLM: três chamadas de planejamento e uma chamada longa de resposta por relatório. A chamada de resposta carrega até doze páginas de 5.000 caracteres, então diminua max_chars se seu modelo for caro.

Como faço para ir mais fundo?

Mude os números, não a estrutura:

  • Mais rodadas. rounds=4 deixa o modelo buscar mais dois conjuntos de lacunas.
  • Mais consultas por rodada. Aumente n na chamada de busca de lacunas de 2 para 4.
  • Fontes mais restritas. Adicione include_domains ao corpo da pesquisa para sites oficiais ou acadêmicos.
  • Apenas material recente. Adicione "time_range": "month" ou "topic": "news".
  • Mais páginas por consulta. read=5 lê cinco páginas, a 2 créditos por pesquisa.

Adicione uma regra de parada antes de aumentar os limites: encerre o loop quando uma rodada trouxer menos de duas fontes novas.

Como mantenho o agente seguro e educado?

Trate cada página como texto não confiável. O prompt final instrui o modelo a usar as fontes apenas como evidência; adicione uma linha explícita de que instruções dentro das fontes devem ser ignoradas. Nunca deixe uma fonte disparar uma chamada de ferramenta ou uma escrita de arquivo.

Do lado da web, Nosso leitor respeita o robots.txt: ele se identifica como LLMWebSearch, segue as regras que um site escreve para ele ou para todos os robôs e deixa de fora o conteúdo de qualquer página que não tem permissão para ler. Páginas que recusam acesso voltam sem conteúdo e o script simplesmente as ignora. Quando um site recusa o nosso leitor, o resultado volta sem conteúdo e com o status do site: nunca resolvemos CAPTCHAs, não entramos em contas nem contornamos um bloqueio ou um paywall.

O que pode dar errado?

Três coisas aparecem nos testes:

  • Consultas vagas. Se o plano for fraco, toda rodada encontra as mesmas páginas. Peça ao modelo consultas que usem nomes e datas específicos.
  • Poucas fontes com texto. Alguns tópicos ficam atrás de paywalls. Amplie as consultas ou permita mais resultados.
  • Prompts longos demais. Doze páginas longas podem exceder o contexto de um modelo pequeno. Diminua max_chars ou mantenha oito fontes.

Registre cada consulta e as URLs que ela retornou. Ler esse log é a forma mais rápida de melhorar o prompt do plano.

Agente de pesquisa profunda: perguntas comuns

Posso executar isso com um modelo local?

Sim, se o servidor local falar o formato chat-completions da OpenAI. Defina LLM_BASE_URL para o endereço dele e LLM_MODEL para o nome do modelo.

Posso transformar isso em uma ferramenta MCP?

Sim. Envolva research() em uma ferramenta MCP, ou dê ao seu agente a ferramenta de pesquisa simples da página MCP e deixe que ele mesmo execute o loop.

Por que não pedir uma resposta diretamente à API de pesquisa?

Porque LLMWebSearch não escreve respostas. A API retorna fontes, não uma resposta escrita: o seu próprio modelo lê as páginas, escreve a resposta e cita as URLs.

Como vejo quanto custou cada pesquisa?

Toda resposta inclui credits_used, e GET https://llmwebsearch.com/api/v1/credits mostra seu saldo restante sem custo.

A partir de US$ 1,20/1K pesquisas · sem KYC

Obtenha uma chave de API