Pular para o conteúdo principal
Agentes de pesquisa são úteis quando você quer mais do que um único resultado de busca ou uma resposta rápida de modelo. Um bom agente de pesquisa pode transformar um tópico amplo em queries de busca, coletar fontes, extrair as evidências importantes, fazer follow-up sobre lacunas e escrever um briefing citado que você pode inspecionar depois. Neste tutorial, construiremos um agente de pesquisa privado usando Python e a API Venice. Ao final, você terá um CLI que pode pesquisar um tópico, fazer scrape de páginas públicas para Markdown, sumarizar chunks de fontes, executar passos de pesquisa de follow-up cientes de lacunas e gerar um relatório citado com artefatos JSONL locais opcionais. Interessado na implementação completa do código? Confira o repositório no GitHub. Antes de continuarmos, você precisará de uma chave de API Venice:

O que vamos construir

A implementação de referência é um pequeno projeto Python com algumas partes claras: O fluxo se parece com isto: Pipeline do agente de pesquisa privado
  1. Pedir à Venice para gerar queries de busca diversas para o tópico.
  2. Pesquisar na web com um ou mais provedores.
  3. Deduplicar URLs antes de lê-las.
  4. Usar o endpoint de scrape da Venice para transformar cada página de origem pública em Markdown.
  5. Dividir páginas longas em chunks.
  6. Pedir à Venice para extrair evidências de cada chunk.
  7. Pedir à Venice para transformar evidências de chunks em notas de origem.
  8. Identificar lacunas de pesquisa e problemas de equilíbrio de origens antes de gerar queries de follow-up.
  9. Pedir à Venice para sintetizar o relatório final com citações no estilo de notas de rodapé.
Isso é “privado” no sentido prático de que o agente mantém a orquestração, notas de origem, artefatos e relatórios finais na sua máquina. A Venice lida com as chamadas de modelo e o scraping através de sua API. A implementação de referência padrão ainda envia queries de busca ao DuckDuckGo ou arXiv, então trate a escolha do provedor como parte do seu design de privacidade.

Configurando o projeto

O projeto de referência usa Python 3.13 e uv, mas o mesmo código funciona com um ambiente virtual normal também. Crie um novo projeto:
Instale as dependências:
Se preferir pip, crie um ambiente virtual e instale os mesmos pacotes:
Crie um arquivo .env para desenvolvimento local:
Usamos VENICE_MODEL para que você possa alterar o modelo sem editar código. A implementação de referência atualmente usa openai-gpt-55 como padrão, mas você pode trocá-lo por outro modelo de chat disponível na sua conta Venice.

Criando os modelos de dados

Antes de escrever a lógica do agente, definiremos os objetos que se movem pelo pipeline. Esses modelos mantêm o resto do código mais fácil de raciocinar porque cada fonte carrega proveniência: de onde veio, qual query a encontrou, quando foi recuperada e como foi dividida em chunks. Crie research_agent/models.py:
Os campos importantes aqui são canonical_url, content_hash e chunks. canonical_url permite ao agente evitar ler a mesma fonte repetidamente quando os resultados de busca diferem apenas por parâmetros de tracking ou fragmentos. content_hash ajuda a capturar páginas duplicadas mesmo quando vivem em URLs diferentes. chunks nos permite sumarizar páginas longas em pedaços menores em vez de perder evidência útil para limites de contexto. Adicione as funções helper abaixo das dataclasses:
O chunking é deliberadamente simples aqui: chunks de tamanho fixo de caracteres com overlap. Isso é suficiente para um agente de pesquisa demo porque o endpoint de scrape da Venice retorna Markdown, que geralmente é muito mais limpo que HTML cru. Para pesquisa em produção em documentos técnicos longos, você pode melhorar isso dividindo por headings, parágrafos ou contagem de tokens.

Construindo o cliente Venice

A seguir, criaremos um pequeno cliente Venice. Você poderia usar o SDK Python da OpenAI para chat completions porque a Venice é compatível com OpenAI, mas a implementação de referência usa httpx diretamente para que o mesmo cliente possa chamar o endpoint POST /augment/scrape da Venice. Crie research_agent/venice.py:
O helper from_env() mantém os segredos fora do seu código-fonte. Também torna o desenvolvimento local conveniente, porque python-dotenv pode carregar VENICE_API_KEY e VENICE_MODEL do .env. Agora adicione chat completions:
Para o relatório final, queremos usar streaming porque relatórios profundos podem levar significativamente mais tempo (porque produzirão muito mais texto). Isso pode causar problemas de timeout em requisições em que pode levar um tempo extremamente longo para produzir a saída final. Usando streaming, podemos eliminar esse problema e tornar a requisição mais resistente a falhas de timeout:
Depois adicione scraping:
O endpoint de scrape da Venice aceita uma URL publicamente acessível e retorna a página como Markdown. Isso significa que o modelo não precisa fazer parsing de HTML cru, e seus prompts de extração de fonte podem trabalhar com texto mais limpo. O helper restante lida com retries e parsing de resposta:
O repositório completo também inclui um helper robusto _post_chat_stream() que lê server-sent events de chat completions em streaming. Você pode começar sem streaming e adicioná-lo quando o restante do fluxo de pesquisa funcionar.

Adicionando provedores de busca

A camada de busca tem dois trabalhos: encontrar URLs de origem e buscar essas URLs através do scraper da Venice. A implementação de referência usa o endpoint HTML do DuckDuckGo para busca geral na web e a API Atom do arXiv para papers. Crie research_agent/web.py:
Agora adicione o DuckDuckGo:
E o arXiv:
A classe WebSearch coordena provedores e busca páginas:
A implementação de referência completa adiciona retries, atrasos de requisição por host e erros mais amigáveis. Vale a pena manter isso porque agentes de pesquisa passam muito tempo lidando com páginas que bloqueiam automação, redirecionam inesperadamente ou retornam erros transitórios. Adicione os pequenos helpers de provedor no final:

Escrevendo artefatos locais

Para workflows de pesquisa, a auditabilidade importa. Se o relatório final disser algo surpreendente, você deve ser capaz de inspecionar qual fonte levou a isso. Crie research_agent/artifacts.py:
Isso escreve um objeto JSON por linha, o que torna os artefatos fáceis de adicionar, inspecionar e processar com ferramentas de linha de comando depois.

Construindo o agente de pesquisa

Agora que temos Venice, busca, modelos e artefatos, podemos construir o agente em si. Crie research_agent/agent.py:
O system prompt é o guardrail comportamental central. Não queremos que o modelo produza um relatório impressionante a partir da memória. Queremos que ele use o material de origem e destaque incertezas quando a evidência for fraca. Também precisamos de duas dataclasses finais em models.py se você ainda não as adicionou:
A seguir, defina o ResearchAgent:
O método run() coordena os passos de pesquisa:
Os dois conjuntos seen_* são o que impedem o agente de desperdiçar tempo em fontes duplicadas. Dedup de URL captura links repetidos. Dedup por hash de conteúdo captura espelhos, posts sindicalizados e páginas que redirecionam para o mesmo conteúdo final.

Planejando buscas iniciais e de follow-up

A primeira chamada de modelo transforma o tópico em queries de busca:
Após cada passo de pesquisa, o agente atualizado faz um passo de análise de lacunas mais deliberado. Ele olha as notas atuais, conta clusters de origens por domínio, pergunta à Venice qual cobertura está faltando, escreve essas lacunas nos artefatos e depois usa as queries resultantes para o próximo passo. Loop de análise de lacunas Comece rastreando o equilíbrio de origens:
Isso dá ao agente uma maneira simples de notar a captura por cluster de origens. Se cada fonte está vindo de uma empresa, um framework ou um domínio, queries de follow-up devem deliberadamente ampliar o conjunto de fontes em vez de coletar mais do mesmo. Agora use essa informação de equilíbrio ao criar buscas de follow-up:
A implementação de referência mais recente envolve isso em _gap_follow_up_queries(), que pede à Venice para retornar registros de lacunas e queries:
Quando --artifacts está habilitado, esses registros são escritos em research_gaps.jsonl. Isso te dá uma trilha de auditoria útil para entender por que o agente buscou uma query de segundo passo em particular. O parser deve ser tolerante. Se o modelo retornar JSON malformado, o agente volta ao tópico original:
Esse padrão vale a pena usar em todo o código de agente: peça saída estruturada, faça parsing dela e forneça um fallback simples quando a saída não for utilizável.

Lendo e sumarizando fontes

Agora coletamos notas de origem. O agente busca cada query, busca cada resultado através do scrape da Venice, divide o Markdown em chunks e sumariza a evidência útil.
Falhas individuais de busca e fetch não devem parar toda a execução. A web pública é bagunçada. Algumas páginas bloqueiam scraping, algumas retornam PDFs, algumas estão fora do ar e algumas redirecionam para lugares inesperados. Um agente de pesquisa deve continuar se movendo e registrar o que falhou. Aqui está o método de leitura de fonte:
Para cada chunk de origem, peça à Venice por um resumo curto de evidências e citações exatas:
Depois reduza os resumos de chunks em uma nota de origem:
Essa sumarização em duas etapas é a parte que faz o agente parecer mais confiável que um script básico de “sumarize essas URLs”. O modelo lê chunks de origem primeiro, depois escreve uma nota em nível de origem a partir desses pedaços extraídos de evidência.

Escrevendo o relatório final

Quando o agente tem notas de origem, ele pode escrever o relatório. Comece com um escritor de relatório de uma passada:
A implementação de referência vai além para relatórios profundos: ela pede à Venice por um outline, esboça cada seção do relatório separadamente e depois pede um passo final de editor para montar o relatório terminado e converter IDs internos de origem em citações no estilo de notas de rodapé. Essa abordagem em estágios é útil quando você quer saída de pesquisa em forma longa porque um único prompt gigante geralmente comprime demais. Os prompts atualizados também empurram o relatório para uma pesquisa ampla e baseada em fontes, em vez de um guia de decisão fino. Se a base de fontes está enviesada para um cluster, o prompt do editor diz à Venice para reconhecer esse viés e evitar apresentá-lo como representativo de todo o campo. Adicione os helpers de digest:
Finalmente, adicione o registro de erros:
Neste ponto, o loop central de pesquisa está pronto.

Adicionando o CLI

Agora precisamos de um ponto de entrada de linha de comando. Crie main.py:
O CLI expõe os knobs que você de fato vai ajustar durante a pesquisa: Agora conecte tudo:
Isso nos dá um CLI de pesquisa local funcional.

Executando o agente

Execute um passo de pesquisa rápido:
Escreva o relatório em um arquivo Markdown:
Use mais fontes e múltiplos provedores:
Escolha o estilo do relatório final:
Use brief para um briefing conciso baseado em fontes, standard para uma pesquisa mais completa e deep para o fluxo em estágios outline/section/editor. Salve artefatos auditáveis:
Quando os artefatos estão habilitados, você verá arquivos como:
Esses arquivos são úteis quando você quer entender como o agente chegou a uma conclusão. Por exemplo, source_notes.jsonl mostra a evidência de origem sumarizada, research_gaps.jsonl mostra por que buscas de follow-up foram geradas e errors.jsonl mostra páginas que falharam durante busca, scraping ou sumarização.

Notas de privacidade e confiabilidade

Um agente de pesquisa toca vários sistemas, então ajuda ser preciso sobre o que vai para onde: Limites de dados do agente de pesquisa privado Se você quiser manter mais do caminho de busca dentro da Venice, pode adaptar a camada de provedor para chamar o endpoint POST /augment/search da Venice em vez de consultar o DuckDuckGo diretamente. A implementação de referência usa provedores públicos leves para que a demo permaneça fácil de executar e entender. Para confiabilidade, mantenha esses padrões conservadores:
  • Use retries para chamadas Venice e requisições web.
  • Adicione um pequeno --request-delay se estiver lendo muitas páginas do mesmo host.
  • Limite --max-sources para que tópicos amplos não rodem indefinidamente.
  • Salve --artifacts para relatórios importantes para poder auditar a saída final.
  • Trate o relatório como um briefing, não como verdade absoluta. Siga as citações até a fonte original quando a precisão importar.

Testando as peças

Você não precisa de requisições web reais ou chamadas Venice para testar a maior parte do sistema. O repo de referência usa classes Venice e web falsas para testar o loop de pesquisa, comportamento de dedup, artefatos e prompts de relatório. Um primeiro teste útil é a canonização de URL:
Depois teste que conteúdo duplicado é pulado:
Fakes tornam os testes de agente muito mais rápidos e menos instáveis. Você pode verificar a lógica de orquestração sem depender de resultados de busca ao vivo, condições de rede ou saída do modelo.

Benchmarking

Muitos provedores de IA agora têm seus próprios fluxos de pesquisa profunda, então o repo de referência inclui um benchmark simples contra a ferramenta Deep Research da Perplexity. Ambos os agentes foram solicitados a escrever um relatório sobre arquitetura de framework de agente de IA, e depois os relatórios gerados foram comitados no repositório do GitHub. Isso não pretende ser um benchmark formal. É uma maneira prática de inspecionar estrutura de relatório, cobertura de fontes, qualidade de citação e se o agente foca demais em um cluster de origem. Por isso também a implementação atualizada rastreia research_gaps.jsonl e o equilíbrio de origens antes das buscas de follow-up.

Estendendo este exemplo

Quando o agente baseline funcionar, aqui estão maneiras práticas de melhorá-lo:
  • Adicionar um provedor de busca Venice usando POST /augment/search.
  • Armazenar relatórios e artefatos em um pequeno banco SQLite em vez de arquivos JSONL.
  • Adicionar allowlists ou blocklists de origem para domínios de pesquisa confiáveis.
  • Adicionar suporte a PDF combinando scrape da Venice com parsing de documento para fontes que não expõem HTML limpo.
  • Adicionar um conjunto de avaliação de tópicos e tipos de fonte esperados para comparar a qualidade da pesquisa após mudanças de prompt.
  • Adicionar um passo de revisão que peça à Venice para encontrar alegações sem suporte no relatório final antes de salvá-lo.
O maior upgrade geralmente é uma melhor seleção de fontes. A geração de queries ajuda, mas você também pode melhorar a qualidade preferindo fontes primárias, documentos de padrões, docs oficiais, papers, changelogs e páginas de datasets em vez de resumos de baixo sinal.

Encerrando

Obrigado por ler! Espero que isso te ajude a construir um agente de pesquisa privado prático com Python e a API Venice. O padrão útil aqui não é só “pedir a um modelo para pesquisar algo”. É dividir a pesquisa em passos auditáveis: planejar buscas, coletar fontes, extrair evidências, escrever notas de origem, fazer follow-up em lacunas e sintetizar com citações. Mantendo esses passos explícitos, obtemos um workflow de pesquisa que é mais fácil de inspecionar, testar e melhorar ao longo do tempo.