Repensando a busca como geração de código
Evoluindo a busca de serviços monolíticos para primitivas programáveis para a era dos arneses de agentes.
A busca é uma primitiva central para os sistemas de IA. Os modelos de fronteira tornam-se mais capazes a cada mês, mas ainda precisam de acesso a conhecimento atualizado, preciso e bem curado do mundo em geral. A busca é a principal forma pela qual os sistemas de IA aproveitam esse conhecimento e, portanto, um componente fundamental de qualquer produto que precise tirar conclusões, realizar ações e executar trabalho no mundo real.
Acreditamos que os pipelines de busca tradicionais estão cada vez mais obsoletos na era dos agentes. A busca tradicional responde a consultas, mas os agentes de hoje concluem tarefas que podem assumir incontáveis formas. Essas tarefas exigem que os agentes definam estratégias de recuperação específicas de tarefas diretamente em seus arneses. No Perplexity Computer, vimos tarefas individuais invocarem centenas ou até milhares de operações de recuperação em poucos minutos: um fluxo de trabalho que é impossível para humanos, mas absolutamente natural para agentes.
Nesse mundo, a busca em si deve se tornar agêntica, com seus blocos de construção acessíveis diretamente como SDKs dentro do arnês do agente. Estamos introduzindo a Busca como Código (Search as Code - SaC) como a nova arquitetura de busca de referência da Perplexity.
Introdução
A pilha de busca da Perplexity atende a milhares de consultas a cada segundo em nossos aplicativos e na Plataforma de API. Em setembro de 2025, publicado a primeira visão geral arquitetônica de nossos sistemas de busca. A inovação constante nesses sistemas tem apoiado o lançamento de novas ofertas, como a Search API, a Agent API e o Computer, com loops de autoaperfeiçoamento otimizando a pilha de busca para atender melhor aos usuários a cada dia que passa.
Tradicionalmente, os sistemas de IA tratam a busca como um monólito: um modelo de IA emite uma consulta, o motor de busca executa seu pipeline predefinido e o modelo consome os resultados como contexto. Na maior parte, isso funcionou bem para atender às necessidades dos primeiros usuários de IA. Dada a relativa simplicidade de suas solicitações, não havia motivo para se preocupar exatamente sobre como o pipeline de busca foi projetado ou se a arquitetura do pipeline era ideal para a tarefa em questão. Os padrões eram considerados bons o suficiente, assim como as interfaces padrão (chamada de função e MCPs).
No entanto, hoje essa abordagem se torna mais obsoleta a cada mês que passa. Os usuários exigem muito mais do que análise de disparo único da IA. Eles esperam que os agentes concluam tarefas de ponta a ponta ao longo de horas ou até dias. Essas tarefas podem ser complexas, abertas e altamente variáveis em suas necessidades de informação, e as arquiteturas monolíticas estão cedendo sob o peso dessas demandas.
O principal gargalo é, em última análise, de controle. Os modelos de fronteira já são muito bons em raciocinar sobre contexto fixo. No entanto, os sistemas de IA mais poderosos exigem a capacidade de direcionar como esse contexto é recuperado, processado, agregado e renderizado para o modelo.
Os sistemas de busca tradicionais não foram projetados com esse grau de controlabilidade em mente. Afinal, não se pode esperar que os usuários humanos exerçam controle refinado sobre os detalhes internos do pipeline de busca, mesmo que isso fosse oferecido. Os primeiros modelos de IA podem controlar a busca apenas por meio de uma trajetória linear de chamadas de função e MCPs. Mas os modelos de fronteira de hoje, impulsionados por arneses de agentes capazes de código, podem exercer controle refinado sobre quaisquer primitivas computacionais imagináveis por meio de código de computador. Nossa tarefa passa a ser fornecer as primitivas corretas.
Para atender a essa necessidade, estamos introduzindo uma nova arquitetura de busca em nossos produtos: Busca como Código (Search as Code - SaC). Essa nova arquitetura capacita os modelos a alcançarem dentro da própria pilha de busca, em vez de apenas consumirem seus outputs finais. A ideia principal é direta: expomos os componentes da pilha de busca como primitivas dentro de um SDK. Para qualquer solicitação que precise de busca, um modelo monta essas primitivas sob demanda em um pipeline de recuperação adaptado a essa solicitação específica.
A montagem desse pipeline é feita por meio de geração e execução de código dentro de um sandbox seguro. Ao contrário de outras abordagens de geração de código para busca, nós simplesmente não inserimos uma API de busca tradicional dentro de um shell ou tempo de execução de linguagem. Em vez disso, projetamos cuidadosamente um SDK de Busca Agêntica que expõe os blocos de construção individuais da busca no nível mais atômico possível.
Munida desses blocos de construção, a SaC dá aos modelos controle direto sobre cada etapa de busca individual: recuperação, ranqueamento, filtragem, ramificações, renderização e muito mais. Ela também dá ao modelo acesso eficiente ao estado intermediário, como listas de candidatos e sinais de ranqueamento. Juntas, essas alavancas gêmeas de controle e legibilidade permitem que os agentes projetem pipelines de busca personalizados que abrangem milhares de operações de recuperação, otimizem esses pipelines em tempo de execução e consumam apenas as informações mais úteis como contexto do modelo.
Este artigo descreve a motivação, o design e a implementação da SaC, juntamente com resultados empíricos em benchmarks novos e existentes. A SaC estabelece uma nova fronteira de custo-desempenho para a busca agêntica, e estamos animados para compartilhá-la com nossos usuários e com a comunidade de IA em geral.
A Rigidez da Busca Tradicional
Os primeiros motores de busca do mundo foram criados para usuários humanos. Esses usuários passaram a esperar uma experiência previsível, tipicamente consistindo em um número fixo de documentos ranqueados por relevância. Os usuários não queriam microgerenciar o processo de busca; eles queriam inserir uma consulta e encontrar um resultado útil.
Como resultado, os motores de busca voltados para humanos convergiram em uma arquitetura monolítica comum, voltada para a produção de páginas de resultados de motores de busca (SERPs) amigáveis para humanos contendo os principais n hits para uma consulta de entrada. Esse padrão impulsionou décadas de progresso na busca do consumidor. É rápido, familiar e altamente eficaz para a navegação humana.
Então vieram os LLMs, e os sistemas de IA também se tornaram consumidores de busca. A Perplexity foi pioneira nessa mudança com o lançamento do nosso motor de respostas em 2022. Desde então, nossos esforços de engenharia de busca têm se concentrado em como otimizar o valor dos resultados de busca para modelos de IA. Para construir a IA mais precisa e confiável do mundo, tivemos que projetar um sistema de busca focado em tornar cada token o mais denso possível em informações. As inovações resultantes em recuperação de subdocumentos, eficiência de contexto, compreensão semântica e outras áreas-chave levaram a melhorias dramáticas na capacidade dos sistemas de IA de recuperar e agir sobre as informações.
No entanto, mesmo os sistemas otimizados para IA herdaram em grande parte o mesmo contrato fundamental que os motores de busca tradicionais: aceitar uma consulta, executar um pipeline de busca predefinido, retornar um conjunto de resultados totalmente processado. Para solicitações simples, essa abordagem funciona bem. Mas para solicitações mais complexas, isso se torna um gargalo cada vez mais limitante que degrada o desempenho, a latência e o custo.
Modos de Falha da Rigidez
Os pipelines de busca tradicionais são projetados em torno de um único ponto de controle: os parâmetros de consulta. O motor de busca possui o resto do pipeline de acordo com sua lógica predefinida, e o modelo deve se adaptar a ele. Para o modelo, qualquer coisa a jusante dos parâmetros de consulta é rígida — a forma da computação real está fora do controle do modelo.
Esta é uma fronteira sensível quando o consumidor é um humano escaneando links. É uma fronteira ruim quando o consumidor é um modelo de IA tentando resolver tarefas intensivas em conhecimento em um loop fechado. Em nossa experiência, essa rigidez cria três modos de falha recorrentes:
Contexto bruto. Os modelos de IA são sensíveis à qualidade e à compacidade do contexto. Tanto a qualidade quanto a compacidade dependem muito da consulta, e os pipelines de busca monolíticos não são projetados para ter um desempenho ideal em todas as consultas. Por exemplo, se um modelo precisa de uma única informação altamente cirúrgica, mas só tem acesso a um endpoint de busca de ponta a ponta que prioriza o recall, usar esse endpoint introduzirá uma grande quantidade de informações irrelevantes no contexto do modelo. Por outro lado, se um modelo precisa de muitas informações que exigem diferentes estratégias de busca, ele pode ser forçado a invocar em série o mesmo pipeline subótimo para todas elas, resultando em custos crescentes e contexto barulhento.
Falha em aproveitar o conhecimento de domínio. Em muitos casos, o modelo pode ter conhecimento de domínio (a partir de seu treinamento, um Agent Skill, memória ou tokens anteriores na trajetória do LLM) que deve orientar a estratégia de busca. No entanto, uma interface de busca rígida impede que o modelo aproveite esse conhecimento. Por exemplo, o modelo pode perceber para uma solicitação específica que deve mesclar sinais lexicais e semânticos de uma maneira particular, priorizar certas fontes ou agregar resultados por uma chave específica. A menos que esses insights aconteçam de ser implementáveis através de parâmetros de consulta, o modelo não pode realmente agir sobre eles.
Fluxo de controle ineficiente e poluição de contexto. Muitos fluxos de trabalho de busca não são naturalmente seriais. Eles podem precisar de ramificações (fan-out) sobre variantes de consulta, busca paralela, desduplicação e outras operações que exigem fluxo de controle não linear e assíncrono. Forçar essas etapas por meio de turnos repetidos do modelo adiciona latência e torna o fluxo de trabalho mais difícil de otimizar. Também polui o contexto do modelo com estado intermediário barulhento que pode não ser útil para o raciocínio do modelo, resultando em pior desempenho e compactações mais frequentes.
Não havia muito o que fazer sobre esses desafios durante as eras de chamada de função e MCP da IA. Quando cada operação de busca requer sua própria viagem de ida e volta para a inferência de LLM, os desenvolvedores naturalmente preferem realizar o máximo possível nessa viagem. Isso significa pipelines de busca de ponta a ponta que retornam conjuntos de resultados totalmente processados para consumo direto por um modelo.
Como resultado, a maioria dos sistemas de busca voltados para IA hoje ainda opera sob esse contrato monolítico. No entanto, com o crescimento contínuo na inteligência dos modelos e nas demandas dos usuários, as deficiências desse contrato tornam-se mais pronunciadas. Os sistemas de IA mais avançados de hoje, construídos sobre arneses centrados em código, podem compor fluxos de trabalho específicos de tarefas que executam milhares de ações a cada minuto. Os sistemas de busca ainda precisam realizar totalmente esse potencial.
Há muito suspeitamos que a fronteira certa para a busca nativa de IA está mais abaixo na pilha. Os modelos não devem apenas chamar um motor de busca. Eles devem ser capazes de orquestrar as peças individuais da pilha de busca conforme a tarefa específica exige. Isso requer uma arquitetura fundamentalmente diferente.
Projetando uma Arquitetura de Busca Programável
A próxima geração de arquiteturas de busca dependerá de um princípio central: a busca deve ser nativamente programável por agentes de IA. Um agente não deve ser limitado a um conjunto de pipelines de busca preestabelecidos. Em vez disso, um agente deve ser capaz de construir o pipeline que a tarefa específica exige, usando blocos de construção componíveis projetados em diferentes níveis de abstração.
Nossa nova arquitetura Search as Code (SaC) incorpora esse princípio. Na SaC, nenhuma operação de recuperação é despachada por meio de uma chamada de função ou interface MCP. Todas as operações são, em vez disso, orquestradas por meio de código Python gerado pelo modelo. Para as necessidades de busca mais simples, esse código pode consistir em um punhado de solicitações para um endpoint de busca de alto nível. Mas para tarefas complexas, o código pode ser tão intrincado quanto necessário, envolvendo execução condicional, assincronia, paralelismo e chamadas para uma ampla gama de primitivas de baixo nível.
A SaC envolve três camadas fortemente acopladas:
Os Modelos servem como plano de controle. Eles raciocinam sobre a diretiva do usuário (ou agente pai), decompõem a diretiva em tarefas, decidem quais pipelines de recuperação e processamento são necessários para cada tarefa e geram código para implementar esses pipelines.
Os Sandboxes de computação fornecem computação determinística por meio de um tempo de execução de execução de código seguro. Eles fornecem uma tela para os modelos implementarem fluxo de controle, loteamento (batching), novas tentativas (retries), filtragem, junção (joining), agregação e outras operações determinísticas.
Nosso SDK de Busca Agêntica expõe a pilha de busca da Perplexity como primitivas componíveis. Ele fornece blocos de construção desde operações de recuperação de baixo nível até análise semântica de alto nível. O SDK está embutido nos tempos de execução de execução dos sandboxes, permitindo que os modelos orquestrem até milhares de operações dentro de um único turno de inferência. Abaixo, discutimos nossas decisões de design para cada camada.
O SDK de Busca Agêntica
O SDK de Busca Agêntica define os blocos de construção para a busca programável. É importante ressaltar que nosso SDK não é uma API de busca preexistente empacotada como uma biblioteca. Nos últimos meses, nossa equipe de engenharia reestruturou nossa pilha de busca em primitivas modulares e componíveis. Construímos o SDK de Busca Agêntica para fornecer acesso direto a essas primitivas, criando uma tela muito mais poderosa na qual o modelo pode orquestrar pipelines de recuperação específicos de tarefas.
Pipelines de busca de alto nível e de ponta a ponta ainda estão disponíveis dentro do SDK, mas não são mais a única opção. Em vez disso, eles servem como uma forma de atalho para padrões de busca comuns. O modelo é livre para usá-los ou ignorá-los conforme a tarefa exige.
Escolha do tempo de execução: Consideramos Python, Rust, TypeScript e Bash como o tempo de execução do SDK. Suspeitávamos que o Python seria o ajuste mais natural devido à sua onipresença e ecossistema de bibliotecas de processamento de dados. Testes internos confirmaram que este é o caso, e a versão do SDK que está sendo lançada hoje é baseada em Python. Esperamos reavaliar periodicamente a escolha do tempo de execução para garantir que ele continue a fornecer a melhor experiência de agente.
Melhoria contínua via auto-pesquisa (autoresearch): Também otimizamos a consumibilidade do SDK para LLMs de fronteira por meio de um loop iterativo de auto-pesquisa. Esse loop, executado continuamente ao longo de semanas, propõe e valida melhorias no SDK em relação a métricas como latência, qualidade de geração de código e desempenho geral da tarefa. O loop de auto-pesquisa já fez inúmeras alterações na estrutura e na estética do SDK, com ganhos significativos em todas as dimensões. Planejamos refinar ainda mais o SDK por meio de auto-pesquisa à medida que novos modelos de fronteira e componentes de busca surgirem.
Sandboxes
Os sandboxes fornecem ambientes seguros para definir e executar pipelines de SaC. Eles executam código gerado pelo modelo, fornecendo acesso ao SDK de Busca Agêntica para facilitar a interação com primitivas de busca individuais.
Fizemos investimentos significativos na otimização e no endurecimento (hardening) de nossos sandboxes, e o design de sistema abrangente deles merece um artigo próprio. Aqui, focamos na consideração de design mais relevante para a SaC: o gerenciamento de estados intermediários.
A SaC capacita os agentes a orquestrar pipelines complexos dentro de um único turno de inferência. No entanto, certos estados intermediários precisam ser transmitidos entre os turnos. Por exemplo, um modelo pode querer buscar alguns documentos no turno 1, inspecionar uma subamostra desses documentos no turno 2 para decidir o que fazer a seguir e, em seguida, desenvolver um pipeline de busca a jusante para investigar mais a fundo esses documentos do turno 3 em diante. Como discutido acima, passar estados intermediários através do espaço de tokens não é uma estratégia eficaz.
Consideramos duas abordagens para gerenciar estados intermediários entre os turnos:
Sistema de arquivos persistente + serde explícito: Os sandboxes podem expor sistemas de arquivos persistentes para os modelos usarem entre os turnos. Os modelos que desejam persistir o estado intermediário podem incluir uma etapa de serialização dentro do código gerado para um turno, juntamente com uma etapa de desserialização em um turno subsequente (seja para a própria inspeção dos modelos ou para uso a jusante). A abordagem do sistema de arquivos permite que os modelos controlem de forma direta e explícita como o estado intermediário é transmitido entre os turnos. Ela também garante a rastreabilidade ao impor a identificação e a persistência explícitas das informações usadas pelo modelo. Uma desvantagem é a sobrecarga de latência e contexto incorrita pela geração do código serde, embora funções utilitárias bem projetadas possam mitigar essa sobrecarga.
REPL: Como alternativa, um sandbox pode persistir o próprio tempo de execução em turnos em um ambiente estilo REPL. Isso permite que os modelos mantenham o estado intermediário na memória sem precisar serializá-lo, uma vez que as variáveis definidas ou modificadas em turnos anteriores podem simplesmente ser referenciadas por nome em turnos subsequentes. A abordagem REPL é mais eficiente em termos de tokens, pois evita a necessidade de gerar código serde. No entanto, a falta de uma etapa de serialização explícita pode prejudicar o desempenho a jusante por motivos familiares a qualquer pessoa que tenha trabalhado com um notebook Jupyter de 100 células: à medida que o namespace de variáveis se torna desordenado, fica mais difícil acompanhar o que exatamente é persistido entre os turnos e por quê.
Testamos ambas as abordagens e descobrimos que, embora tenham um desempenho semelhante no uso comum, o serde baseado em sistema de arquivos oferece melhor confiabilidade em trajetórias particularmente longas. Portanto, adotamos o serde baseado em sistema de arquivos como nossa solução. Lembramos que exigir que os modelos transmitam o estado de forma declarativa em vez de implícita os ajuda a gerenciar esse estado com mais eficácia. Esta é uma constatação preliminar e continuaremos a iterar em ambas as abordagens.
Modelos
Os modelos que alimentam os arneses de agentes servem como o plano de controle da SaC: montando dinamicamente pipelines de busca a partir dos blocos de construção do SDK de Busca Agêntica para atender às necessidades de cada tarefa, despachando esses pipelines como código para execução no sandbox.
A Perplexity emprega uma variedade de modelos em nossos arneses de agentes, e descobrimos que os modelos de fronteira mais recentes são bastante eficazes em geral na geração de código de uso geral. O principal desafio é induzir a geração de código eficaz especificamente para o SDK de Busca Agêntica. Ou seja, como podemos fazer com que os modelos entrelaçuem efetivamente os blocos de construção do nosso SDK em pipelines otimizados para tarefas?
Ao contrário da biblioteca padrão de uma linguagem, é improvável que um SDK construído sob medida seja representado em dados de pré-treinamento. Mesmo com as melhorias de consumibilidade do SDK provenientes da auto-pesquisa, muitos modelos ainda são treinados para interagir com sistemas de busca por meio de chamadas de função e invocação direta de MCP. É improvável que esses modelos manejem com maestria o SDK apenas com código-fonte e documentos gerados automaticamente.
Para resolver esse desafio, desenvolvemos Agent Skills altamente ajustadas para ensinar os modelos a aproveitar efetivamente o nosso SDK. As versões iniciais foram desenvolvidas de acordo com os princípios de design da Perplexity para Skills e, em seguida, otimizadas por meio de um loop dedicado de auto-pesquisa focado nas mesmas métricas usadas na otimização do SDK. Também limitamos o tamanho das Skills para nos proteger contra o inchaço de contexto, e nossas versões finais têm menos de 2000 tokens em seus arquivos raiz SKILL.md.
As Skills otimizadas vão além de listar os blocos de construção disponíveis do SDK (algo que pode ser facilmente obtido por meio de reflexão em tempo de execução). A maior parte dos tokens é gasta fornecendo orientações concisas e generalizáveis e exemplos de poucas tomadas (few-shot) para compor esses blocos em padrões complexos. Munidos dessas Skills, observamos os modelos aproveitarem efetivamente o SDK para orquestrar pipelines de busca que escalam para milhares de operações discretas.
Código como Orquestrador e Preenchedor de Lacunas
Ao combinar essas camadas, a SaC altera a relação entre os modelos e a pilha de busca. Em sistemas de busca de pipeline fixo, o modelo fica acima da busca e interage com ela por meio de uma interface de chamada serial estreita. Na SaC, o modelo torna-se um participante ativo na orquestração do próprio processo de busca. Todos os elementos da pilha de busca tornam-se diretamente programáveis pelo modelo, com o sandbox e o SDK de Busca Agêntica fornecendo as interfaces necessárias para esses elementos.
Mas e quanto aos recursos que não existem nativamente? O código é um meio poderoso para orquestrar recursos preexistentes. No entanto, o poder do código vai além da orquestração. Ele também pode servir como um preenchedor de lacunas para recursos que não estão presentes na pilha de busca ou no SDK. Os agentes se beneficiam da parcimônia, e seria ineficiente para o SDK cobrir todas as operações potenciais com uma função dedicada. Em vez disso, o SDK fornece as primitivas mais fundamentais, e o modelo pode construir quaisquer componentes adicionais em tempo de execução com código.
Considere, por exemplo, uma expressão regular (regex) complexa que não é implementável de forma eficiente por meio da própria sintaxe de consulta do sistema de busca. Sem recursos de codificação, o modelo seria forçado a gerar sua melhor aproximação, fazer uma consulta e realizar filtragem baseada em espaço de tokens em um conjunto de resultados muito barulhento. Com a SaC, o modelo pode, em vez disso, gerar um programa que faz chamadas paralelas ao SDK para coletar um superconjunto do conjunto de resultados da regex desejada. Após a desduplicação por meio do SDK, o modelo pode escrever código adicional para restringir deterministicamente os resultados à regex exata. Desta forma, os agentes podem implementar recursos de busca personalizados sem inchar o SDK com sub-rotinas excessivamente específicas.
Estudo de Caso: Avisos de Fornecedores de CVE
Apresentamos um estudo de caso baseado em uma tarefa do mundo real em nosso pacote de testes. Esta tarefa pede a um agente que identifique e caracterize mais de 200 CVEs de alta gravidade de 2023–2025. Cada registro deve citar o aviso do próprio fornecedor afetado, nomear o produto e a versão de correção, e mostrar que a versão de correção está vinculada ao CVE específico.
A resposta da SaC obteve 100% de precisão, com o uso total de tokens caindo 85,1% em relação à linha de base sem SaC (de 288,7 mil tokens para 42,9 mil tokens). Os sistemas testados sem ser da Perplexity, discutidos com mais detalhes na Seção 4, pontuaram todos abaixo de 25%.
Apresentamos três blocos de código estilizados da trajetória para ilustrar como a programabilidade da SaC permite que o modelo implemente estratégias eficazes.
# Part 1 of 3: fan out over official advisory formats.
templates = [
("Mozilla",
'site:mozilla.org/en-US/security/advisories/mfsa{year} '
'"CVE-{year}-" "Fixed in" "Impact high"'),
("Jenkins",
'site:jenkins.io/security/advisory/{year} '
'"CVE-{year}" "Severity" "High" "Fix"'),
("Chrome",
'site:chromereleases.googleblog.com/{year} '
'"High CVE-{year}" "Stable channel has been updated"'),
("Android",
'source.android.com/docs/security/bulletin/{year}-{month:02d}-01 '
'"High" "CVE-{year}"'),
...
]
queries = [
{"vendor": vendor, "query": pattern.format(year=year, month=month)}
for year in [2023, 2024, 2025]
for vendor, pattern in templates
for month in ([1] if "{month" not in pattern else range(1, 13))
]
seed_hits = sdk.search.web_many(queries, limit_per_query=8, concurrency=12)
pages = [
{"vendor": q["vendor"], "url": h.url, "text": join_result_fields(h)}
for q, hits in zip(queries, seed_hits)
for h in hits
if official_vendor_advisory(h.url, q["vendor"])
]Este primeiro bloco é pura orquestração. O programa gerado começa codificando a regra de classe de origem diretamente no plano de consulta: apenas os formatos de aviso de propriedade do fornecedor são relevantes. Fontes que não são de fornecedores, incluindo NVD, MITRE, CVE Details, notícias, páginas do CERT e bancos de dados de terceiros, estão estruturalmente fora do escopo. As restrições de frase exata também direcionam a busca para páginas cujo texto indexado já contém os detalhes precisos de CVE necessários a jusante.
# Part 2 of 3: synthesize refinements for sparse vendor-years.
coverage = summarize(pages, by=["vendor", "year", "url_kind"])
prompt = """
Goal: 230+ high or critical CVEs from official vendor advisories.
Avoid aggregators, CERTs, news, NVD, MITRE, and CVE databases.
Current coverage:
{coverage}
Suggest more site-scoped exact-phrase queries for sparse vendor-years.
Prefer per-advisory pages over archive or month-index pages.
Return JSON lines with vendor and query.
""".format(coverage=coverage)
raw = query_llm(prompt)
expanded_queries = [
row for row in parse_jsonl(raw)
if official_scope(row["query"]) and mentions_cve_year(row["query"])
]
expanded_hits = sdk.search.web_many(
unique(expanded_queries),
limit_per_query=8,
concurrency=12,
)O segundo bloco usa um LLM como uma sub-rotina de planejamento intermediária. O código resume quais pares de fornecedor-ano estão produzindo páginas candidatas suficientes, pede refinamentos direcionados e valida cada consulta proposta antes da execução. Isso preserva padrões úteis da trajetória, como sondas de frase exata com escopo de site e preenchimento adaptativo (backfilling), sem codificar de forma rígida um rastreador de avisos de CVE personalizado no SDK.
# Part 3 of 3: verify CVE-to-version binding.
all_hits = dedupe_by_url(flatten(seed_hits) + flatten(expanded_hits))
items = [
{"url": h.url, "vendor_hint": infer_vendor(h.url),
"text": join_result_fields(h)}
for h in all_hits
if official_vendor_advisory(h.url, infer_vendor(h.url))
]
verified = sdk.llm.extract_many(
items,
instruction=(
"Keep only vendor advisories where the page ties a high or critical "
"CVE to a specific fixed version, build, patch, or security level."
),
schema={
"matches": bool,
"cve": str,
"vendor": str,
"product": str,
"fix_version": str,
"severity": str,
"source_url": str,
"evidence": str,
"version_bound_to_cve": bool,
"confidence": float,
},
)
records = [
to_cve_record(x) for x in verified
if x.matches and x.version_bound_to_cve
if high_or_critical(x.severity) and x.confidence > 0.75
]
records = dedupe_by(records, key="cve")O bloco final é um verificador de resultados cuja lógica é inteiramente definida pelo agente por meio de geração de código. Embora as sub-rotinas de busca possam encontrar páginas de aviso plausíveis, a tarefa exige uma relação mais estrita: o aviso deve vincular um CVE a um produto afetado e uma versão de correção em texto de autoria do fornecedor. O esquema torna essa relação explícita, para que o código a jusante possa desduplicar por CVE, rejeitar URLs de agregadores, descartar evidências fracas de versão e continuar preenchendo até que o piso de contagem de registros seja atingido.
Resultados da Avaliação
Avaliamos a eficácia da SaC em um conjunto abrangente de benchmarks, focando tanto no desempenho absoluto quanto na fronteira de custo-desempenho.
Benchmarks e Sistemas
Nosso pacote de benchmark compreende cinco benchmarks no total, projetados para estressar fluxos de trabalho de IA dependentes de busca em uma variedade de domínios, formatos de tarefas e níveis de complexidade. Usamos quatro benchmarks preexistentes: DeepSearchQA (DSQA), BrowseComp, Humanity's Last Exam (HLE) e WideSearch. Para os três primeiros benchmarks (DSQA, BrowseComp e HLE), relatamos a precisão como a principal métrica (topline). Para o WideSearch, relatamos a pontuação F1 por linha.
Também usamos o recém-desenvolvido benchmark WANDR, que se concentra em tarefas difíceis de “pesquisa ampla” (wide research) que exigem cuidadosa orquestração de busca, computação e raciocínio de modelo. O WANDR é inspirado nas tarefas profissionais intensivas em conhecimento que o Perplexity Computer lida para os usuários. Ele itera sobre o WideSearch e benchmarks semelhantes, mas enfatiza tarefas e estruturas de tarefas mais complexas. Publicaremos o benchmark WANDR nas próximas semanas.
Avaliamos cinco sistemas baseados em agentes. Consideramos execuções individuais em vez de pontuações de “melhor de N” para isolar o desempenho da arquitetura subjacente em vez dos benefícios da paralelização. A configuração de cada sistema é descrita abaixo:
Perplexity (SaC): Avaliamos a arquitetura SaC na Agent API de produção da Perplexity. O GPT 5.5 (alto raciocínio) serve como o modelo subjacente.
OpenAI: Avaliamos a OpenAI Responses API com a busca (web_search) e o tempo de execução Python (code_interpreter) ativados. O GPT 5.5 (alto raciocínio) serve como o modelo subjacente.
Anthropic: Avaliamos os Agentes Gerenciados da Anthropic com o conjunto de ferramentas de agente 20260401 e comandos permitidos automaticamente. O Opus 4.7 (alto raciocínio) serve como o modelo subjacente.
Exa: Avaliamos o Exa Agent por meio da API de produção, com o esforço definido como alto.
Parallel: Avaliamos as Tarefas Paralelas por meio da API de produção, com o processador definido como ultra4x.
Desempenho Comparativo
A Tabela 1 relata as pontuações de benchmark para cada sistema. A SaC supera todos os outros sistemas em quatro dos cinco benchmarks. No benchmark restante (HLE), a SaC está essencialmente empatada em primeiro lugar com as Respostas da OpenAI. A Figura 2 da Introdução visualiza essas pontuações em forma gráfica.
Benchmark | Perplexity (SaC) | OpenAI | Anthropic | Exa | Parallel |
DSQA | 0,871 | 0,733 | 0,815 | 0,530 | 0,810 |
BrowseComp | 0,805 | 0,720 | 0,598 | 0,380 | 0,560 |
HLE | 0,612 | 0,614 | 0,566 | 0,387 | 0,515 |
WideSearch | 0,651 | 0,522 | 0,590 | 0,471 | 0,584 |
WANDR | 0,386 | 0,130 | 0,152 | 0,057 | 0,126 |
Tabela 1 | Pontuações de benchmark para cada sistema avaliado. A melhor pontuação por linha está em negrito.
Embora a SaC alcance desempenho de ponta em todo o conjunto de benchmarks, sua vantagem é particularmente pronunciada no WANDR. A Figura 5 detalha as pontuações do WANDR, mostrando que a implementação de SaC da Perplexity supera o segundo melhor sistema por um fator de 2,5×. Apesar dessa margem ampla, o WANDR permanece insaturado e se mostra desafiador até mesmo para a SaC. Acreditamos que os fluxos de trabalho de busca complexos e altamente horizontais exigidos pelas tarefas do WANDR exigirão avanços adicionais na pesquisa e na engenharia de busca para alcançar consistentemente alto desempenho.
Finalmente, medimos os ganhos relativos da SaC versus um pipeline de busca mais tradicional que aproveita a mesma infraestrutura de busca da Perplexity. A Figura 6 relata a diferença de pontuação entre as arquiteturas SaC e não-SaC em cada benchmark. Em termos gerais, a SaC fornece um impulso substancial no desempenho, com o maior ganho absoluto no DSQA (+19,77 pp, 29%) e o maior ganho relativo no WANDR (+12,00 pp, 45%).
Fronteira de Custo-Desempenho
Na prática, os usuários se importam com o desempenho em relação ao custo. Portanto, avaliamos a fronteira de custo-desempenho no DSQA e no WideSearch. Medimos o custo e o desempenho da SaC em níveis de raciocínio de modelo baixo, médio e alto, juntamente com os outros sistemas. As Figuras 7 e 8 plotam a pontuação do benchmark em relação ao preço por tarefa, com o eixo x invertido para que os pontos mais à direita sejam mais baratos e os pontos mais altos representem melhor desempenho.
No DSQA, todas as três configurações de SaC estão na fronteira superior direita. A configuração de baixo raciocínio é mais barata do que todos os outros sistemas, enquanto tem melhor desempenho do que dois deles. A configuração de raciocínio médio supera todos os sistemas não-SaC por menos de US$ 1 por tarefa. A configuração de alto raciocínio alcança o desempenho máximo com um custo competitivo.
O WideSearch mostra uma fronteira de formato semelhante. Assim como no DSQA, a configuração de baixo raciocínio atinge desempenho competitivo a um custo menor do que todos os sistemas não-SaC, enquanto o raciocínio médio e alto superam os sistemas não-SaC no desempenho da tarefa.
Rumo a uma Nova Arquitetura de Computação
A Busca como Código reflete uma mudança mais ampla no design de software. Por décadas, os sistemas de software foram organizados em torno de instruções determinísticas executadas por tempos de execução tradicionais em CPUs. Os modelos de fronteira introduzem uma nova forma de computação: raciocínio em espaço de tokens que pode seguir e gerar instruções. Os sistemas computacionais mais capazes combinarão essas duas formas de computação em vez de escolher entre elas.
A busca é um campo de testes natural para esta arquitetura híbrida. Os modelos são bem adequados para decidir quais evidências são necessárias e como a incerteza deve ser resolvida. Tempos de execução determinísticos são bem adequados para processamento em lote, paralelismo, filtragem, ranqueamento e agregação. A infraestrutura de busca serve como uma camada de E/S universal, fornecendo ao tempo de execução ganchos úteis para as informações do mundo que podem sustentar milhares de operações por minuto. Quando essas peças são integradas, o sistema resultante é muito mais poderoso e eficiente na realização de tarefas do mundo real.
Todas as partes desta arquitetura são necessárias para desbloquear esses recursos. Sem modelos inteligentes, o sistema não pode raciocinar sobre a estratégia de busca. Sem sandboxes, os modelos são forçados a E/S serial e processamento ineficiente em espaço de tokens. E sem uma pilha de busca atomizada, o modelo não tem nada para orquestrar. A SaC funciona porque o raciocínio, a computação determinística e a E/S são projetados conjuntamente para acentuar os pontos fortes de cada camada.
Esse co-design pode ser levado ainda mais longe por meio do desenvolvimento de loops de melhoria contínua. Por exemplo, o SDK de Busca Agêntica e as SaC Agent Skills podem ser otimizados conjuntamente em um loop de auto-pesquisa comum. De forma mais ambiciosa, os modelos podem ser treinado para tirar proveito de primitivas de busca de baixo nível expostas como um SDK. Pode-se até tentar co-evoluir o design do SDK durante o próprio processo de treinamento do modelo. Esperamos buscar estratégias de co-design mais agressivas em trabalhos futuros.
Construímos a SaC para permitir que os modelos controlem o processo de busca, em vez de apenas consumirem seus resultados. Nossos resultados provam o poder desse controle: a SaC avança tanto o desempenho absoluto quanto a fronteira de custo-desempenho em benchmarks de agentes intensivos em conhecimento. Estamos animados para trazer os recursos da SaC para nossos usuários, começando hoje com o Perplexity Computer e a Agent API. Continuaremos a otimizar a arquitetura SaC em todas as camadas da pilha para garantir que nossos usuários (e os agentes que os atendem) tenham os recursos de busca mais poderosos e eficientes possíveis.
Citação
@online{perplexity2026RethinkingSearchAsCodeGeneration,
author = {{Perplexity} and Denis Bykov and Aleksandr Nikolenko and Artur Zayats and Maksim Gaiduk and Vitalii Polshkov and Akshay Nair and James Liounis and Kirill Priemko and Ryan Buchmayer and Phi Hoang and Jerry Ma},
title = {{Rethinking search as code generation}},
date = {2026-06-01},
url = {https://perplexity.coolkeypoint.com/hub/blog/rethinking-search-as-code-generation}
}