<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[IA agêntica - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[IA agêntica - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/pt/search-labs/blog/category/agentic-ai</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/blog/category/agentic-ai</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/category/agentic-ai.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Wed, 23 Sep 2026 08:37:59 GMT</lastBuildDate>
  <item>
    <title><![CDATA[137.000 pessoas, zero decisões humanas: resposta a desastres baseada em agentes com o Elasticsearch]]></title>
    <description><![CDATA[Descubra como uma regra de detecção do Kibana, um fluxo de trabalho e um agente de IA realocaram automaticamente 137.000 militares em sete instalações quando um furacão atingiu a região, sem a necessidade de um despachante.]]></description>
    <content:encoded><![CDATA[<p>A Elastic acabou de coordenar a evacuação automatizada de 137.000 militares em sete instalações, sem nenhuma intervenção humana. Um furacão de categoria 4 atinge a costa de Hampton Roads. O enriquecimento geoespacial do Elasticsearch identifica todas as instalações na zona de impacto no momento da indexação. Uma regra de detecção do Kibana dispara. Um fluxo de trabalho inicia uma conversa com o agente de IA. O agente analisa a capacidade, a distância e a compatibilidade entre os ramos e, em seguida, envia 16 notificações de evacuação e recebimento em uma única etapa. Do evento bruto do GDACS à ação coordenada, automaticamente.</p><p>Todos os anos, os desastres naturais forçam gestores de emergência, comandantes militares e autoridades de segurança pública a tomar decisões de alto risco em prazos reduzidos. Essas decisões tradicionalmente dependem de árvores de chamadas, planilhas e conhecimento institucional distribuído entre dezenas de pessoas. A sobrecarga de coordenação por si só consome um tempo precioso.</p><p>Este post demonstra como a Elastic pode viabilizar um sistema de coordenação responsivo e baseado em agentes para resposta a desastres que detecta uma ameaça, avalia a logística e toma medidas automaticamente. Para tornar isso concreto, criamos uma simulação: um furacão fictício de Categoria 4 que ameaça a costa de Hampton Roads aciona o realojamento automatizado de mais de 137.000 pessoas em sete instalações militares.</p><p><strong>Aviso:</strong> <strong>Este é um cenário totalmente fictício criado para fins de demonstração. </strong>O furacão ELARA-26 não existe. Os locais das instalações são baseados em dados geográficos reais e disponíveis publicamente (o conjunto de dados Military Installations, Ranges, and Training Areas [MIRTA] do Departamento de Defesa dos EUA [DoD]), mas todos os dados operacionais, como contagem de pessoal, capacidade de alojamento, ativos, e-mails de contato e perfis de missão, são totalmente fictícios. Nada nesta demonstração reflete prontidão militar, capacidade ou procedimentos operacionais reais.</p><h2>Por que a resposta automatizada a desastres requer coordenação geoespacial e agêntica</h2><p>Quando um desastre natural ameaça a infraestrutura crítica, o desafio de coordenação é imediato:</p><ul><li><p>Quais instalações estão na zona de impacto?</p></li><li><p>Quantas pessoas precisam se deslocar?</p></li><li><p>Para onde eles podem ir, e essas instalações têm capacidade?</p></li><li><p>Quem precisa ser notificado agora?</p></li></ul><p>Essas perguntas não esperam. Nem as respostas deveriam.</p><h2>Implantar o pipeline: pré-requisitos e configuração</h2><p>Siga as instruções <a href="https://github.com/tehbooom/elastic_natural_disaster/blob/main/README.md">aqui no repositório de exemplo</a> para implantar um cluster local da Elastic com o Elastic Inference Service (EIS) via <a href="https://www.elastic.co/docs/explore-analyze/elastic-inference/connect-self-managed-cluster-to-eis#set-up-eis-with-cloud-connect">Cloud Connect</a>.</p><h2>Como funciona o pipeline agêntico de resposta a desastres do Elasticsearch</h2><p>O pipeline tem sete camadas que trabalham juntas de ponta a ponta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf09bfae87ab35bec/6a4693ef31bdbbe3ef8b33ae/61814cddea0409162fb057c2113e0a496c105238-1999x275.png" alt="Pipeline flowchart Alt text: Horizontal flowchart with seven labeled boxes connected by arrows: GDACS feed, ingest pipeline, enrich (geo_shape), detection rule, workflow, AI agent, and email." /><ol><li><p><strong>Ingestão de dados:</strong> eventos de desastre do Global Disaster Alert and Coordination System (GDACS) enviados para o Elasticsearch</p></li><li><p>P<strong>ipeline de ingestão</strong>: GeoJSON é ingerido e normalizado para o Elastic Common Schema (ECS).</p></li><li><p><strong>Enriquecimento geoespacial:</strong> O polígono da área afetada pelo evento é comparado aos limites indexados de instalações militares.</p></li><li><p><strong>Alerting:</strong> Uma regra de detecção do Kibana é acionada quando um desastre afeta qualquer instalação.</p></li><li><p><strong>Automação de fluxo de trabalho:</strong> O alerta aciona um fluxo de trabalho do Kibana que inicia uma conversa com um agente de IA.</p></li><li><p><strong>Raciocínio da IA:</strong> o agente analisa as instalações afetadas, seus ativos e as instalações de apoio mais próximas para determinar a realocação de todos os ativos e do pessoal.</p></li><li><p><strong>Notificações por e-mail</strong>: o agente envia e-mails para todos os destinatários referentes à entrada e saída de pessoal e/ou ativos.</p></li></ol><p>Vamos examinar cada camada.</p><h2>Etapa 1: indexação de instalações militares com limites geográficos</h2><p>A base é o conjunto de dados DoD MIRTA de <a href="https://source.coop/seerai/hifld/military-installations-ranges-and-training-areas-mirta-dod-sites---boundaries">source.coop/seerai/hifld</a>. Este conjunto de dados fornece um geo_shape do tipo Point para cada instalação; coordenadas de centroide em vez de polígonos de limites completos.</p><p>Cada documento de instalação no índice mitra-facilities é enriquecido com dados de perfil operacional (todos fictícios), além do que o MIRTA fornece:</p>{
  "entity_name": "Naval Station Norfolk",
  "branch_of_service": "Navy",
  "mission_function_type": "fleet_support",
  "personnel_count": 50000,
  "housing_capacity": 55000,
  "temporary_housing_capacity": 10000,
  "logistics_capabilities": ["fuel", "airlift", "sealift", "medical"],
  "available_assets": [
    { "type": "helicopters", "count": 24 },
    { "type": "transport_vehicles", "count": 150 }
  ],
  "contact_email": "norfolk.ops@navy.mil.gov.fake",
  "operational_status": "act",
  "is_joint_base": false,
  "entity_geo_location": { "type": "polygon", "coordinates": [...] }
}<p>Esse índice rico é o que permite ao agente de IA tomar decisões inteligentes de alocação; não apenas "aqui estão as bases próximas," mas "aqui estão bases com capacidade de alojamento disponível, tipos de missão compatíveis e a logística para receber os ativos que chegam."</p><h2>Etapa 2: ingerindo e normalizando eventos do GDACS</h2><p>O GDACS publica GeoJSON em tempo real para terremotos, ciclones tropicais, inundações, incêndios florestais, vulcões e secas. Ingerimos esse feed em um fluxo de dados (logs-gdacs.events-*) usando um pipeline de ingestão personalizado que normaliza o GeoJSON bruto para campos do ECS.</p><p>O pipeline de ingestão do GDACS faz várias coisas que valem a pena notar:</p><p><strong>Extração de geometria:</strong> O centróide é armazenado como um geo_point para exibição no mapa, e o polígono de impacto é armazenado como um geo_shape em gdacs.affected_area, que é o campo usado posteriormente para consultas de interseção.</p><p><strong>Normalização da gravidade:</strong> cada tipo de desastre tem uma escala de gravidade diferente. Um ciclone tropical é medido pela velocidade do vento em km/h; um terremoto, pela magnitude Richter. O pipeline mapeia todos eles para uma pontuação normalizada de 0–100:</p>// Trecho de Painless do pipeline de ingestão
if (type == 'TC') {
  norm = Math.min(100.0, Math.max(0.0, (val - 40.0) / 2.6));
} else if (type == 'EQ') {
  norm = Math.min(100.0, Math.max(0.0, (val - 4.0) * 20.0));
}<p>A pontuação de gravidade normalizada é então mapeada para um rótulo severity_level (low, medium, high, critical) usado para o mapeamento de gravidade do alerta na regra de detecção.</p><p><strong>Alinhamento ao ECS:</strong> event.kind: alert, event.category: threat, registros de data e hora mapeados para event.start/event.end, e um _id estável baseado em fingerprint para desduplicação.</p><h2>Passo 3: enriquecimento geoespacial: encontrar instalações afetadas no momento da indexação</h2><p>A política enrich geo_match do Elasticsearch compara o polígono do desastre com todos os limites de instalação no momento da indexação, sem a necessidade de uma junção no momento da consulta. Em vez de consultar no momento da busca, usamos um <strong>processador enrich</strong> no pipeline de ingestão para comparar o polígono de impacto do desastre com todos os limites de instalação <em>à medida que o documento é indexado</em>.</p><p>A política de enriquecimento é uma política geo_match:</p>{
  "geo_match": {
    "indices": "mitra-facilities",
    "match_field": "entity_geo_location",
    "enrich_fields": [
      "entity_name",
      "entity_type",
      "entity_station_number",
      "entity_geo_city_name",
      "entity_geo_region_name"
    ]
  }
}<p>O processador é executado no final do pipeline de ingestão:</p>{
  "enrich": {
    "policy_name": "facilities-geo",
    "field": "gdacs.affected_area",
    "target_field": "affected_facilities",
    "shape_relation": "INTERSECTS",
    "max_matches": 128
  }
}<p>O INTERSECTS captura qualquer instalação cujo limite toque ou sobreponha o polígono do desastre e até mesmo interseções parciais. O resultado é que cada documento de evento do GDACS é armazenado com um array aninhado affected_facilities que nos informa exatamente quais instalações estão na zona de impacto. Nenhuma consulta de junção é necessária.</p><h2>Etapa 4: regra de detecção: alerta sobre impacto nas instalações</h2><p>Uma regra de detecção do Kibana monitora o fluxo de dados logs-gdacs.events-* e é disparada quando um evento do GDACS tiver sido enriquecido com pelo menos uma instalação afetada:</p>Consulta: affected_facilities: { entity_name: * }<p>A regra é executada em uma programação de hora em hora (abrangendo uma janela de now-1h a now) e usa o mapeamento dinâmico de gravidade; o campo gdacs.severity_level calculado pelo pipeline de ingestão determina automaticamente a gravidade do alerta.</p><p>A gravidade do alerta também determina a pontuação de risco por meio do mapeamento de campos:</p>"risk_score_mapping": [
  {
    "field": "gdacs.normalized_severity",
    "operator": "equals",
    "value": ""
  }
]<p>Quando a regra dispara, ela passa todo o contexto do alerta, incluindo o array affected_facilities enriquecido com nomes, tipos e locais de instalação, para um fluxo de trabalho subsequente do Kibana.</p><h2>Etapa 5: Automação do fluxo de trabalho: conectando o alerta ao agente</h2><p>Os fluxos de trabalho do Kibana cuidam da transição da detecção para a resposta. O fluxo de trabalho de resposta a desastres naturais é acionado pelo alerta:</p>triggers:
  - type: alert
steps:
  - name: start_convo
    type: kibana.request
    with:
      method: "POST"
      path: "/api/agent_builder/converse"
      body:
        agent_id: "mitra.response"
        input: "Novo alerta de desastre natural: {{ event.alerts | json }}"<p>Toda a carga útil do alerta (tipo de desastre, gravidade, área afetada e a lista de instalações impactadas) é encaminhada ao agente de IA como contexto inicial. O agente cuida do restante.</p><h2>Etapa 6: o agente de IA: dos dados à ação coordenada</h2><p>O agente mitra.response recebe o payload completo do alerta e, em um único loop agêntico, avalia o escopo, localiza instalações receptoras, aloca pessoal e envia notificações de evacuação e recebimento, tudo sem intervenção humana.</p><p>O agente tem duas ferramentas disponíveis:</p><ul><li><p><strong>mitra.nearest_facility</strong>consulta o índice mitra-facilities usando uma consulta geo_shape, classificada por distância de uma determinada coordenada, retornando até 50 instalações ativas próximas com capacidade disponível.</p></li><li><p><strong>mitra.send_email</strong> itera sobre um array JSON de objetos de instalações e envia notificações formatadas de evacuação ou recebimento.</p></li></ul><p>O conjunto de instruções do agente define um fluxo de trabalho claro:</p><ol><li><p><strong>Avalie a situação.</strong> Analise o alerta, identifique as instalações afetadas e determine a abrangência do desastre.</p></li><li><p><strong>Faça um inventário do que precisa ser movido.</strong> Contagem de pessoal, ativos críticos, requisitos de alojamento por instalação.</p></li><li><p><strong>Encontre as instalações de destino.</strong> Chame mitra.nearest_facility para cada instalação afetada, filtrando as instalações que ainda estão na zona de perigo.</p></li><li><p><strong>Tome decisões de alocação.</strong> Analise soluções de instalação única em comparação com instalações múltiplas, compatibilidade entre ramos, capacidade de alojamento e suporte a ativos.</p></li><li><p><strong>Envie e-mails de coordenação.</strong> Envie ordens de evacuação para as instalações de origem e notificações de recebimento para as instalações receptoras.</p></li><li><p><strong>Gere um relatório de resumo. </strong>Gera um breve resumo de todas as instalações afetadas, do total de pessoas, dos ativos transferidos, das instalações de destino e de quaisquer preocupações para o chat para revisão.</p></li></ol><p>A lógica de alocação do agente segue restrições do mundo real: não exceder a capacidade de alojamento, preferir relocações do mesmo ramo quando possível, usar bases conjuntas para o excedente de diferentes ramos e priorizar a distância para minimizar o tempo de deslocamento.</p><h3>A ferramenta de instalação mais próxima</h3><p>A consulta do fluxo de trabalho subjacente usa geo_shape com um filtro circle e classificação por _geo_distance:</p>"query": {
  "bool": {
    "filter": [
      {
        "geo_shape": {
          "entity_geo_location": {
            "shape": {
              "type": "circle",
              "coordinates": [{{ inputs.lon }}, {{ inputs.lat }}],
              "radius": "5000km"
            },
            "relation": "intersects"
          }
        }
      },
      { "term": { "operational_status.keyword": "act" } }
    ]
  }
},
"sort": [
  {
    "_geo_distance": {
      "entity_geo_point": { "lat": {{ inputs.lat }}, "lon": {{ inputs.lon }} },
      "order": "asc",
      "unit": "km"
    }
  }
],
"script_fields": {
  "available_capacity": {
    "script": {
      "source": "Math.max(0, doc['housing_capacity'].value - doc['personnel_count'].value)"
    }
  }
}<p>A capacidade disponível é calculada no momento da consulta por meio de um campo com script que calcula a capacidade de alojamento menos a contagem atual de pessoal. O agente usa isso para alocar pessoal entre os destinos sem exceder os limites.</p><h2>Furacão ELARA-26: coordenação agêntica de 137.000 pessoas, de ponta a ponta</h2><p>O furacão ELARA-26 é uma tempestade de categoria 4 (ventos máximos de 213 km/h) com previsão de atingir a costa na região de Hampton Roads, na Virgínia. Quando o evento do GDACS é ingerido, o polígono da área afetada intercepta sete grandes instalações militares na região. A regra de detecção dispara. O fluxo de trabalho inicia uma conversa com o agente.</p><p>Em um único loop agêntico, o agente:</p><ul><li><p>Identificou sete instalações na zona de impacto, com um total combinado de 137.372 pessoas.</p></li><li><p>Chamou mitra.nearest_facility para encontrar instalações receptoras fora da trajetória da tempestade.</p></li><li><p>Distribuiu o pessoal entre nove instalações receptoras com base na capacidade de alojamento disponível e na distância.</p></li><li><p>Gerou e enviou ordens de evacuação para todas as sete instalações afetadas.</p></li><li><p>Gerou e enviou notificações de recebimento para todas as nove instalações receptoras.</p></li><li><p>Produziu um resumo completo de coordenação, semelhante ao mostrado abaixo:</p></li></ul><p><strong>Instalações evacuadas:</strong></p><p>Instalação</p><p>Pessoal</p><p>Estação Naval de Norfolk</p><p>50.000</p><p>Base expedicionária conjunta Little Creek-Fort Story</p><p>18.000</p><p>Naval Air Station Oceana</p><p>15.355</p><p>Naval Air Station Oceana Dam Neck Annex</p><p>17.509</p><p>Reserva Militar Estadual NG Camp Pendleton</p><p>9.707</p><p>Base Conjunta Langley-Eustis</p><p>15.000</p><p>Naval Weapons Station Yorktown</p><p>11.801</p><p><strong>Instalações receptoras:</strong></p><p>Instalação</p><p>Distância</p><p>Pessoal ingressante</p><p>Fort Gregg-Adams</p><p>97 km</p><p>~40.000</p><p>Base do Corpo de Fuzileiros Navais de Quantico</p><p>148 km</p><p>~30.000</p><p>Naval Support Facility Indian Head</p><p>151 km</p><p>~30.000</p><p>Base Conjunta Andrews</p><p>180 km</p><p>~30.000</p><p>Naval Air Station Patuxent River</p><p>141 km</p><p>~10.000</p><p>NG MTA Camp Butner</p><p>174 km</p><p>~5.000</p><p>Local de treinamento NG Bethany Beach</p><p>209 km</p><p>~4.707</p><p>Rivanna Station</p><p>140 km</p><p>~7.500</p><p>Centro de suprimentos Def Gen</p><p>22 km</p><p>~6.000</p><p>Os ativos realocados incluem veículos de transporte, helicópteros, barcos de patrulha, unidades médicas, veículos de engenharia, geradores, reboques de água, kits de abrigo e sistemas de comunicação.</p><h3>Notificações automatizadas por e-mail</h3><p>Depois que o agente finalizou seu plano de alocação, ele chamou mitra.send_email e enviou 16 e-mails de uma só vez; ou seja, ordens de evacuação para todas as sete instalações afetadas e notificações de recebimento para todas as nove instalações receptoras. Cada mensagem incluía a instalação de destino, a quantidade de pessoal que chegaria, os ativos a serem movidos e um contato de coordenação. O que teria levado horas de ligações em cadeia foi concluído automaticamente no momento em que o agente terminou de raciocinar.</p><h3>Estendendo a resposta agêntica a desastres com RAG e fundamentação em políticas</h3><p>Esta demo é puramente baseada em dados estruturados, como números de capacidade, distâncias e status operacional. Os recursos de busca semântica e retrieval augmented generation (RAG) da Elastic podem tornar o agente significativamente mais inteligente, com duas adições:</p><p><strong>Recuperação de respostas históricas:</strong> indexe relatórios pós-ação anteriores, resumos de incidentes da Agência Federal de Gestão de Emergências (FEMA) e registros de resposta a desastres como embeddings vetoriais. Quando ocorre um novo evento, o agente pode recuperar semanticamente como eventos semelhantes foram tratados, embasando decisões de alocação com conhecimento institucional, em vez de se basear apenas em cálculos de capacidade.</p><p><strong>Fundamentação em políticas e doutrinas:</strong> indexe diretrizes de gerenciamento de emergências do DoD, planos de continuidade de operações de instalações e orientações do comandante. O agente pode recuperar e citar as políticas reais que regem uma resposta, garantindo que cada decisão seja fundamentada em doutrina, em vez de inferência.</p><p>Ambos seguem a mesma abordagem nativa da Elastic:; um pipeline de inferência gera embeddings em tempo de indexação, e uma ferramenta de busca semântica é exposta ao agente. O pipeline de coordenação permanece o mesmo. O agente simplesmente fica mais inteligente.</p><h2>Por que o Elasticsearch é a plataforma certa para a resposta agêntica no setor público</h2><p>Este não é um chatbot. Não é um dashboard. É um sistema responsivo de fluxo de trabalho agêntico, que detectou uma ameaça, raciocinou sobre um problema logístico complexo e coordenou a realocação de 137.000 pessoas sem intervenção humana. Esse tipo de resultado só é possível porque todos os recursos dos quais ele depende estão em uma única plataforma unificada.</p><p>O suporte geoespacial do Elasticsearch (geo_point, geo_shape, políticas de enriquecimento e classificação baseada em distância) lida com o raciocínio espacial que torna a detecção de interseções e a consulta de instalações possíveis em escala. A busca semântica e os embeddings vetoriais ancoram os agentes na realidade, garantindo que o raciocínio da IA seja baseado no que realmente está em seus dados, em vez de suposições alucinadas. O mecanismo de detecção do Kibana, os fluxos de trabalho, o Agent Builder e as ferramentas do Agent Builder conectam tudo em um pipeline que vai do evento bruto à ação coordenada, sem a necessidade de nenhum código de integração externo.</p><p>Nenhuma outra plataforma reúne tudo isso como a Elastic. A combinação de indexação em tempo real, precisão geoespacial, recuperação semântica e orquestração por agentes, tudo em uma única pilha de tecnologia, com segurança e observabilidade de nível empresarial integradas, é o que diferencia a Elastic de ferramentas que fazem bem uma dessas coisas, mas exigem que você reúna o restante por conta própria.</p><h2>Resposta geoespacial agêntica para gerenciamento de emergências, bombeiros, aplicação da lei e saúde pública</h2><p>A mesma arquitetura se aplica onde quer que pessoas, instalações e eventos em tempo real se cruzem. Os dados específicos mudam. O pipeline não.</p><p><strong>Gerenciamento de emergências:</strong> a FEMA e os órgãos estaduais de gerenciamento de emergências podem mapear locais de abrigo, áreas de mobilização e populações vulneráveis em relação aos polígonos de clima severo do National Weather Service (NWS), acionando o pré-posicionamento automatizado de recursos antes que uma tempestade atinja a costa.</p><p><strong>Serviços de bombeiros e emergência médica:</strong> os corpos de bombeiros podem sobrepor localizações de unidades e zonas de resposta a perímetros de incêndios florestais ou clusters de incêndios estruturais, encaminhando automaticamente solicitações de ajuda mútua para as unidades disponíveis mais próximas com o equipamento adequado.</p><p><strong>Aplicação da lei:</strong> as agências podem correlacionar locais de incidentes ativos com zonas escolares, infraestrutura crítica e posições de policiais, disparando notificações de bloqueio baseadas em localização geográfica ou despacho de recursos sem esperar pela triagem manual.</p><p><strong>Segurança nas escolas públicas:</strong> os distritos escolares podem monitorar feeds de ameaças em tempo real em relação aos limites do campus. Quando uma ameaça cruza o perímetro de uma escola, um agente pode notificar imediatamente a administração, iniciar comunicações de confinamento e coordenar a resposta das forças policiais, tudo antes que um atendente pegue o telefone.</p><p><strong>Saúde pública:</strong> os departamentos de saúde podem cruzar dados de vigilância de doenças ou zonas de risco ambiental com a localização de clínicas, camadas de densidade populacional e estoques de depósitos de suprimentos para direcionar recursos para onde são mais necessários.</p><p>Setor</p><p>Caso de uso</p><p>Recurso da Elastic</p><p>Gerenciamento de emergências</p><p>Corresponda os locais de abrigo aos polígonos de clima severo do NWS</p><p>Enriquecimento de geo_shape + fluxos de trabalho do Kibana</p><p>Bombeiros e EMS</p><p>Sobreponha as localizações das unidades aos perímetros de incêndios florestais</p><p>roteamento geoespacial + consulta de instalação mais próxima</p><p>Aplicação da lei</p><p>Correlacione incidentes com zonas escolares e posições de policiais</p><p>regras de alerta com reconhecimento geográfico + despacho de agentes</p><p>Segurança nas escolas públicas</p><p>Monitore feeds de ameaças em relação aos perímetros do campus</p><p>regras de detecção + notificação automatizada</p><p>Saúde pública</p><p>Corresponda zonas de perigo a locais de clínicas e depósitos de suprimentos</p><p>busca semântica + enriquecimento geoespacial</p><p>Os dados são diferentes em cada cenário. O padrão subjacente de ingerir, enriquecer no momento da indexação, detectar interseção, acionar resposta agêntica e agir é o mesmo. A Elastic oferece às organizações do setor público a plataforma para criar uma vez e adaptar em qualquer lugar.</p><p><em>O lançamento e a disponibilização de quaisquer recursos ou funcionalidades descritos neste artigo ficam a exclusivo critério da Elastic. Os recursos ou funcionalidades não disponíveis no momento podem não ser disponibilizados no prazo previsto ou nem chegar a ser disponibilizados.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-agentic-disaster-response</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-agentic-disaster-response</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Alec Carpenter]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt969cad2694920de4/6a4693f37746672ad42675b5/cb292a501835472598dee30bef25c77afc54db6c-720x420.png" length="0" type="image/png"/>
    <pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Como criar aplicações de IA agentiva com Mastra e Elasticsearch]]></title>
    <description><![CDATA[Aprenda como construir aplicações de IA agentiva usando Mastra e Elasticsearch com um exemplo prático.]]></description>
    <content:encoded><![CDATA[<p>Neste artigo, vamos mostrar como usar o framework <a href="https://mastra.ai/">Mastra</a> TypeScript para criar aplicações agentivas que interagem com <a href="https://www.elastic.co/elasticsearch">Elasticsearch</a>.</p><p>Recentemente, contribuímos para o projeto open source <a href="https://github.com/mastra-ai/mastra">mastra-ai/mastra</a> adicionando suporte ao Elasticsearch como banco de dados vetorial. Com esse novo recurso, você pode usar o Elasticsearch nativamente no Mastra para armazenar embeddings. Além dos vetores, o Elasticsearch oferece um conjunto de recursos avançados para atender a todos os seus requisitos de engenharia de contexto. (por exemplo, <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">busca híbrida e reranking</a>).</p><p>Este artigo detalha a criação de um agente para implementar uma arquitetura de retrieval augmented generation (RAG) usando o Elasticsearch. Vamos apresentar um projeto de demonstração onde uma abordagem agentiva é usada para interagir com um corpus de dados de filmes de ficção científica armazenados no Elasticsearch. O projeto está disponível em <a href="https://github.com/elastic/mastra-elasticsearch-example">elastic/mastra-elasticsearch-example</a>.</p><h2>Mastra</h2><p>Mastra é um framework TypeScript para criar aplicações de IA com agentes.</p><p>A estrutura do projeto em Mastra é a seguinte:</p>src/
├── mastra/
│   ├── agents/
│   │   └── weather-agent.ts
│   ├── tools/
│   │   └── weather-tool.ts
│   ├── workflows/
│   │   └── weather-workflow.ts
│   ├── scorers/
│   │   └── weather-scorer.ts
│   └── index.ts
├── .env.example
├── package.json
└── tsconfig.json<p>No Mastra, você pode criar <a href="https://mastra.ai/docs/agents/overview">agentes</a>, <a href="https://mastra.ai/docs/agents/using-tools">ferramentas</a>, <a href="https://mastra.ai/docs/workflows/overview">fluxos de trabalho</a> e <a href="https://mastra.ai/docs/evals/overview">métricas</a>.</p><p>Um <strong>agente</strong> é uma classe que aceita uma mensagem na entrada e produz uma resposta como saída. Um agente pode usar ferramentas, grandes modelos de linguagem (LLMs) e uma memória (figura 1).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0f7484f7501997dc/6a170417cdacbffb5a7d28f6/f6aca2dcc7fcc45d25e06681649be1b2b7eb6781-706x721.png" alt="Um diagrama que mostra o funcionamento de um agente no Mastra." /><p>As <strong>ferramentas</strong> de um agente permitem que ele interaja com o "mundo externo", como se comunicar com uma API web ou realizar uma operação interna, como consultar o Elasticsearch. O componente de <strong>memória</strong> é essencial para armazenar o histórico das conversas, incluindo entradas e saídas anteriores. Esse contexto armazenado permite que o agente forneça respostas mais informadas e relevantes para futuras perguntas utilizando suas interações passadas.</p><p>Os <strong>fluxos de trabalho</strong> permitem que você defina sequências complexas de tarefas usando etapas claras e estruturadas, em vez de depender do raciocínio de um único agente (figura 2). Eles dão controle total sobre como as tarefas são divididas, como os dados circulam entre elas e o que é executado e quando. Os fluxos de trabalho são executados usando o mecanismo de execução integrado por padrão ou podem ser implantados em <a href="https://mastra.ai/docs/deployment/workflow-runners">executores de fluxo de trabalho</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd82ea661569e1018/6a170419dc55de3adde00cc9/0dce161cf7891207015dc87532b5b90df1822432-880x252.png" alt="Um exemplo de fluxo de trabalho no Mastra." /><p>No Mastra, você também pode definir métricas, que são testes automatizados para avaliar as saídas dos agentes usando métodos baseados em modelos, regras e estatísticas. Os avaliadores retornam <em>métricas</em>: valores numéricos (normalmente entre 0 e 1) que quantificam o quanto uma saída atende aos seus critérios de avaliação. Essas métricas permitem que você acompanhe objetivamente o desempenho, compare diferentes abordagens e identifique áreas de melhoria em seus sistemas de IA. Os avaliadores podem ser personalizados com seus próprios prompts e funções de métrica.</p><h2>Elasticsearch</h2><p>Para executar o projeto de demonstração, precisamos ter uma instância do Elasticsearch em execução. Você pode ativar um teste gratuito no <a href="https://www.elastic.co/cloud">Elastic Cloud</a> ou instalá-lo localmente usando o script <a href="https://github.com/elastic/start-local"><code>start-local</code></a>:</p>curl -fsSL https://elastic.co/start-local | sh<p>Isso instalará o Elasticsearch e o Kibana no seu computador e gerará uma chave API para ser usada na configuração da integração Mastra.</p><p>A chave API será mostrada como saída do comando anterior e armazenada em um arquivo <strong>.env</strong> na pasta elastic-start-local.</p><h2>Instalar e configurar a demonstração</h2><p>Criamos um repositório <a href="https://github.com/elastic/mastra-elasticsearch-example">elastic/mastra-elasticsearch-example</a> contendo o código-fonte do projeto de demonstração. O exemplo relatado no repositório ilustra como criar um agente no Mastra que implementa uma arquitetura RAG para recuperar documentos do Elasticsearch.</p><p>Fornecemos um conjunto de dados para a demonstração sobre filmes de ficção científica. Extraímos 500 filmes do conjunto de dados IMDb no <a href="https://www.kaggle.com/datasets/rajugc/imdb-movies-dataset-based-on-genre/versions/2?select=scifi.csv">Kaggle</a>.</p><p>O primeiro passo é instalar as dependências do projeto com npm, usando o seguinte comando:</p>npm install<p>Então precisamos configurar o arquivo <strong>.env</strong> que conterá as configurações. Podemos gerar esse arquivo copiando a estrutura do arquivo <strong>.env.example</strong>, usando o seguinte comando:</p>cp .env.example .env<p>Agora podemos editar o arquivo .env, adicionando as informações que faltam:</p>OPENAI_API_KEY=
ELASTICSEARCH_URL=
ELASTICSEARCH_API_KEY=
ELASTICSEARCH_INDEX_NAME=scifi-movies<p>O nome do índice do Elasticsearch é <strong><code>scifi-movies</code></strong>. Se quiser, pode mudar usando a variável de ambiente <code>ELASTICSEARCH_INDEX_NAME</code>.</p><p>Usamos a OpenAI como serviço de embeddings, o que significa que você precisa fornecer uma chave de API para a OpenAI na variável de ambiente <code>OPENAI_API_KEY</code>.</p><p>O modelo de embedding usado no exemplo é <a href="https://developers.openai.com/api/docs/models/text-embedding-3-small">openai/text-embedding-3-small</a>, com uma dimensão de embedding de 1.536.</p><p>Para gerar a resposta final, utilizamos o modelo <a href="https://developers.openai.com/api/docs/models/gpt-5-nano">openai/gpt-5-nano</a> para reduzir os custos.</p><p>A arquitetura RAG permite que você use um modelo LLM final menos potente (e normalmente mais barato) porque o trabalho pesado de fundamentar a resposta é feito pelo componente de recuperação (Elasticsearch, neste caso).</p><p>O LLM menor é responsável apenas por duas tarefas principais:</p><ul><li><p><strong>Reformulação/embedding da consulta:</strong> conversão da pergunta do usuário em linguagem natural em um vetor de embedding para busca semântica.</p></li><li><p><strong>Sintetização da resposta:</strong> pegar os fragmentos de contexto recuperados e altamente relevantes (documentos/filmes) e sintetizá-los em uma resposta coerente, final e legível por humanos, seguindo as instruções do prompt fornecido.</p></li></ul><p>Como o processo RAG <strong>fornece o contexto factual exato</strong> necessário para a resposta, o LLM final não precisa ser massivo ou altamente complexo, nem precisa possuir todo o conhecimento necessário dentro de seus próprios parâmetros (é aí que modelos grandes e caros se destacam). Basicamente, ele atua como um sofisticado resumidor e formatador de texto para o contexto fornecido pelo Elasticsearch, e não como uma base de conhecimento completa em si. Isso permite o uso de modelos como <code>gpt-5-nano</code> para otimização de custos e latência.</p><p>Após a configuração do arquivo .env, você pode fazer a ingestão dos filmes no Elasticsearch usando o seguinte comando:</p>npx tsx src/utility/store.ts<p>Você deve ver uma saída da seguinte forma:</p>🚀 Starting ingestion of 500 movies from 500_scifi_movies.jsonl...
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 1/500 (0%) | ok:1 | fail:0 | chunks:1 | eta:19m 33s | current:Capricorn One
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 2/500 (0%) | ok:2 | fail:0 | chunks:2 | eta:10m 32s | current:Doghouse
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 3/500 (1%) | ok:3 | fail:0 | chunks:3 | eta:7m 33s | current:Dinocroc
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 4/500 (1%) | ok:4 | fail:0 | chunks:7 | eta:6m 10s | current:Back to the Future           
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 5/500 (1%) | ok:5 | fail:0 | chunks:9 | eta:5m 14s | current:The Projected Man            
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 6/500 (1%) | ok:6 | fail:0 | chunks:11 | eta:4m 41s | current:I, Robot
...
✅ Ingestion complete in 1m 46s. Success: 500, Failed: 0, Chunks: 693.<p>O mapeamento do índice de filmes de ficção científica contém os seguintes campos:</p><ul><li><p><strong>embedding</strong>, dense_vector com dimensão de 1.536, similaridade cosseno.</p></li><li><p><strong>description</strong>, texto contendo a descrição do filme.</p></li><li><p><strong>director</strong>, texto contendo o nome do diretor.</p></li><li><p><strong>título</strong>, texto contendo o título do filme.</p></li></ul><p>Geramos os embeddings usando o título e a descrição. Como o título e a descrição são dois campos separados, a concatenação de ambos garante que o vetor de embedding resultante capture tanto a identidade específica e única (título) quanto o contexto rico e descritivo (descrição) do filme, resultando em buscas semânticas mais precisas e abrangentes. Essa entrada combinada oferece ao modelo de embedding uma representação mais adequada do conteúdo do documento para comparação de similaridade.</p><h2>Execute a demonstração</h2><p>Você pode executar a demonstração com o seguinte comando:</p>npm run dev<p>Esse comando iniciará uma aplicação web em <strong>localhost:4111</strong> para acessar o Mastra Studio (Figura 3).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a539df677a33b36/6a17041a47d49c36842d88a0/1567e309df21a12bcf1dfef4429f82342549956c-1705x1079.png" alt="Uma captura de tela do Mastra Studio com o exemplo do agente Elasticsearch." /><p>O <a href="https://mastra.ai/docs/getting-started/studio">Mastra Studio</a> oferece uma interface de usuário interativa para criar e testar seus agentes, além de uma REST API que expõe seu aplicativo Mastra como um serviço local. Isso permite que você comece a trabalhar imediatamente, sem se preocupar com integração.</p><p>Fornecemos um <strong>Agente Elasticsearch</strong> que utiliza <a href="https://mastra.ai/reference/tools/vector-query-tool">o createVectorQueryTool</a> da Mastra como ferramenta para executar busca semântica usando Elasticsearch. Esse agente utiliza a abordagem RAG para buscar documentos relevantes (ou seja, filmes) para responder à pergunta do usuário.</p><p>Este agente usa o seguinte prompt:</p>You are a helpful assistant that answers questions based on the provided context.
Follow these steps for each response:

1. First, carefully analyze the retrieved context chunks and identify key information.
2. Break down your thinking process about how the retrieved information relates to the query.
3. Draw conclusions based only on the evidence in the retrieved context.
4. If the retrieved chunks don't contain enough information, explicitly state what's missing.

Format your response as:
THOUGHT PROCESS:
- Step 1: [Initial analysis of retrieved chunks]
- Step 2: [Reasoning based on chunks]

FINAL ANSWER:
[Your concise answer based on the retrieved context]

Important: When asked to answer a question, please base your answer only on the context provided in the tool. 
If the context doesn't contain enough information to fully answer the question, please state that explicitly and stop it.
Do not add more information than what is present in the retrieved chunks.
Remember: Explain how you're using the retrieved information to reach your conclusions.<p>Se você clicar no menu <code>Mastra Studio &gt; Agents</code> e selecionar <strong>Agente Elasticsearch</strong>, pode testar o agente usando um sistema de chat. Por exemplo, você pode pedir informações sobre filmes de ficção científica com a seguinte pergunta:</p><p><em>Encontre 5 filmes ou séries de TV sobre OVNIs</em>.</p><p>Você notará que o agente executará a ferramenta vectorQueryTool. Você pode clicar na ferramenta invocada para visualizar a entrada e a saída. Ao final da execução, o LLM responderá à sua pergunta, considerando o contexto do índice de filmes de ficção científica do Elasticsearch (figura 4).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltda92a9b6e56528d3/6a17041c2b835f9724f4b0d6/d9998d4f687984de98845dae52d1288166abf448-1344x1071.png" alt=" Resposta do LLM usando o Agente Elasticsearch." /><p>O Mastra executa internamente os seguintes passos:</p><ol><li><p><strong>Conversão de vetor:</strong> A pergunta do usuário, <em>Encontre 5 filmes ou séries de TV sobre OVNIs,</em> é convertida em uma incorporação vetorial usando o modelo <code>openai/text-embedding-3-small</code> da OpenAI.</p></li><li><p><strong>Busca vetorial:</strong> este embedding é então usado para consultar o Elasticsearch por meio de uma busca vetorial.</p></li><li><p><strong>Recuperação do resultado:</strong> o Elasticsearch retorna um conjunto de 10 filmes altamente relevantes para a consulta (ou seja, aqueles cujos vetores estão mais próximos do vetor de consulta do usuário).</p></li><li><p><strong>Geração de respostas:</strong> os filmes recuperados e a pergunta original do usuário são enviados para o LLM, especificamente <code>openai/gpt-5-nano</code>. O LLM processa essas informações e gera uma resposta final, garantindo que o pedido do usuário por cinco resultados seja atendido.</p></li></ol><h2>O Agente Elasticsearch</h2><p>Aqui apresentamos o código-fonte do agente Elasticsearch.</p>import { Agent } from "@mastra/core/agent";
import { ElasticSearchVector } from '@mastra/elasticsearch';
import { createVectorQueryTool } from '@mastra/rag';
import { ModelRouterEmbeddingModel } from "@mastra/core/llm";
import { Memory } from "@mastra/memory";

const es_url = process.env.ELASTICSEARCH_URL;
const es_apikey = process.env.ELASTICSEARCH_API_KEY;
const es_index_name = process.env.ELASTICSEARCH_INDEX_NAME;
const prompt = 'insert here the previous prompt';

const esVector = new ElasticSearchVector({
  id: 'elasticsearch-vector',
  url: es_url,
  auth: {
    apiKey : es_apikey
  }
});

const vectorQueryTool = createVectorQueryTool({
  vectorStore: esVector,
  indexName: es_index_name,
  model: new ModelRouterEmbeddingModel("openai/text-embedding-3-small")
});

export const elasticsearchAgent = new Agent({
  id: "elasticsearch-agent",
  name: "Elasticsearch Agent",
  instructions: prompt,
  model: 'openai/gpt-5-nano',
  tools: { vectorQueryTool },
  memory: new Memory(),
});<p>O <strong>vectorQueryTool</strong> é a ferramenta que é invocada para implementar a parte de recuperação do exemplo RAG. Ele utiliza a implementação <a href="https://mastra.ai/reference/vectors/elasticsearch">ElasticSearchVector</a> que a Elastic contribuiu para o Mastra.</p><p>O agente é um objeto da classe agent que utiliza o vectorQueryTool, o prompt e uma memória. Como você pode ver, o código que precisamos colocar em prática para conectar o Elasticsearch a um agente é mínimo.</p><h2>Conclusão</h2><p>Este artigo demonstrou a simplicidade e o poder de integrar o Elasticsearch ao framework Mastra para criar aplicações sofisticadas de IA agentiva. Especificamente, detalhamos a criação de um agente RAG capaz de realizar busca semântica em um corpus de dados de filmes de ficção científica indexados no Elasticsearch.</p><p>O principal aprendizado é a contribuição direta da Elastic para o projeto open source Mastra, fornecendo suporte nativo para o Elasticsearch como um repositório vetorial. Essa integração reduz significativamente a barreira de entrada, como demonstra o código-fonte do <strong>Elasticsearch Agent</strong>. Usando o <code>ElasticSearchVector</code> e <code>createVectorQueryTool</code>, a configuração completa para conectar o Elasticsearch ao seu agente exige apenas algumas linhas de código de configuração.</p><p>O Elasticsearch oferece vários recursos avançados para aumentar a relevância dos resultados. Por exemplo, a <a href="https://www.elastic.co/elasticsearch/hybrid-search">busca híbrida</a> aumenta significativamente a precisão ao combinar a busca lexical com a busca vetorial. Outro recurso interessante é a reclassificação usando os <a href="https://www.elastic.co/search-labs/tutorials/jina-tutorial/jina-reranker-v3">modelos Jina</a> mais recentes, que podem ser aplicados ao final da busca híbrida. Para saber mais sobre essas técnicas, consulte os seguintes artigos do Elasticsearch Labs:</p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/hybrid-search-elasticsearch">Busca híbrida do Elasticsearch</a> por Valentin Crettaz</p></li><li><p><a href="https://www.elastic.co/search-labs/blog/jina-models-elasticsearch-guide">Uma introdução aos modelos Jina, sua funcionalidade e seus usos no Elasticsearch</a> por Scott Martens</p></li></ul><p>Também incentivamos você a explorar o exemplo fornecido e começar a construir seus próprios agentes baseados em dados com Mastra e Elasticsearch. Para mais informações sobre o Mastra, você pode consultar a documentação oficial <a href="https://mastra.ai/docs">aqui</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-agentic-ai-applications-mastra-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-agentic-ai-applications-mastra-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Enrico Zimuel]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt083181bab7c0e2d0/6a17041eacf0880b70be99f5/ab30baf2f908534840c5d71a46705773807baf54-1280x720.png" length="0" type="image/png"/>
    <pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando um servidor MCP do Elasticsearch com TypeScript]]></title>
    <description><![CDATA[Saiba como criar servidor MCP do Elasticsearch com TypeScript e Claude Desktop.]]></description>
    <content:encoded><![CDATA[<p>Ao trabalhar com grandes bases de conhecimento no Elasticsearch, encontrar informações é apenas metade da batalha. Engenheiros precisam sintetizar resultados de múltiplos documentos, gerar resumos e rastrear respostas até as fontes. Para isso, o Protocolo de Contexto do Modelo (MCP) oferece uma maneira padronizada de conectar o Elasticsearch a aplicativos baseados em grandes modelos de linguagem (LLM). Embora a Elastic ofereça soluções oficiais, como o Elastic Agent Builder (que inclui um <a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server">endpoint MCP</a> entre os recursos), a criação de um servidor MCP personalizado oferece controle total sobre a lógica de busca, a formatação dos resultados e como o conteúdo recuperado é passado para um LLM para síntese, resumos e citações.</p><p>Neste artigo, exploraremos os benefícios de criar um servidor MCP do Elasticsearch personalizado e mostraremos como criar um servidor em TypeScript que conecte o Elasticsearch a aplicativos com LLM.</p><h2>Por que criar um servidor MCP do Elasticsearch personalizado?</h2><p>A Elastic oferece algumas alternativas para <a href="https://www.elastic.co/docs/solutions/search/mcp">servidores MCP</a>:</p><ul><li><p><a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server">Servidor MCP do Elastic Agent Builder para Elasticsearch 9.2+</a></p></li><li><p><a href="https://github.com/elastic/mcp-server-elasticsearch?tab=readme-ov-file#elasticsearch-mcp-server">Servidor MCP do Elasticsearch para versões mais antigas (Python)</a></p></li></ul><p>Se você precisar de mais controle sobre como o servidor MCP interage com o Elasticsearch, a criação do seu próprio servidor personalizado oferece a flexibilidade de adaptá-lo exatamente às suas necessidades. Por exemplo, o endpoint MCP do Agent Builder é limitado a consultas em Elasticsearch Query Language (ES|QL), enquanto um servidor personalizado permite usar o Query DSL completo. Você também tem controle sobre como os resultados são formatados antes de serem passados para o LLM e pode integrar etapas adicionais de processamento, como o resumo com tecnologia OpenAI que implementaremos neste tutorial.</p><p>Ao final deste artigo, você terá um servidor MCP no TypeScript que busca informações armazenadas em um índice do Elasticsearch, resume essas informações e fornece citações. Usaremos o Elasticsearch para recuperação, o modelo <code>gpt-4o-mini</code> da OpenAI para resumir e gerar citações, e o Claude Desktop como cliente MCP e UI para receber consultas dos usuários e dar respostas. O resultado é um assistente de conhecimento interno que ajuda os engenheiros a entender e sintetizar as práticas recomendadas nos documentos técnicos de sua organização.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltad9133cb083ad352/6a170c19b0367d411e72bd5b/ec5771a874cf9740d4cac6888622cbe8cd6aede7-1999x1133.png" alt="Criando um servidor MCP Elastic com TypeScript e Claude Desktop." /><h2>Pré-requisitos:</h2><ul><li><p>Node.js 20 +</p></li><li><p>Elasticsearch</p></li><li><p>Chave de API da OpenAI</p></li><li><p>Claude Desktop</p></li></ul><h3>O que é MCP?</h3><p><a href="https://www.elastic.co/what-is/mcp">O MCP</a> é um padrão aberto, criado pela <a href="https://www.anthropic.com/news/model-context-protocol">Anthropic</a>, que oferece conexões seguras e bidirecionais entre LLMs e sistemas externos, como o Elasticsearch. Você pode ler mais sobre a situação atual do MCP <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">neste artigo</a>.</p><p>O cenário de MCP está <a href="https://www.elastic.co/search-labs/blog/mcp-current-state#mcp-project-updates:-transport,-elicitation,-and-structured-tooling">em constante evolução</a>, com servidores disponíveis para uma ampla gama de casos de uso. Além disso, é fácil criar seu próprio servidor MCP personalizado, como mostraremos neste artigo.</p><h3>Clientes do MCP</h3><p>Há uma longa <a href="https://modelcontextprotocol.io/clients">lista de clientes MCP disponíveis</a>, cada um com as próprias características e limitações. Por simplicidade e popularidade, usaremos o <a href="https://claude.ai/download">Claude Desktop</a> como nosso cliente MCP. Ele servirá como interface de chat na qual os usuários poderão fazer perguntas em linguagem natural e que invocará automaticamente as ferramentas expostas pelo nosso servidor MCP para buscar documentos e gerar resumos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06fd7a02042094e1/6a170c1b14b2700024e3c651/66eb0b11473347b6cf2d85718251eeac38d6249d-1999x1491.png" alt="Página do Claude 4.5 Sonnet, com a observação, &quot;hora do café e do Claude? Como posso ajudar você hoje?&quot;" /><h2>Criando um servidor MCP do Elasticsearch</h2><p>Usando o <a href="https://github.com/modelcontextprotocol/typescript-sdk">TypeScript SDK</a>, podemos criar um servidor que entende como consultar nossos dados do Elasticsearch com base em uma entrada de consulta do usuário.</p><p>Aqui estão os passos deste artigo para integrar o servidor MCP do Elasticsearch com o cliente Claude Desktop:</p><ol><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#configure-mcp-server-for-elasticsearch">Configure o servidor MCP para o Elasticsearch.</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#load-the-mcp-server-into-claude-desktop">Carregue o servidor MCP no Claude Desktop.</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#test-it-out">Faça o teste.</a></p></li></ol><h3>Configure o servidor MCP para o Elasticsearch</h3><p>Para começar, vamos iniciar uma aplicação de nó:</p>npm init -y<p>Isso criará um arquivo <code>package.json</code> e, com ele, poderemos começar a instalar as dependências necessárias para essa aplicação.</p>npm install @elastic/elasticsearch @modelcontextprotocol/sdk openai zod &amp;&amp; npm install --save-dev ts-node @types/node typescript<ul><li><p><strong>@elastic/elasticsearch</strong> nos dará acesso à biblioteca Elasticsearch Node.js.</p></li><li><p><strong>@modelcontextprotocol/sdk</strong> fornece as ferramentas de núcleo para criar e gerenciar um servidor MCP, registrar ferramentas e lidar com a comunicação com clientes MCP.</p></li><li><p><strong>openai</strong> permite a interação com modelos OpenAI para gerar resumos ou respostas em linguagem natural.</p></li><li><p><a href="https://zod.dev/"><strong>zod</strong></a>ajuda a definir e validar esquemas estruturados para dados de entrada e saída em cada ferramenta.</p></li></ul><p><code>ts-node</code>, <code>@types/node</code>, e <code>typescript</code> serão usados durante o desenvolvimento para digitar o código e compilar os scripts.</p><h4>Configurar o conjunto de dados</h4><p>Para fornecer os dados que o Claude Desktop pode consultar usando nosso servidor MCP, usaremos um <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/dataset.json">conjunto de dados fictício de base de conhecimento interna</a>. Veja como será um documento desse conjunto de dados:</p>{
    "id": 5,
    "title": "Logging Standards for Microservices",
    "content": "Consistent logging across microservices helps with debugging and tracing. Use structured JSON logs and include request IDs and timestamps. Avoid logging sensitive information. Centralize logs in Elasticsearch or a similar system. Configure log rotation to prevent storage issues and ensure logs are searchable for at least 30 days.",
    "tags": ["logging", "microservices", "standards"]
}<p>Para ingerir os dados, preparamos um script que cria um índice no Elasticsearch e carrega o conjunto de dados nele. Você pode encontrá-lo <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/setup.ts">aqui</a>.</p><h4>Servidor MCP</h4><p>Crie um arquivo chamado <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/index.ts"><code>index.ts</code></a> e adicione o seguinte código para importar as dependências e lidar com as variáveis de ambiente:</p>// index.ts
import { z } from "zod";
import { Client } from "@elastic/elasticsearch";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import OpenAI from "openai";

const ELASTICSEARCH_ENDPOINT =
  process.env.ELASTICSEARCH_ENDPOINT ?? "http://localhost:9200";
const ELASTICSEARCH_API_KEY = process.env.ELASTICSEARCH_API_KEY ?? "";
const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? "";
const INDEX = "documents";<p>Além disso, vamos inicializar os clientes para lidar com as chamadas do Elasticsearch e do OpenAI:</p>const openai = new OpenAI({
  apiKey: OPENAI_API_KEY,
});

const _client = new Client({
  node: ELASTICSEARCH_ENDPOINT,
  auth: {
    apiKey: ELASTICSEARCH_API_KEY,
  },
});<p>Para tornar nossa implementação mais robusta e garantir entrada e saída estruturadas, definiremos esquemas usando <a href="https://zod.dev/"><code>zod</code></a>. Isso nos permite validar dados em tempo de execução, detectar erros com antecedência e facilitar o processamento de forma programática das respostas da ferramenta:</p>const DocumentSchema = z.object({
  id: z.number(),
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
});

const SearchResultSchema = z.object({
  id: z.number(),
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
  score: z.number(),
});

type Document = z.infer&lt;typeof DocumentSchema&gt;;
type SearchResult = z.infer&lt;typeof SearchResultSchema&gt;;<p>Saiba mais sobre saídas estruturadas <a href="https://www.elastic.co/search-labs/blog/structured-outputs-elasticsearch-guide">aqui</a>.</p><p>Agora vamos inicializar o servidor MCP:</p>const server = new McpServer({
  name: "Elasticsearch RAG MCP",
  description:
    "A RAG server using Elasticsearch. Provides tools for document search, result summarization, and source citation.",
  version: "1.0.0",
});<h4>Definição das ferramentas MCP</h4><p>Com tudo configurado, podemos começar a escrever as ferramentas que serão expostas pelo nosso servidor MCP. Esse servidor expõe duas ferramentas:</p><ul><li><p><strong><code>search_docs</code></strong><strong>: </strong>Busca por documentos no Elasticsearch usando busca de texto completo.</p></li><li><p><strong><code>summarize_and_cite</code></strong><strong>:</strong> Resume e sintetiza informações de documentos previamente recuperados para responder a uma pergunta do usuário. Essa ferramenta também adiciona citações que referenciam os documentos fonte.</p></li></ul><p>Juntas, essas ferramentas formam um fluxo de trabalho simples de "recuperar e resumir", em que uma ferramenta busca documentos relevantes e a outra usa esses documentos para gerar uma resposta resumida e citada.</p><h4>Formato de resposta da ferramenta</h4><p>Cada ferramenta pode aceitar parâmetros de entrada arbitrários, mas deve responder com a seguinte estrutura:</p><ul><li><p><strong>Conteúdo:</strong> esta é a resposta da ferramenta em um formato não estruturado. Este campo geralmente é usado para retornar texto, imagens, áudio, links ou embeddings. Para esta aplicação, ele será usado para retornar texto formatado com as informações geradas pelas ferramentas.</p></li><li><p><strong>structuredContent: </strong>Esse é um retorno opcional usado para fornecer os resultados de cada ferramenta em um formato estruturado. É útil para fins programáticos. Embora não seja usado neste servidor MCP, pode ser útil caso você queira desenvolver outras ferramentas ou processar os resultados programaticamente.</p></li></ul><p>Com essa estrutura em mente, vamos nos aprofundar em cada ferramenta em detalhes.</p><h4>Ferramenta de Busca de Documentos</h4><p>Esta ferramenta realiza uma <a href="https://www.elastic.co/docs/solutions/search/full-text">busca de texto completo</a> no índice do Elasticsearch para recuperar os documentos mais relevantes com base na consulta do usuário. Ele destaca correspondências-chave e oferece uma visão geral rápida com pontuações de relevância.</p>server.registerTool(
  "search_docs",
  {
    title: "Search Documents",
    description:
      "Search for documents in Elasticsearch using full-text search. Returns the most relevant documents with their content, title, tags, and relevance score.",
    inputSchema: {
      query: z
        .string()
        .describe("The search query terms to find relevant documents"),
      max_results: z
        .number()
        .optional()
        .default(5)
        .describe("Maximum number of results to return"),
    },
    outputSchema: {
      results: z.array(SearchResultSchema),
      total: z.number(),
    },
  },
  async ({ query, max_results }) =&gt; {
    if (!query) {
      return {
        content: [
          {
            type: "text",
            text: "Query parameter is required",
          },
        ],
        isError: true,
      };
    }

    try {
      const response = await _client.search({
        index: INDEX,
        size: max_results,
        query: {
          bool: {
            must: [
              {
                multi_match: {
                  query: query,
                  fields: ["title^2", "content", "tags"],
                  fuzziness: "AUTO",
                },
              },
            ],
            should: [
              {
                match_phrase: {
                  title: {
                    query: query,
                    boost: 2,
                  },
                },
              },
            ],
          },
        },
        highlight: {
          fields: {
            title: {},
            content: {},
          },
        },
      });

      const results: SearchResult[] = response.hits.hits.map((hit: any) =&gt; {
        const source = hit._source as Document;

        return {
          id: source.id,
          title: source.title,
          content: source.content,
          tags: source.tags,
          score: hit._score ?? 0,
        };
      });

      const contentText = results
        .map(
          (r, i) =&gt;
            `[${i + 1}] ${r.title} (score: ${r.score.toFixed(
              2,
            )})\n${r.content.substring(0, 200)}...`,
        )
        .join("\n\n");

      const totalHits =
        typeof response.hits.total === "number"
          ? response.hits.total
          : (response.hits.total?.value ?? 0);

      return {
        content: [
          {
            type: "text",
            text: `Found ${results.length} relevant documents:\n\n${contentText}`,
          },
        ],
        structuredContent: {
          results: results,
          total: totalHits,
        },
      };
    } catch (error: any) {
      console.log("Error during search:", error);

      return {
        content: [
          {
            type: "text",
            text: `Error searching documents: ${error.message}`,
          },
        ],
        isError: true,
      };
    }
  }
);<p><em>Configuramos </em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-fuzzy-query"><em><code>fuzziness</code></em></a><em><code>: “AUTO”</code></em><em> para ter uma tolerância variável de erros de digitação com base no comprimento do token que está sendo analisado. Também definimos </em><em><code>title^2</code></em><em> para aumentar a pontuação dos documentos onde a correspondência ocorre no campo de título.</em></p><h4>Ferramenta summarize_and_cite</h4><p>Esta ferramenta gera um resumo baseado em documentos recuperados na busca anterior. Usa o modelo <code>gpt-4o-mini</code> da OpenAI para sintetizar as informações mais relevantes e responder à pergunta do usuário, fornecendo respostas derivadas diretamente dos resultados da busca. Além do resumo, também retorna metadados de citação para os documentos de origem usados.</p>server.registerTool(
  "summarize_and_cite",
  {
    title: "Summarize and Cite",
    description:
      "Summarize the provided search results to answer a question and return citation metadata for the sources used.",
    inputSchema: {
      results: z
        .array(SearchResultSchema)
        .describe("Array of search results from search_docs"),
      question: z.string().describe("The question to answer"),
      max_length: z
        .number()
        .optional()
        .default(500)
        .describe("Maximum length of the summary in characters"),
      max_docs: z
        .number()
        .optional()
        .default(5)
        .describe("Maximum number of documents to include in the context"),
    },
    outputSchema: {
      summary: z.string(),
      sources_used: z.number(),
      citations: z.array(
        z.object({
          id: z.number(),
          title: z.string(),
          tags: z.array(z.string()),
          relevance_score: z.number(),
        })
      ),
    },
  },
  async ({ results, question, max_length, max_docs }) =&gt; {
    if (!results || results.length === 0 || !question) {
      return {
        content: [
          {
            type: "text",
            text: "Both results and question parameters are required, and results must not be empty",
          },
        ],
        isError: true,
      };
    }

    try {
      const used = results.slice(0, max_docs);

      const context = used
        .map(
          (r: SearchResult, i: number) =&gt;
            `[Document ${i + 1}: ${r.title}]\\n${r.content}`
        )
        .join("\n\n---\n\n");

      // Generate summary with OpenAI
      const completion = await openai.chat.completions.create({
        model: "gpt-4o-mini",
        messages: [
          {
            role: "system",
            content:
              "You are a helpful assistant that answers questions based on provided documents. Synthesize information from the documents to answer the user's question accurately and concisely. If the documents don't contain relevant information, say so.",
          },
          {
            role: "user",
            content: `Question: ${question}\\n\\nRelevant Documents:\\n${context}`,
          },
        ],
        max_tokens: Math.min(Math.ceil(max_length / 4), 1000),
        temperature: 0.3,
      });

      const summaryText =
        completion.choices[0]?.message?.content ?? "No summary generated.";

      const citations = used.map((r: SearchResult) =&gt; ({
        id: r.id,
        title: r.title,
        tags: r.tags,
        relevance_score: r.score,
      }));

      const citationText = citations
        .map(
          (c: any, i: number) =&gt;
            `[${i + 1}] ID: ${c.id}, Title: "${c.title}", Tags: ${c.tags.join(
              ", ",
            )}, Score: ${c.relevance_score.toFixed(2)}`,
        )
        .join("\n");

      const combinedText = `Summary:\\n\\n${summaryText}\\n\\nSources used (${citations.length}):\\n\\n${citationText}`;

      return {
        content: [
          {
            type: "text",
            text: combinedText,
          },
        ],
        structuredContent: {
          summary: summaryText,
          sources_used: citations.length,
          citations: citations,
        },
      };
    } catch (error: any) {
      return {
        content: [
          {
            type: "text",
            text: `Error generating summary and citations: ${error.message}`,
          },
        ],
        isError: true,
      };
    }
  }
);<p>Por fim, precisamos iniciar o servidor usando <a href="https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#stdio">stdio</a>. Isso significa que o cliente MCP se comunicará com nosso servidor lendo e escrevendo nos fluxos padrão de entrada e saída. Stdio é a opção de transporte mais simples e funciona bem para servidores MCP locais lançados como subprocessos pelo cliente. Adicione o seguinte código ao final do arquivo:</p>const transport = new StdioServerTransport();
server.connect(transport);<p>Agora compile o projeto usando o seguinte comando:</p>npx tsc index.ts --target ES2022 --module node16 --moduleResolution node16 --outDir ./dist --strict --esModuleInterop<p>Isso criará uma pasta <code>dist</code> e, dentro dela, um arquivo <code>index.js</code>.</p><h3>Carregue o servidor MCP no Claude Desktop</h3><p>Siga <a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">este guia</a> para configurar o servidor MCP com o Claude Desktop. No arquivo de configuração Claude, precisamos definir os seguintes valores:</p>{
  "mcpServers": {
    "elasticsearch-rag-mcp": {
      "command": "node",
      "args": [   "/Users/user-name/app-dir/dist/index.js"
      ],
      "env": {
        "ELASTICSEARCH_ENDPOINT": "your-endpoint-here",
        "ELASTICSEARCH_API_KEY": "your-api-key-here",
        "OPENAI_API_KEY": "your-openai-key-here"
      }
    }
  }
}<p>O valor <code>args</code> deve apontar para o arquivo compilado na pasta <code>dist</code>. Você também precisa definir as variáveis de ambiente no arquivo de configuração com exatamente os mesmos nomes definidos no código.</p><h3>Faça o teste</h3><p>Antes de executar cada ferramenta, clique em <strong>Busca e Ferramentas</strong> para garantir que as ferramentas estejam ativadas. Aqui você também pode ativar ou desativar cada uma delas:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt395a7337021f9820/6a170c1c67045bb74d45c228/172981c2a54adabc70d5819013c3007670935605-1999x1002.png" alt="Página do Claude 4.5 Sonnet, com a observação, &quot;Boa tarde, Jeff. Como posso ajudar você hoje?&quot;" /><p>Por fim, vamos testar o servidor MCP no chat do Claude Desktop e começar a fazer perguntas:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf4ac458dc0206271/6a170c1e66c4f91328f8c072/03654c0f8c53c714f801fba8b25747071179209b-1999x1353.png" alt="Solicitação de pesquisa do usuário no chat do Claude Desktop para documentos sobre métodos de autenticação e controle de acesso por função (RBAC), junto com as respostas do Claude." /><p>Para a pergunta “<strong>Buscar documentos sobre métodos de autenticação e controle de acesso por função</strong>”, a ferramenta <code>search_docs</code> é executada e retorna os seguintes resultados:</p>Most Relevant Documents:
Access Control and Role Management (highest relevance) - This document covers role-based access control (RBAC) principles, including ensuring users only have necessary permissions, regular auditing of user roles, revoking inactive accounts, and implementing just-in-time access for sensitive operations.
User Authentication with OAuth 2.0 - This document explains OAuth 2.0 authentication, which enables secure delegated access without credential sharing. It covers configuring identity providers, token management with limited scope and lifetime, and secure storage of refresh tokens.
Container Security Guidelines - While primarily about container security, this document touches on access control aspects like running containers as non-root users and avoiding embedded credentials.
Incident Response Playbook - This mentions role assignment during incidents (incident commander, communications lead, etc.), which relates to access control in emergency scenarios.
Logging Standards for Microservices - This document includes guidance on avoiding logging sensitive information, which is relevant to authentication security.<p>A resposta é: "Ótimo! Encontrei 5 documentos relevantes sobre métodos de autenticação e controle de acesso por função. Eis o que foi encontrado:"</p><p>A chamada de ferramenta retorna os documentos fonte como parte da carga útil de resposta, que são posteriormente usados para gerar citações.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbaf48a9468770ce2/6a170c21509168bffee1bb14/25ff4c7e9563d99752f95540dafdc7fd211a66e3-800x530.gif" alt="Página do Claude 4.5 Sonnet, com respostas em rolagem que incluem os cinco documentos relevantes sobre métodos de autenticação e controle de acesso por função." /><p>Também é possível encadear várias ferramentas em uma única interação. Neste caso, o Claude Desktop analisa a pergunta do usuário e determina que precisa primeiro chamar <code>search_docs</code> para recuperar documentos relevantes e depois passar esses resultados para <code>summarize_and_cite</code> para gerar a resposta final, tudo isso sem exigir prompts separados do usuário:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta46ff45274e64192/6a170c230c4857a91501aac1/e6a8a46acb4236e77058f18bcd2f0737b5882c05-1999x1101.png" alt="Chat no Claude Desktop, com a observação &quot;Jeff está de volta&quot;, além de uma nova pergunta do usuário: &quot;Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas?&quot; Inclua referências.&quot;" /><p>Neste caso, para a consulta “<strong>Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas? Inclua referências.</strong>”, obtivemos os seguintes resultados:</p>Based on the documentation, here are the main recommendations to improve authentication and access control across your systems:

Key Recommendations

1. Implement Role-Based Access Control (RBAC)
Ensure users have only the permissions necessary for their job functions. This principle of least privilege minimizes security risks by limiting access to what's truly needed. [1]

2. Regular Access Audits
Conduct regular audits of user roles and promptly revoke access for inactive accounts. This helps prevent unauthorized access from dormant or compromised accounts. [1]

3. Just-in-Time (JIT) Access
Implement just-in-time access for sensitive operations, where permissions are granted only when needed and for a limited duration. This reduces the attack surface by minimizing standing privileges. [1]

4. OAuth 2.0 for Secure Authentication
Use OAuth 2.0 to enable secure delegated access without sharing user credentials. This protocol allows third-party applications to access resources on behalf of users without exposing passwords. [2]

5. Token Security and Management
Configure your identity provider to issue tokens with limited scope and lifetime

Store refresh tokens securely
Validate access tokens consistently to maintain security [2]
References

Access Control and Role Management (Tags: security, access-control)
User Authentication with OAuth 2.0 (Tags: authentication, oauth)
These recommendations work together to create a defense-in-depth approach, where multiple security layers protect your systems from unauthorized access.<p>Como na etapa anterior, podemos ver a resposta de cada ferramenta para esta pergunta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8f633c518e708a99/6a170c25ab7f082991db9ed6/cb606d356b2f7d5e4878a5eff71bc881869ac0ee-800x585.gif" alt="Página de chat do Claude Desktop, com texto rolando que inclui a resposta de cada ferramenta para a pergunta: &quot;Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas? Inclua referências.&quot;" /><p><em>Nota: Se aparecer um submenu perguntando se você aprova o uso de cada ferramenta, selecione </em><em><strong>Permitir sempre</strong></em><em> ou </em><em><strong>Permitir uma vez</strong></em><em>.</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6627ee0bff1862df/6a170c266f7f040f6f91488c/aea942ba9b0037526ea215bec65690f1a5c3099c-1522x250.png" alt="Opções &quot;Sempre permitir&quot; e &quot;Permitir uma vez&quot; do Claude Desktop para o usuário escolher." /><h2>Conclusão</h2><p>Os servidores MCP representam um passo significativo rumo à padronização das ferramentas LLM para aplicações locais e remotas. Embora a compatibilidade total ainda esteja em andamento, estamos avançando nessa direção.</p><p>Neste artigo, aprendemos como criar um servidor MCP personalizado em TypeScript que conecta o Elasticsearch a aplicações baseadas em LLM. Nosso servidor expõe duas ferramentas: <code>search_docs</code> para recuperar documentos relevantes usando Query DSL; e <code>summarize_and_cite</code> para gerar resumos com citações via modelos OpenAI e Claude Desktop como UI.</p><p>O futuro da compatibilidade entre diferentes provedores de clientes e servidores parece promissor. As próximas etapas incluem adicionar mais funcionalidades e flexibilidade ao seu agente. Existe um <a href="https://www.elastic.co/search-labs/blog/llm-functions-elasticsearch-intelligent-query">artigo</a> prático sobre como parametrizar suas consultas usando modelos de pesquisa para ter precisão e flexibilidade.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5600198cb47666a5/6a170c28509168ce3ae1bb18/0bb24c05fff391f42070c2883182ea6fe9cb9680-1280x720.png" length="0" type="image/png"/>
    <pubDate>Fri, 27 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[A ferramenta shell não é uma solução milagrosa para engenharia de contexto]]></title>
    <description><![CDATA[Saiba quais ferramentas de recuperação de contexto existem para a engenharia de contexto, como elas funcionam e as vantagens e desvantagens.]]></description>
    <content:encoded><![CDATA[<p>As ferramentas mais importantes para o agente são as ferramentas de busca que ele pode usar para construir o próprio contexto. Postagens recentes do <a href="https://www.llamaindex.ai/blog/files-are-all-you-need">LlamaIndex</a> e <a href="https://x.com/hwchase17/status/2011814697889316930">LangChain</a> suscitaram uma discussão: <em>uma ferramenta de linha de comando e um sistema de arquivos são tudo o que o agente precisa para engenharia de contexto? </em>Infelizmente, a discussão rapidamente se desviou para o foco errado: sistema de arquivos x banco de dados.</p><p>Esta postagem volta a se concentrar na questão: <em>quais são as interfaces de busca que um agente precisa para construir o próprio contexto?</em> Primeiro, ele aborda as vantagens entre ferramentas de linha de comando e ferramentas dedicadas de banco de dados. A partir daí, oferece um framework prático para encontrar as interfaces certas para as necessidades do seu agente.</p><h2>O que "construir contexto" realmente significa para um agente?</h2><p>Nos primeiros <a href="https://www.elastic.co/what-is/retrieval-augmented-generation">pipelines de Retrieval-Augmented Generation (RAG)</a>, o desenvolvedor projetou um pipeline de recuperação fixo, e o modelo de linguagem grande (LLM) era um receptor passivo do contexto. Essa limitação era fundamental: o contexto era recuperado em cada consulta, fosse necessário ou não, sem checar se realmente ajudava.</p><p>Com a transição para o RAG agêntico, os agentes agora têm acesso a um conjunto de ferramentas de busca para criar o próprio contexto. Por exemplo, tanto o Claude Code [1] quanto o Cursor [2] permitem que o agente escolha diferentes ferramentas de busca e até as combine para consultas encadeadas, dependendo do que a tarefa realmente exige.</p><h2>Quais interfaces de busca existem para engenharia de contexto?</h2><p>O contexto pode estar em diferentes locais, como na web, em um sistema de arquivos local ou em um banco de dados. O agente pode interagir com cada uma dessas fontes de dados fora de contexto em diferentes ferramentas:</p><ul><li><p><strong>As ferramentas de linha de comando</strong> podem executar comandos de linha de comando e ter acesso ao sistema de arquivos local. Alguns exemplos de ferramentas de linha de comando integradas são <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool">a ferramenta bash da API Claude</a>, <a href="https://docs.openclaw.ai/tools/exec">a ferramenta exec do OpenClaw</a> e <a href="https://docs.langchain.com/oss/python/integrations/tools/bash">a ferramenta de linha de comando do LangChain</a>.</p></li><li><p><strong>Ferramentas de banco de dados dedicadas,</strong> como ferramentas de um servidor Model Context Protocol (MCP) (por exemplo, o <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/mcp-server">servidor MCP do Elastic Agent Builder)</a> ou ferramentas personalizadas (por exemplo, <code>run_esql(query)</code> ou <code>db_list_index()</code>), podem consultar bancos de dados.</p></li><li><p><strong>Ferramentas dedicadas de busca de arquivos</strong> podem buscar e ler arquivos locais (ou carregados), sem acesso total à linha de comando. Alguns exemplos de ferramentas integradas de busca de arquivos são o <a href="https://ai.google.dev/gemini-api/docs/file-search">File Search Tool da API do Gemini</a> e o <a href="https://developers.openai.com/api/docs/guides/tools-file-search">File Search Tool da OpenAI</a>.</p></li><li><p><strong>Ferramentas de busca na web</strong> podem recuperar informações da web.</p></li><li><p><strong>Ferramentas de memória</strong> armazenam e recuperam da memória de longo prazo (independentemente de como esteja armazenada).</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2c5d083815149773/6a170acb964cea61a108bb80/115f20c8ded259e508f51524b2c06bdc702d70ab-1999x1050.png" alt="Diagrama que mostra como um agente usa diferentes ferramentas de recuperação de contexto para acessar arquivos locais, dados proprietários, a web e a memória de longo prazo." /><p>Como você pode ver, a ferramenta shell é versátil e pode ser usada para recuperar contexto de diferentes fontes de dados, incluindo:</p><ul><li><p><strong>Sistema de arquivos:</strong> o agente explora a estrutura de diretórios (ls, find), busca conteúdo relevante (grep, cat) e repete o processo até obter contexto suficiente.</p></li><li><p><strong>Banco de dados:</strong> o agente pode usar ferramentas de linha de comando (CLI) para banco de dados (p. ex., <a href="https://www.elastic.co/docs/reference/query-languages/sql/sql-cli"><code>elasticsearch-sql-cli</code></a>), chamar APIs HTTP via curl ou executar scripts. Isso é útil principalmente em combinação com as habilidades do agente, que são exemplos reutilizáveis e documentados inseridos no contexto do agente para orientar o uso correto das ferramentas (p. ex., <a href="https://github.com/elastic/agent-skills">Elastic Agent Skills para Elasticsearch</a>).</p></li><li><p><strong>Web: </strong>o agente pode executar buscas na web usando o comando curl via API de um provedor de busca.</p></li></ul><p>No entanto, a ferramenta de linha de comando dá acesso direto ao sistema e, portanto, exige medidas de segurança, como execução em ambiente sandbox isolado e logging de todos os comandos executados.</p><h2>Quando usar as diferentes interfaces de busca</h2><p>A interface de busca certa depende dos seus dados, dos seus padrões de consulta e do seu caso de uso. Esta seção serve como um ponto de partida prático.</p><h3>Sistemas de arquivos não tornam bancos de dados obsoletos</h3><p>A discussão entre sistemas de arquivos e bancos de dados não envolve a camada de armazenamento. Por exemplo, o LangChain explica que <a href="https://x.com/hwchase17/status/2011814697889316930">seu sistema de memória</a> na verdade não armazena memória em um sistema de arquivos real. Em vez disso, ele armazena a memória em um banco de dados e a <em>representa</em> como um conjunto de arquivos para o agente [3].</p><p>Sistemas de arquivos são uma escolha natural para casos de uso nativos de arquivos, como agentes de codificação. Eles também funcionam bem como bloco de notas temporário ou memória de trabalho e para casos de usuário único ou agente único em que a concorrência não é preocupação. Nesses casos, um sistema de arquivos físico ou a representação dos dados como sistema de arquivos dá flexibilidade antes de se comprometer com uma interface específica.</p><p>Porém, o armazenamento no sistema de arquivos tem desvantagens reais, como concorrência fraca, aplicação manual de esquemas e transações atômicas. Esses fatores ficam mais evidentes quando sua aplicação precisa redimensionar ou migrar para um panorama multi-agente. Qualquer pessoa que ignore essas desvantagens está condenada a <a href="https://dx.tips/oops-database">reinventar penosamente bancos de dados piores</a>, sem as décadas de engenharia por trás da segurança das transações ou do controle de acesso que os bancos de dados de produção já oferecem. Além disso, na maioria dos contextos de negócios, você não escolhe usar o banco de dados, já que ele já existe, armazenando dados críticos para a empresa.</p><h3>Ferramenta de linha de comando e sistema de arquivos</h3><p>Ferramenta de linha de comando é o ponto de partida natural para buscas no sistema de arquivos. Atualmente, os agentes de codificação estão gerando um grande avanço no campo. Como eles trabalham com código em arquivos locais, são naturalmente casos de uso que envolvem muitos arquivos. Portanto, os LLMs são ajustados na fase pós-treinamento nas tarefas de codificação. É por isso que muitos LLMs são bons não só em escrever código como em usar comandos de linha de comando e navegar por sistemas de arquivos.</p><p>Usar uma ferramenta de linha de comando com CLIs integradas, como <code>ls</code> e <code>grep</code>, para encontrar arquivos é eficaz. Com grep, uma consulta como "Encontre todos os arquivos que importam <code>matplotlib</code>" é rápida, precisa e barata. Mas, quando o agente precisa lidar com consultas conceituais, como "Como nosso app lida com falhas na autenticação?", a correspondência de padrões com o grep pode atingir um teto muito rápido. Várias alternativas que trazem capacidades de busca semântica para a linha de comando surgiram para preencher essa lacuna, incluindo <a href="https://github.com/jina-ai/jina-grep-cli"><code>jina-grep</code></a>.</p><p>No entanto, grep e muitas das alternativas de busca semântica funcionam em O(n) sobre o corpus. Nos casos de uso em bases de código, isso pode ser suficiente. No entanto, se seus dados aumentarem, a latência será perceptível. Nesse caso, é necessário um datastore indexado para manter o desempenho.</p><h3>Ferramenta Shell + banco de dados</h3><p>Outra forma de incluir aos seus dados mais recursos de busca, como busca semântica ou híbrida, é armazená-los em um banco de dados, como o Cursor. Além disso, quando os dados exigem junções relacionais complexas ou agregações, é indispensável uma interface de banco de dados.</p><p>Quando os dados estão em um banco de dados em vez de no sistema de arquivos, uma ferramenta de linha de comando pode funcionar como uma interface leve para banco de dados em determinados casos de uso. Se suas consultas forem simples o suficiente para uma CLI ou uma chamada de curl, uma ferramenta dedicada de banco de dados pode adicionar complexidade desnecessária.</p><p>Essa abordagem também é adequada nas fases iniciais de exploração, quando você ainda não sabe quais padrões de consulta seu agente realmente desenvolverá. Nesse caso, as habilidades do agente podem fornecer ao agente estrutura suficiente para realizar consultas corretamente, sem precisar se comprometer com uma ferramenta desenvolvida especificamente para isso. No entanto, quando o agente precisa de várias iterações para encontrar a maneira correta de consultar o banco de dados para tarefas repetitivas, a sobrecarga de tokens ao usar uma ferramenta de linha de comando como interface deixa de justificar a simplicidade de evitar mais uma ferramenta.</p><h3>Ferramenta dedicada de banco de dados</h3><p>Principalmente quando padrões de consulta repetidos são estruturados ou analíticos, ferramentas dedicadas a banco de dados são necessárias. Um <a href="https://vercel.com/blog/testing-if-bash-is-all-you-need">post do blog da Vercel e da Braintrust</a> comparou agentes com diferentes conjuntos de ferramentas de busca para tarefas reais de recuperação em dados semiestruturados, como chamados de suporte ao cliente e transcrições de chamadas de vendas (por exemplo: "Quantos problemas abertos mencionam 'segurança'?" ou "Encontre problemas onde alguém relatou um bug e depois alguém enviou um PR alegando corrigir.") [4].</p><p>Agentes com ferramentas dedicadas de banco de dados usavam menos tokens, eram mais rápidos e cometiam menos erros do que agentes com apenas uma ferramenta de linha de comando e um sistema de arquivos. A lição é que ferramentas diretas de banco de dados são a opção certa quando a consulta exige raciocínio analítico sobre dados semiestruturados.</p><h3>Combinando interfaces de busca</h3><p>Nenhuma interface de busca única lida bem com todas as consultas. Por exemplo, o Cursor combina ferramentas de linha de comando (para buscas via grep) e ferramentas de busca semântica e permite que o agente selecione a ferramenta certa com base nas instruções do usuário. Eles relatam que o agente escolhe o grep para buscar símbolos ou strings específicos, a busca semântica para perguntas conceituais ou comportamentais e ambos para tarefas exploratórias.</p><p>O experimento Vercel relata o mesmo: seu agente híbrido, com acesso tanto a uma ferramenta de linha de comando quanto a uma ferramenta de banco de dados dedicada, obteve o melhor desempenho entre todos os agentes testados, usando primeiro as ferramentas de banco de dados dedicadas e, em seguida, confirmando os resultados via busca no sistema de arquivos. No entanto, essa abordagem usa mais tokens e tempo para raciocinar sobre a escolha e validação da ferramenta.</p><p>Em ambos os exemplos, o padrão é o mesmo: a composição supera qualquer interface única, mas tem como contrapartida o aumento no custo e da latência.</p><h2>Recomendações práticas para encontrar o conjunto certo de ferramentas</h2><p>O conjunto certo de interfaces de busca é pequeno, específico e adequado aos padrões reais de consulta do seu agente. A prática recomendada atual é ter um agente com o mínimo de ferramentas possível, em vez de ter um agente com centenas de ferramentas MCP. Isso ocorre porque a desvantagem de expor todas as ferramentas possíveis de antemão enche a janela de contexto e confunde o agente sobre qual ferramenta realmente usar. Por exemplo, o Claude Code supostamente tem apenas cerca de 20 ferramentas.</p><p>Em vez disso, a ideia da divulgação progressiva é começar com um conjunto mínimo de ferramentas e deixar o agente descobrir outros recursos somente quando necessário. Pesquisas da Anthropic [5] e da Cursor [6] mostraram que essa abordagem gera uma economia de tokens entre 47%–85%. O Claude Code, por exemplo, implementa isso diretamente, permitindo que o agente descubra de forma incremental como consultar uma API ou um banco de dados, sem que esse conhecimento consuma contexto em cada chamada LLM.</p><p>Após saber os padrões de consulta do agente, você pode revisitar o conjunto de ferramentas de busca às quais o agente tem acesso como padrão. Uma forma útil de pensar sobre essa troca é o <a href="https://www.elastic.co/search-labs/blog/database-retrieval-tools-context-engineering#building-the-right-database-retrieval-tools-%5C(%E2%80%9Clow-floor,-high-ceiling%E2%80%9D%5C">princípio "piso baixo, teto alto"</a> para decidir quais ferramentas devem ser selecionadas. Ferramentas "teto alto" não limitam o potencial do agente. Por exemplo, uma ferramenta de linha de comando versátil permite que o agente escreva consultas completas ao banco de dados, inclusive as ambíguas, mas ao custo de sobrecarga no raciocínio, maior latência e menor confiabilidade.</p><p>Ferramentas de baixo piso são o oposto. São ferramentas especializadas que abrangem consultas específicas e são imediatamente acessíveis ao agente com o mínimo de sobrecarga de raciocínio, gerando menor custo e maior confiabilidade. Mas eles precisam de engenharia inicial, não conseguem cobrir todas as possíveis consultas e podem dificultar para o agente escolher a ferramenta certa.</p><p>Pense em cada ferramenta como parte de um espectro: ferramentas com baixo limiar de uso são fáceis para o agente usar corretamente, mas têm escopo limitado. Já as ferramentas com alto teto (maior potencial) são versáteis, mas exigem mais raciocínio para serem usadas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt72deecc6781e3499/6a170acd5091682f4fe1baba/e6d1b973be4b0a0a25c99c74f02a47e98395a3f7-1200x630.png" alt="Diagrama comparando três abordagens de design de agente (piso alto/teto alto, piso baixo/teto baixo e baixo piso/teto alto), mostrando como diferentes estratégias de ferramentas afetam como os agentes lidam com consultas ambíguas, versáteis e previsíveis." /><p>A maioria dos agentes precisa de uma combinação de diferentes ferramentas de busca. Porém, cada ferramenta precisa justificar sua inclusão. Recomendamos começar com uma ferramenta de busca versátil (por exemplo, uma ferramenta <code>search_database()</code> ou uma ferramenta de linha de comando). Em seguida, reutilize os registros de comando que você já mantém para fins de segurança, a fim de monitorar o que seu agente realmente faz, incluindo chamadas de ferramentas, tentativas repetidas e número de chamadas por consulta de usuário. E, quando você notar um padrão de consulta se repetindo ou falhando, é hora de criar uma ferramenta específica para ele.</p><h2>Resumo</h2><p>O debate entre sistema de arquivos e banco de dados está desviando a atenção da verdadeira questão que os engenheiros deveriam se fazer: <em>quais são as interfaces de busca adequadas que o agente precisa para construir o próprio contexto?</em> A resposta mais provável é: <em>nenhuma</em>.</p><p>A ferramenta de linha de comando é versátil para interagir com diferentes fontes fora do contexto e, portanto, é um bom ponto de partida. Por outro lado, é menos eficiente e preciso nos casos de uso com consultas analíticas estruturadas do que ferramentas dedicadas a bancos de dados.</p><p>O objetivo é encontrar o conjunto mínimo de ferramentas de busca que lide bem com os padrões de consulta reais do seu agente. Comece com uma ferramenta de linha de comando e registre em log o que seu agente realmente faz. Quando um padrão de consulta se repetir e falhar, é hora de projetar ferramentas especializadas.</p><h2>Referências</h2><p>1. Thariq (Anthropic). <a href="https://x.com/trq212/status/2027463795355095314">Lessons from Building Claude Code: Seeing like an Agent</a> (2026).</p><p>2. Cursor: Documentation. <a href="https://cursor.com/docs/agent/tools/search">Semantic &amp; agentic search</a> (2026).</p><p>3. Harrison Chase (LangChain). <a href="https://x.com/hwchase17/status/2011814697889316930">How we built Agent Builder’s memory system</a> (2026).</p><p>4. Ankur Goyal (Braintrust) and Andrew Qu (Vercel). <a href="https://vercel.com/blog/testing-if-bash-is-all-you-need">Testing if "bash is all you need"</a> (2026).</p><p>5. Anthropic. <a href="https://www.anthropic.com/engineering/advanced-tool-use">Introducing advanced tool use on the Claude Developer Platform</a> (2025).</p><p>6. Cursor. <a href="https://cursor.com/blog/dynamic-context-discovery">Dynamic context discovery</a> (2026).</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/search-tools-context-engineering</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/search-tools-context-engineering</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Leonie Monigatti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1b9bbbff55c09fa4/6a170acecdacbff1167d29fd/f91e4d07915ba7bf3b7abf15fac8fab3350f7df2-1280x720.png" length="0" type="image/png"/>
    <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Usando a API de Inferência Elasticsearch junto com modelos de Hugging Face]]></title>
    <description><![CDATA[Aprenda a conectar o Elasticsearch a modelos do Hugging Face usando endpoints de inferência e a construir um sistema multilíngue de recomendação de blogs com busca semântica e conclusões de chat.]]></description>
    <content:encoded><![CDATA[<p>Em atualizações recentes, o Elasticsearch introduziu uma integração nativa para conectar a modelos hospedados no <a href="https://endpoints.huggingface.co/">Hugging Face Inference Service</a>. Neste post, vamos explorar como configurar essa integração e realizar inferência por meio de chamadas simples de API usando um grande modelo de linguagem (LLM). Vamos usar <a href="https://huggingface.co/HuggingFaceTB/SmolLM3-3B">SmolLM3-3B</a>, um modelo leve de uso geral com bom equilíbrio entre uso de recursos e qualidade da resposta.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9094997548bd70f8/6a170d6a839dfa0ad6dcff54/7ddadf1976421a860a7d62087239adb9150d808b-1999x1388.png" alt="Gráfico de dispersão mostrando vários modelos de linguagem pequenos plotados pelo tamanho do modelo (em bilhões de parâmetros) no eixo x e a taxa de vitória (em porcentagem) no eixo y. O SmolLM3‑3B aparece no topo da tendência de eficiência, com uma taxa de vitória maior do que outros modelos de tamanho semelhante." /><h2>Pré-requisitos</h2><ul><li><p><strong>Elasticsearch 9.3 ou Elastic Cloud Serverless: </strong>você pode criar uma implantação na nuvem seguindo <a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/elastic-cloud">essas instruções</a>, ou você pode usar o <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart#local-dev-quick-start"><code>start-local</code></a> quickstart.</p></li><li><p><strong>Python 3.12: </strong>baixe o Python <a href="https://www.python.org/">aqui</a>.</p></li><li><p><strong>Hugging Face </strong><a href="https://huggingface.co/docs/hub/en/security-tokens">Token de acesso</a>.</p></li></ul><h2>Chat completions usando um endpoint de inferência do Hugging Face</h2><p>Primeiro, vamos construir um exemplo prático que conecta o Elasticsearch a um <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put">endpoint de inferência</a> Hugging Face para gerar recomendações baseadas em IA a partir de uma coleção de artigos de blog. Para a base de conhecimento do app, usaremos um conjunto de dados de artigos de blog da empresa, que contém informações valiosas, mas frequentemente difíceis de navegar.</p><p>Com este endpoint, a <a href="https://www.elastic.co/docs/solutions/search/semantic-search">busca semântica</a> recupera os artigos mais relevantes para uma consulta específica, e um Hugging Face LLM gera recomendações curtas e contextuais com base nesses resultados.</p><p>Vamos dar uma olhada em uma visão geral do fluxo de informações que vamos criar:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf217b7b7db4e1e6c/6a170d6ca929cf8022ae0a3b/1dfbc2323438feaaa42e13ab242dd1f7166f74aa-1200x676.png" alt="Diagrama de fluxo mostrando um índice Elasticsearch que fornece resultados de busca semântica para um endpoint de inferência, que retorna recomendações de artigos." /><p>Neste artigo, testaremos a <strong>capacidade do SmolLM3-3B </strong>decombinar seu tamanho compacto com fortes capacidades de raciocínio multíngue e chamada de ferramentas. Com base em uma consulta de busca, enviaremos todo o conteúdo correspondente (em inglês e espanhol) para o LLM para gerar uma lista de artigos recomendados com uma descrição personalizada com base na consulta de busca e nos resultados.</p><p>Veja como poderia ser a UI de um site de artigos com um sistema de geração de recomendações por IA.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt20e69b9a06fecd65/6a170d6e839dfa6f97dcff58/8d3b86b212f28ff279f2da67a33e6134039f0e4e-1999x949.png" alt="UI de um site de artigos com um sistema de geração de recomendações por IA, listando três exemplos, com texto em inglês e títulos em inglês ou espanhol." /><p>Você pode encontrar a implementação completa desta aplicação no <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/notebook.ipynb">notebook</a> vinculado.</p><h3>Configuração de endpoints de inferência do Elasticsearch</h3><p>Para usar o <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-hugging-face">endpoint de inferência do Hugging Face</a> no Elasticsearch, precisamos de dois elementos importantes: uma chave de API do Hugging Face e uma URL de endpoint do Hugging Face em execução. Ela deverá ficar assim:</p>PUT _inference/chat_completions/hugging-face-smollm3-3b
{
    "service": "hugging_face",
    "service_settings": {
        "api_key": "hugging-face-access-token", 
        "url": "url-endpoint" 
    }
}<p>O endpoint de inferência Hugging Face no Elasticsearch permite diferentes tipos de tarefas: <code>text_embedding</code>, <code>completion</code>, <code>chat_completion</code>, e <code>rerank</code>. Neste post do blog, usamos <code>chat_completion</code> porque precisamos que o modelo gere recomendações conversacionais baseadas nos resultados de busca e em um prompt do sistema. Esse endpoint nos permite realizar preenchimentos de chat diretamente do Elasticsearch de forma simples usando a API do Elasticsearch:</p>POST _inference/chat_completion/hugging-face-smollm3-3b/_stream
{
  "messages": [
      { "role": "user", "content": "&lt;user prompt&gt;" }
  ]
}<p>Isso servirá como o núcleo da aplicação, recebendo o prompt e os resultados de busca que passarão pelo modelo. Com a teoria explicada, vamos começar a implementar a aplicação.</p><h4>Configurando o endpoint de inferência no Hugging Face</h4><p>Para implantar o modelo Hugging Face, vamos usar <a href="https://huggingface.co/inference-endpoints/dedicated">implantações Hugging Face One-Click</a>, um serviço fácil e rápido para implantar endpoints de modelos. Lembre-se de que este é um serviço pago, e seu uso pode incorrer em custos adicionais. Esta etapa criará a instância do modelo que será usada para gerar as recomendações dos artigos.</p><p>Você pode escolher um modelo do catálogo de um clique.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta7bdfa43d6766324/6a170d6fb339d59e5476a039/b816e9fba1fe172687bf58f5143fb1f838c1077f-549x331.png" alt="Exibição da interface de um catálogo de modelos filtrado para &quot;smoll3&quot;, mostrando um modelo chamado &quot;smollm3‑3b&quot; com geração de texto, vLLM, GPU 1× Nvidia L4 e um preço listado de US$ 0,80, além de uma nota sugerindo que você amplie a busca para todos os modelos de Hugging Face." /><p>Vamos escolher o modelo <strong>SmolLM3-3B</strong> :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb0a2e6ffd7deb20/6a170d710c48574b7401aafc/610d3aba0429f3666c2df3616d513eb6a4397c0c-502x478.png" alt="Interface para criar um endpoint para o modelo SmolLM3‑3B, mostrando o nome do modelo, uma nota &quot;verified by Hugging Face&quot;, um campo de nome de endpoint, um custo de US$ 0,80 por hora por réplica em execução, uma opção cURL e um botão &quot;Create Endpoint&quot;." /><p>A partir daqui, pegue o URL do endpoint do Hugging Face:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt25714021711ed6ff/6a170d72c1e8a54853f88336/025094ddb2cfbd1f0f216a5ec4e119b0f4fa2c42-646x328.png" alt="Visualização do **dashboard** de um endpoint de inferência Hugging Face chamado &quot;smollm3‑3b‑pnz&quot;, mostrando um status verde de execução, uma réplica ativa, zero solicitações na última hora, guias de navegação e o URL do endpoint exibido." /><p>Como mencionado na <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-hugging-face">documentação de endpoints de inferência Hugging Face do Elasticsearch</a>, a geração de texto requer um modelo compatível com a API OpenAI. Por esse motivo, precisamos anexar o subcaminho <code>/v1/chat/completions</code> à URL do endpoint Hugging Face. O resultado final ficará assim:</p>https://j2g31h0futopfkli.us-east-1.aws.endpoints.huggingface.cloud/v1/chat/completions<p>Com isso pronto, podemos começar a programar em um notebook Python.</p><h4>Gerando a Chave API do Hugging Face</h4><p>Crie uma <a href="https://huggingface.co/join">conta Hugging Face</a> e obtenha um token de API seguindo <a href="https://huggingface.co/docs/hub/en/security-tokens#user-access-tokens">estas instruções</a>. Você pode escolher entre três tipos de token: <em>detalhado</em> (recomendado para produção, pois fornece acesso apenas a recursos específicos); <em>de leitura</em> (para acesso somente leitura); ou <em>de gravação</em> (para acesso de leitura e gravação). Para este tutorial, um token de leitura é suficiente, já que só precisamos chamar o endpoint de inferência. Guarde esta chave para o próximo passo.</p><h4>Configurando o endpoint de inferência do Elasticsearch</h4><p>Primeiro, vamos declarar um cliente Elasticsearch Python:</p>os.environ["ELASTICSEARCH_API_KEY"] = "your-elasticsearch-api-key"
os.environ["ELASTICSEARCH_URL"] = "https://xxxx.us-central1.gcp.cloud.es.io:443"

es_client = Elasticsearch(
    os.environ["ELASTICSEARCH_URL"], api_key=os.environ["ELASTICSEARCH_API_KEY"]
)<p>Em seguida, vamos criar um endpoint de inferência no Elasticsearch que use o modelo Hugging Face. Esse endpoint nos permitirá gerar respostas com base nos posts do blog e no prompt passado para o modelo.</p>INFERENCE_ENDPOINT_ID = "smollm3-3b-pnz"

os.environ["HUGGING_FACE_INFERENCE_ENDPOINT_URL"] = (
 "https://j2g31h0futopfkli.us-east-1.aws.endpoints.huggingface.cloud/v1/chat/completions"
)
os.environ["HUGGING_FACE_API_KEY"] = "hf_xxxxx"

resp = es_client.inference.put(
        task_type="chat_completion",
        inference_id=INFERENCE_ENDPOINT_ID,
        body={
            "service": "hugging_face",
            "service_settings": {
                "api_key": os.environ["HUGGING_FACE_API_KEY"],
                "url": os.environ["HUGGING_FACE_INFERENCE_ENDPOINT_URL"],
            },
        },
    )<h3>Conjunto de dados</h3><p>O conjunto de dados contém os <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/dataset.json">posts do blog</a> que serão consultados, representando um conjunto de conteúdo multilíngue usado em todo o fluxo de trabalho:</p>// Articles dataset document example: 
{
    "id": "6",
    "title": "Complete guide to the new API: Endpoints and examples",
    "author": "Tomas Hernandez",
    "date": "2025-11-06",
    "category": "tutorial",
    "content": "This guide describes in detail all endpoints of the new API v2. It includes code examples in Python, JavaScript, and cURL for each endpoint. We cover authentication, resource creation, queries, updates, and deletion. We also explain error handling, rate limiting, and best practices. Complete documentation is available on our developer portal."
  }<h4>Mapeamento do Elasticsearch</h4><p>Com o conjunto de dados definido, precisamos criar um esquema de dados que se ajuste adequadamente à estrutura do post do blog. Os seguintes <a href="https://www.elastic.co/docs/manage-data/data-store/mapping">mapeamentos de índice</a> serão usados para armazenar os dados no Elasticsearch:</p>INDEX_NAME = "blog-posts"

mapping = {
    "mappings": {
        "properties": {
            "id": {"type": "keyword"},
            "title": {
                "type": "object",
                "properties": {
                    "original": {
                        "type": "text",
                        "copy_to": "semantic_field",
                        "fields": {"keyword": {"type": "keyword"}},
                    },
                    "translated_title": {
                        "type": "text",
                        "fields": {"keyword": {"type": "keyword"}},
                    },
                },
            },
            "author": {"type": "keyword", "copy_to": "semantic_field"},
            "category": {"type": "keyword", "copy_to": "semantic_field"},
            "content": {"type": "text", "copy_to": "semantic_field"},
            "date": {"type": "date"},
            "semantic_field": {"type": "semantic_text"},
        }
    }
}


es_client.indices.create(index=INDEX_NAME, body=mapping)<p>Aqui, podemos ver com mais clareza como os dados são estruturados. Usaremos busca semântica para recuperar resultados baseados em linguagem natural, junto com a propriedade <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/copy-to"><code>copy_to</code></a> para copiar o conteúdo do campo para o campo <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text"><code>semantic_text</code></a>. Além disso, o campo <code>title</code> contém dois subcampos: o subcampo <code>original</code> armazena o título em inglês ou espanhol, dependendo do idioma original do artigo; e o subcampo <code>translated_title</code> está presente apenas para artigos em espanhol e contém a tradução para o inglês do título original.</p><h3>Ingestão de dados</h3><p>O seguinte trecho de código ingere o conjunto de dados de postagens do blog no Elasticsearch usando a <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/javascript/bulk_examples">bulk API</a>:</p>def build_data(json_file, index_name):
    with open(json_file, "r") as f:
        data = json.load(f)

    for doc in data:
        action = {"_index": index_name, "_source": doc}
        yield action


try:
    success, failed = helpers.bulk(
        es_client,
        build_data("dataset.json", INDEX_NAME),
    )
    print(f"{success} documents indexed successfully")

    if failed:
        print(f"Errors: {failed}")
except Exception as e:
    print(f"Error: {str(e)}")<p>Agora que os artigos já estão no Elasticsearch, precisamos criar uma função capaz de buscar no campo <code>semantic_text</code>:</p>def perform_semantic_search(query_text, index_name=INDEX_NAME, size=5):
    try:
        query = {
            "query": {
                "match": {
                    "semantic_field": {
                        "query": query_text,
                    }
                }
            },
            "size": size,
        }

        response = es_client.search(index=index_name, body=query)
        hits = response["hits"]["hits"]

        return hits
    except Exception as e:
        print(f"Semantic search error: {str(e)}")
        return []<p>Precisamos também de uma função que chame o endpoint de inferência. Neste caso, chamaremos o endpoint usando <strong><code>chat_completion</code></strong>tipo de tarefa para obter respostas de streaming:</p>def stream_chat_completion(messages: list, inference_id: str = INFERENCE_ENDPOINT_ID):
    url = f"{ELASTICSEARCH_URL}/_inference/chat_completion/{inference_id}/_stream"
    payload = {"messages": messages}
    headers = {
        "Authorization": f"ApiKey {ELASTICSEARCH_API_KEY}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.post(url, json=payload, headers=headers, stream=True)
        response.raise_for_status()

        for line in response.iter_lines(decode_unicode=True):
            if line:
                line = line.strip()

                if line.startswith("event:"):
                    continue

                if line.startswith("data: "):
                    data_content = line[6:]

                    if not data_content.strip() or data_content.strip() == "[DONE]":
                        continue

                    try:
                        chunk_data = json.loads(data_content)

                        if "choices" in chunk_data and len(chunk_data["choices"]) &gt; 0:
                            choice = chunk_data["choices"][0]
                            if "delta" in choice and "content" in choice["delta"]:
                                content = choice["delta"]["content"]
                                if content:
                                    yield content

                    except json.JSONDecodeError as json_err:
                        print(f"\nJSON decode error: {json_err}")
                        print(f"Problematic data: {data_content}")
                        continue

    except requests.exceptions.RequestException as e:
        yield f"Error: {str(e)}"<p>Agora podemos escrever uma função que chama a função de busca semântica, junto com o endpoint de inferência <code>chat_completions</code> e o endpoint de recomendações, para gerar os dados que serão alocados nos cartões:</p>def recommend_articles(search_query, index_name=INDEX_NAME, max_articles=5):
    print(f"\n{'='*80}")
    print(f"🔍 Search Query: {search_query}")
    print(f"{'='*80}\n")

    articles = perform_semantic_search(search_query, index_name, size=max_articles)

    if not articles:
        print("❌ No relevant articles found.")
        return None, None

    print(f"✅ Found {len(articles)} relevant articles\n")

    # Build context with found articles
    context = "Available blog articles:\n\n"
    for i, article in enumerate(articles, 1):
        source = article.get("_source", article)
        context += f"Article {i}:\n"
        context += f"- Title: {source.get('title', 'N/A')}\n"
        context += f"- Author: {source.get('author', 'N/A')}\n"
        context += f"- Category: {source.get('category', 'N/A')}\n"
        context += f"- Date: {source.get('date', 'N/A')}\n"
        context += f"- Content: {source.get('content', 'N/A')}\n\n"

    system_prompt = """You are an expert content curator that recommends blog articles.

    Write recommendations in a conversational style starting with phrases like:
    - "If you're interested in [topic], this article..."
    - "This post complements your search with..."
    - "For those looking into [topic], this article provides..."


    FORMAT REQUIREMENTS:
    - Return ONLY a JSON array
    - Each element must have EXACTLY these three fields: "article_number", "title", "recommendation"
    - If the original title is in spanish, use the "translated_title" subfield in the "title" field

    Keep each recommendation concise (2-3 sentences max) and focused on VALUE to the reader.

    EXAMPLE OF CORRECT FORMAT:
    [
        {"article_number": 1, "title": "Article title in english", "recommendation": "If you are interested in [topic], this article provides..."},
        {"article_number": 2, "title": "Article title in english", "recommendation": " for those looking into [topic], this article provides..."}
    ]

    Return ONLY the JSON array following this exact structure."""

    user_prompt = f"""Search query: "{search_query}"

    Generate recommendations for the following articles: {context}
    """

    messages = [
        {"role": "system", "content": "/no_think"},
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt},
    ]

    # LLM generation
    print(f"{'='*80}")
    print("🤖 Generating personalized recommendations...\n")

    full_response = ""

    for chunk in stream_chat_completion(messages):
        print(chunk, end="", flush=True)
        full_response += chunk

    return context, articles, full_response<p>Finalmente, precisamos extrair as informações e formatá-las para serem impressas:</p>def display_recommendation_cards(articles, recommendations_text):
    print("\n" + "=" * 100)
    print("📇 RECOMMENDED ARTICLES".center(100))
    print("=" * 100 + "\n")

    # Parse JSON recommendations - clean tags and extract JSON
    recommendations_list = []
    try:

        # Clean up &lt;think&gt; tags
        cleaned_text = re.sub(
            r"&lt;think&gt;.*?&lt;/think&gt;", "", recommendations_text, flags=re.DOTALL
        )
        # Remove markdown code blocks ( ... ``` or ``` ... ```)
        cleaned_text = re.sub(r"```(?:json)?", "", cleaned_text)
        cleaned_text = cleaned_text.strip()

        parsed = json.loads(cleaned_text)

        # Extract recommendations from list format
        for item in parsed:
            article_number = item.get("article_number")
            title = item.get("title", "")
            rec_text = item.get("recommendation", "")

            if article_number and rec_text:
                recommendations_list.append(
                    {
                        "article_number": article_number,
                        "title": title,
                        "recommendation": rec_text,
                    }
                )
    except json.JSONDecodeError as e:
        print(f"⚠️  Could not parse recommendations as JSON: {e}")
        return

    for i, article in enumerate(articles, 1):
        source = article.get("_source", article)

        # Card border
        print("┌" + "─" * 98 + "┐")

        # Find recommendation and title for this article number
        recommendation = None
        title = None
        for rec in recommendations_list:
            if rec.get("article_number") == i:
                recommendation = rec.get("recommendation")
                title = rec.get("title")
                break

        # Print title
        title_lines = textwrap.wrap(f"📌 {title}", width=94)
        for line in title_lines:
            print(f"│  {line}".ljust(99) + "│")

        # Card border
        print("├" + "─" * 98 + "┤")

        # Print recommendation
        if recommendation:
            recommendation_lines = textwrap.wrap(recommendation, width=94)
            for line in recommendation_lines:
                print(f"│  {line}".ljust(99) + "│")

        # Card bottom
        print("└" + "─" * 98 + "┘")<p>Vamos testar isso fazendo uma pergunta sobre as postagens do blog de segurança:</p>search_query = "Security and vulnerabilities"

context, articles, recommendations = recommend_articles(search_query)

print("\nElasticsearch context:\n", context)

# Display visual cards
display_recommendation_cards(articles, recommendations)<p>Aqui podemos ver os cartões no console gerados pelo fluxo de trabalho:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4aa221a08a51aeb3/6a170d7460084be1413c45d6/730d35212594bb3db30447c3ea7e2a92857287b7-1999x1515.png" alt="Seção intitulada &quot;Artigos Recomendados&quot; apresenta cinco resumos de artigos em caixa, incluindo tópicos sobre vulnerabilidade no sistema de autenticação, riscos de migração, desempenho da REST API v2 e melhorias na autenticação, mudanças no sistema de notificações e um guia completo para a nova API." /><p>Você pode ver os resultados completos, incluindo todos os acertos e a resposta do LLM, <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/results.md">neste arquivo</a>.</p><p>Estamos pedindo artigos relacionados a: "Segurança e vulnerabilidades." Esta pergunta é usada como consulta de busca nos documentos armazenados no Elasticsearch. Os resultados recuperados são então passados para o modelo, que gera recomendações com base em seu conteúdo. Como podemos ver, o modelo fez um ótimo trabalho criando textos curtos envolventes que podem motivar o leitor a clicar.</p><h2>Conclusão</h2><p>Este exemplo mostra como Elasticsearch e Hugging Face podem ser combinados para criar um sistema centralizado rápido e eficiente para aplicações de IA. Essa abordagem reduz o esforço manual e oferece flexibilidade, graças ao extenso catálogo de modelos da Hugging Face. O uso do SmolLM3-3B, em particular, demonstra como modelos compactos e multilíngues ainda podem fornecer raciocínio significativo e geração de conteúdo quando combinados com busca semântica. Juntas, essas ferramentas oferecem uma base escalável e eficaz para construir análises inteligentes de conteúdo e aplicações multilíngues.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hugging-face-elasticsearch-inference-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hugging-face-elasticsearch-inference-api</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5f961af4cb26ec97/6a170d767d8d6790c770e790/1417d6ff033712206c9bd4bcc22074ee3437ce96-1999x1125.png" length="0" type="image/png"/>
    <pubDate>Mon, 23 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[A extensão Gemini CLI para Elasticsearch com ferramentas e recursos]]></title>
    <description><![CDATA[Apresentamos a extensão da Elastic para a CLI Gemini do Google, que permite buscar, extrair e analisar dados do Elasticsearch em fluxos de trabalho de desenvolvedores e agentes.
]]></description>
    <content:encoded><![CDATA[<p>Temos a satisfação de anunciar o lançamento da nossa extensão Elastic para a Gemini CLI do Google, trazendo toda a eficiência da <a href="https://www.elastic.co/elasticsearch">Elasticsearch</a> e <a href="https://www.elastic.co/elasticsearch/agent-builder">Elastic Agent Builder</a> diretamente para o seu fluxo de trabalho de desenvolvimento de IA. Essa extensão também oferece várias habilidades de agente recentemente desenvolvidas para interagir com o Elasticsearch.</p><p>A extensão está disponível como um projeto open source <a href="https://github.com/elastic/gemini-cli-elasticsearch">aqui</a>.</p><h2>O que é a Gemini CLI e como você a instala?</h2><p><a href="https://geminicli.com/">Gemini CLI</a> é um agente de IA open source que traz os modelos Gemini do Google diretamente para a linha de comando. Ele permite que os desenvolvedores interajam com a IA a partir do terminal para realizar tarefas como gerar código, editar arquivos, executar comandos do shell e recuperar informações da web.</p><p>Diferentemente das interfaces típicas de chat, a Gemini CLI se integra ao seu ambiente local de desenvolvimento, o que significa que ela pode entender o contexto do projeto, modificar arquivos, executar builds ou testes e automatizar fluxos de trabalho diretamente no terminal. Isso a torna útil para desenvolvedores, engenheiros de confiabilidade de sites (SREs) e outros profissionais que desejam codificação e automação assistidas por IA sem sair do fluxo de trabalho da linha de comando.</p><p>Você pode instalar a Gemini CLI usando vários gerenciadores de pacotes. O método mais comum é usar o npm:</p>npm install -g @google/gemini-cli<p>Para conhecer opções alternativas de instalação, consulte a <a href="https://geminicli.com/docs/get-started/installation/">página oficial de instalação</a>.</p><p>Após a instalação, inicie a CLI executando:</p>gemini<p>Você vê uma tela, conforme mostrado na Figura 1:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4ff43abe550941b4/6a17072ba29299fc2ad00fa4/6dfcec4a77b3dc83bf0d974417bf2e211abb1f4f-876x468.png" alt="Uma captura de tela da Gemini CLI." /><h2>Configurar o Elasticsearch</h2><p>Precisamos ter uma instância do Elasticsearch em execução. Se quiser usar o servidor MCP (Model Context Protocol), você também precisará ter o Kibana 9.3+ instalado. Para usar a habilidade da Elasticsearch linguagem de consulta (ES|QL) (<code>esql</code>) descrita abaixo, o Kibana não é necessário.</p><p>Você pode ativar um teste gratuito no <a href="https://www.elastic.co/cloud">Elastic Cloud</a> ou instalá-lo localmente usando o script <a href="https://github.com/elastic/start-local"><code>start-local</code></a> :</p>curl -fsSL https://elastic.co/start-local | sh<p>Isso instalará o Elasticsearch e o Kibana no seu computador e gerará uma chave API para ser usada na configuração da Gemini CLI.</p><p>A chave API será mostrada como saída do comando anterior e armazenada em um <strong>.env</strong> arquivo na pasta <strong><code>elastic-start-local</code></strong>.</p><p>Se você está usando o Elasticsearch no local (por exemplo, usando <code>start-local</code>), e quer usar o Elastic Agent Builder com MCP, também precisa conectar um grande modelo de linguagem (LLM). Você pode ler <a href="https://www.elastic.co/docs/explore-analyze/ai-features/llm-guides/llm-connectors">esta página de documentação</a> para entender as diferentes opções.</p><p>Se você estiver usando o Elastic Cloud (ou serverless), já tem uma conexão LLM pré-configurada.</p><h2>Instale a extensão do Elasticsearch</h2><p>Você pode instalar a extensão Elasticsearch para Gemini CLI com o seguinte comando:</p>gemini extensions install https://github.com/elastic/gemini-cli-elasticsearch<p>Você pode verificar se as extensões foram instaladas com sucesso abrindo o Gemini e executando o seguinte comando:</p>/extensions list<p>Você deverá ver a extensão Elasticsearch disponível.</p><p>Se quiser usar a integração MCP, precisa ter uma versão do Elasticsearch 9.3+ instalada. Você precisa da URL do seu servidor MCP do <a href="https://www.elastic.co/kibana">Kibana</a>:</p><ul><li><p>Obtenha a URL do seu servidor MCP em Agents &gt; View all tools &gt; Manage MCP &gt; Copy MCP Server URL (Agentes &gt; Ver todas as ferramentas &gt; Gerenciar MCP &gt; Copiar URL do Servidor MCP).</p></li><li><p>A URL ficará assim: https://your-kibana-instance/api/agent_builder/mcp</p></li></ul><p>Você precisa da URL do endpoint do Elasticsearch. Isso normalmente é relatado no topo da página do Kibana Elasticsearch. Se você está rodando o Elasticsearch com <code>start-local</code>, você já tem o endpoint na chave <code>ES_LOCAL_URL</code> no <code>start-local</code> .env. arquivo.</p><p>Também é necessário uma chave de API. Se estiver executando o Elasticsearch com <code>start-local</code>, você já tem a <code>ES_LOCAL_API_KEY</code> no arquivo<code>start-local</code> .env arquivo. Caso contrário, é possível criar uma chave de API usando a interface do Kibana, conforme <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys">indicado aqui</a>:</p><ul><li><p>No Kibana: Stack Management &gt; Security &gt; API Keys &gt; Create API Key (Stack management &gt; Segurança &gt; Chaves de API &gt; Criar chave de API) .</p></li><li><p>Sugerimos definir apenas os privilégios de leitura para a chave API, habilitando o privilégio <code>feature_agentBuilder.read</code> conforme <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/permissions#grant-access-with-roles">reportado aqui</a>.</p></li><li><p>Copie o valor da chave de API codificada.</p></li></ul><p>Defina as variáveis de ambiente necessárias no seu shell:</p>export ELASTIC_URL="your-elasticsearch-url"
export ELASTIC_MCP_URL="your-elasticsearch-mcp-url"
export ELASTIC_API_KEY="your-encoded-api-key"<h2>Instale o conjunto de dados de exemplo</h2><p>Você pode instalar o conjunto de dados de <strong>pedidos de comércio eletrônico </strong>disponível no Kibana. Inclui um único índice chamado <strong><code>kibana_sample_data_ecommerce</code></strong>, contendo informações sobre 4.675 pedidos de um website. Para cada pedido, temos as seguintes informações:</p><ul><li><p>Informações do cliente (nome, ID, data de nascimento, e-mail e mais).</p></li><li><p>Data do pedido.</p></li><li><p>ID do pedido.</p></li><li><p>Produtos (lista de todos os produtos com preço, quantidade, ID, categoria, desconto e outros detalhes).</p></li><li><p>SKU.</p></li><li><p>Preço total (sem impostos, com impostos).</p></li><li><p>Quantidade total.</p></li><li><p>Informações geográficas (cidade, país, continente, localização, região).</p></li></ul><p>Para instalar os dados de exemplo, abra a página <strong>Integrações</strong> no Kibana (busque por “Integração” na barra de busca superior) e instale os <strong>Dados de Exemplo</strong>. Para mais detalhes, consulte a <a href="https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana">documentação aqui</a>.</p><p>O objetivo deste artigo é mostrar como é fácil configurar o Gemini CLI para se conectar ao Elasticsearch e interagir com o índice <strong><code>kibana_sample_data_ecommerce</code></strong>.</p><h2>Como usar o Elasticsearch MCP</h2><p>Você pode verificar a conexão usando o seguinte comando no Gemini:</p>/mcp list<p>Você deve ver o <strong><code>elastic-agent-builder</code></strong> ativado, como mostrado na Figura 2:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt52b85e7255360f3b/6a17072da929cf33d3ae08f5/1508423bc1d1bc3c04a1cb01e2d59495a3516ed1-1465x844.png" alt="O servidor MCP 'elastic-agent-builder' com a lista de ferramentas." /><p>O Elasticsearch fornece um conjunto padrão de ferramentas. Veja a descrição <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/tools/builtin-tools-reference">aqui</a>.</p><p>Usando essas ferramentas, você pode interagir com o Elasticsearch, fazendo perguntas como:</p><ul><li><p><code>Give me the list of all the indexes available in Elasticsearch.</code></p></li><li><p><code>How many customers are based in the USA in the kibana_sample_data_ecommerce index of Elasticsearch?</code></p></li></ul><p>Dependendo da pergunta, o Gemini usará uma ou mais ferramentas disponíveis para tentar respondê-la.</p><h2>Os comandos /elastic</h2><p>Na extensão Elasticsearch para Gemini CLI, também adicionamos<strong><code>/elastic</code></strong> comandos.</p><p>Se você executar o comando <strong><code>/help</code></strong>, verá todas as opções de <code>/elastic</code> disponíveis (Figura 3):</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt741c7451ecab10d2/6a17072ea6c2b9ccd6e79643/5b2a0727ce7a04354878dd048253d3f4d062324b-1983x230.png" alt="Os comandos '/elastic' disponíveis." /><p>Esses comandos podem ser úteis se você quiser executar diretamente uma ferramenta específica do servidor MCP.<code>elastic-agent-builder</code>  Por exemplo, usando o seguinte comando, você pode obter o mapeamento do <code>kibana_sample_data_ecommerce</code>:</p>/elastic:get-mapping kibana_sample_data_ecommerce<p>Esses comandos são essencialmente atalhos para executar ferramentas específicas, em vez de depender do modelo Gemini para determinar qual ferramenta deve ser usada.</p><h2>Como usar as habilidades do Elasticsearch</h2><p>Essa extensão também inclui uma <a href="https://github.com/elastic/gemini-cli-elasticsearch/tree/main/skills/esql">habilidade de agente para o ES|QL</a>, a <a href="https://www.elastic.co/docs/explore-analyze/discover/try-esql">Linguagem de Consulta Elasticsearch</a> disponível no Elasticsearch. <a href="https://agentskills.io/home">Agent Skills</a> é um formato aberto que fornece aos agentes de programação de IA, como o Gemini CLI, instruções personalizadas para tarefas específicas. Eles utilizam um conceito chamado <em>divulgação progressiva</em>, o que significa que apenas uma breve descrição da habilidade é adicionada ao prompt inicial do sistema. Quando você solicita que o agente execute uma tarefa, como consultar o Elasticsearch, ele associa a solicitação à habilidade relevante e carrega dinamicamente as instruções detalhadas. Essa é uma forma eficiente de gerenciar orçamentos de tokens enquanto fornece à IA exatamente o contexto que ela precisa.</p><p>A<strong> habilidade</strong> <strong><code>esql</code></strong>foi projetada para permitir que o Gemini CLI escreva e execute consultas ES|QL diretamente no seu cluster. ES|QL é uma poderosa linguagem de consulta encadeada que torna a exploração de dados, a análise de logs e as agregações altamente intuitivas. Com essa habilidade ativada, você não precisa pesquisar a sintaxe ES|QL; basta fazer perguntas em linguagem natural ao Gemini CLI sobre seus dados e o agente cuidará do resto.</p><p>As execuções são realizadas usando simples comandos <a href="https://curl.se/">curl</a> executados em um terminal. Isso é possível porque o Elasticsearch oferece um conjunto abrangente de APIs REST que podem ser facilmente usadas para integrar o sistema a qualquer arquitetura.</p><p><strong>O que a </strong><strong> habilidadeesqloferece:</strong></p><ul><li><p><strong>Descoberta de índices e esquemas:</strong> o agente pode usar as ferramentas integradas da habilidade para listar os índices disponíveis e buscar mapeamentos de campo. Por exemplo, antes de escrever uma consulta para o conjunto de dados de comércio eletrônico, o agente pode executar uma verificação de esquema em <strong><code>kibana_sample_data_ecommerce</code></strong> para entender os campos disponíveis, como <strong><code>taxful_total_price</code></strong> ou <strong><code>category</code></strong>.</p></li><li><p><strong>Tradução perfeita da linguagem natural:</strong> a habilidade dá ao agente mais do que um simples manual de referência; ela fornece um guia específico para interpretar a intenção do usuário. Quando você digita solicitações em linguagem natural, como "Mostrar tempo médio de resposta agrupado por serviço", o agente usa o padrão de correspondência da habilidade para traduzir instantaneamente suas palavras nas agregações, filtros e comandos ES|QL corretos.</p></li><li><p><strong>Autocorreção:</strong> Se uma consulta falhar (por exemplo, devido a uma incompatibilidade de tipo ou erro de sintaxe), a skill retorna a consulta gerada juntamente com a mensagem de erro exata do Elasticsearch, permitindo que o agente corrija instantaneamente a consulta e tente novamente sem que você precise intervir.</p></li></ul><p>Como a habilidade <code>esql</code> também está disponível como ferramenta no servidor MCP <code>elastic-agent-builder</code>, precisamos desativar esse servidor momentaneamente. Você pode usar o seguinte comando para desativá-lo:</p>/mcp disable elastic-agent-builder<p>Em seguida, você pode simplesmente digitar um prompt como esse em sua Gemini CLI:</p>Find the top 5 product categories by total sales revenue in the kibana_sample_data_ecommerce index<p>O agente irá:</p><ul><li><p>Reconheça a necessidade da habilidade <code>esql</code> .</p></li><li><p>Verifique o esquema do <strong><code>kibana_sample_data_ecommerce</code></strong>.</p></li><li><p>Crie uma consulta ES|QL, como: <code>FROM kibana_sample_data_ecommerce | STATS total_revenue = SUM(taxful_total_price) BY category.keyword | SORT total_revenue DESC | LIMIT 5</code>.</p></li><li><p>Execute a consulta na API do Elasticsearch.</p></li><li><p>Apresente a resposta final para você diretamente no terminal.</p></li></ul><p>Aqui, apresentamos um exemplo de resposta do Gemini ao prompt anterior:</p>───────────────────────────────────────────────────────────
&gt; Find the top 5 product categories by total sales revenue in the kibana_sample_data_ecommerce index   ───────────────────────────────────────────────────────────
✓  Activate Skill "esql": Interact with Elasticsearch using ES|QL and curl. Use when querying, managing indices,  …
Skill esql activated. Resources loaded from /home/user/.gemini/extensions/elasticsearch/skills/esql: 
Showing up to 200 items (files + folders).                                                                     /home/user/.gemini/extensions/elasticsearch/skills/esql/                                                            ├───SKILL.md 
└───references/
├───esql-reference.md 
├───generation-tips.md 
└───query-patterns.md

✦ I will start by exploring the mapping of the kibana_sample_data_ecommerce index to identify the fields for product category and sales revenue. Then, I will construct and execute an ES|QL query to determine the top 5 product categories by total sales revenue.

✓  Shell curl -s "${ELASTIC_URL%/}/kibana_sample_data_ecommerce/_mapping" -H "Authorization: ApiKey $(printenv ELAS…                                                                                                                       {  
   "kibana_sample_data_ecommerce": { 
     "mappings": { 
       "properties": {
         "category": { 
           "type": "text", 
           "fields": {
             "keyword": {
               "type": "keyword"
             }
           }
         }, 
         "currency": {
           "type": "keyword"
         }, 

✦ Okay, I have the mapping. The category is products.category.keyword and sales revenue is taxful_total_price. I'll now execute the ES|QL query to get the top 5 categories by revenue.

✓  Shell curl -s -X POST "${ELASTIC_URL%/}/_query" \  -H "Authorization: ApiKey $(printenv ELASTIC_API_KEY)" \  -H …
{ 
   "took": 62,
   "is_partial": false, 
   "completion_time_in_millis": 1772805644164,
   "documents_found": 4675,
   "values_loaded": 12084, 
   "start_time_in_millis": 1772805644102, 
   "expiration_time_in_millis": 1773237644087,  
   "columns": [ 
     { 
       "name": "total_revenue",    
       "type": "double"  
     }, 
     {   
       "name": "products.category.keyword",

✦ The query for top 5 product categories by revenue was successful. I'll format the returned JSON values into a   user-friendly list.

 ✓  Shell 
                             
 Top 5 product categories by total sales revenue: 
 1. Men's Clothing: 149393.91
 2. Women's Clothing: 135099.91
 3. Women's Shoes: 105479.17
 4. Men's Shoes: 91797.92
 5. Women's Accessories: 60830.31 

✦ I've found the answer; now I'll format it for clarity.

 ✓  Shell 

 Here are the top 5 product categories by total sales revenue:                                                        
                                                                      
 | Rank | Category              | Total Revenue | 
 |------|-----------------------|---------------| 
 | 1    | Men's Clothing        | 149,393.91    |
 | 2    | Women's Clothing      | 135,099.91    |
 | 3    | Women's Shoes         | 105,479.17    |
 | 4    | Men's Shoes           | 91,797.92     | 
 | 5    | Women's Accessories   | 60,830.31     | 

✦ I've formatted and presented the answer. I'm finished.
 ───────────────────────────────────────────────────────────<p>É interessante notar como o modelo Gemini gera a resposta final mostrando todos os passos que ele segue. Aqui, você pode ver claramente a influência da habilidade no processo de raciocínio do modelo. Na primeira vez que o modelo reconhece que precisa usar uma habilidade ou executar um comando shell, ele solicita permissão usando a abordagem baseada em intervenção humana.</p><p>Ao lidar com o trabalho pesado de descoberta de esquema, geração de consultas e execução, a habilidade <code>esql</code> permite que você se concentre inteiramente nas respostas, em vez da mecânica de obtê-las. Você obterá os dados de que precisa, formatados corretamente e diretamente no seu terminal, tudo isso sem precisar escrever uma única linha de código ou alternar para outro aplicativo.</p><h2>Conclusão</h2><p>Neste artigo, apresentamos a extensão Elasticsearch para Gemini CLI que lançamos recentemente. Essa extensão oferece a você a capacidade de interagir com a instância do Elasticsearch usando o Gemini e o servidor Elasticsearch MCP fornecido pelo Elastic Agent Builder, disponível a partir da versão 9.3.0, bem como o comando <code>/elastic</code>.</p><p>Além disso, a extensão também inclui uma habilidade <code>esql</code> que converte a solicitação do usuário de linguagem natural em uma consulta ES|QL. Essa habilidade pode ser particularmente útil quando o servidor MCP não pode ser usado, pois a comunicação subjacente é conduzida por comandos curl simples executados em um terminal. O Elasticsearch oferece um conjunto abrangente de APIs REST que podem ser facilmente integradas a qualquer projeto. Isso é especialmente útil ao desenvolver aplicações de IA agêntica.</p><p>Para mais informações sobre nossa extensão Gemini CLI, acesse o repositório do projeto <a href="https://github.com/elastic/gemini-cli-elasticsearch">aqui</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/gemini-cli-extension-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/gemini-cli-extension-elasticsearch</guid>
    <category><![CDATA[Integrações]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Walter Rafelsberger,Enrico Zimuel]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4ff43abe550941b4/6a17072ba29299fc2ad00fa4/6dfcec4a77b3dc83bf0d974417bf2e211abb1f4f-876x468.png" length="0" type="image/png"/>
    <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Habilidades de agentes para Elastic: transforme agentes de IA em especialistas Elastic]]></title>
    <description><![CDATA[Dê ao seu agente de codificação de IA o conhecimento necessário para consultar, visualizar, proteger e automatizar com o Elastic Agent Skills.]]></description>
    <content:encoded><![CDATA[<p>Todo desenvolvedor, engenheiro de confiabilidade de sites (SRE) ou analista que tentou usar um agente de codificação de IA com uma Platform especializada encontrou a mesma barreira. Você pede para o agente escrever uma consulta, configurar um alerta ou investigar algo, e ele chega perto, mas não acerta. A Elastic tem uma vantagem: mais de uma década de documentação, postagens em blogs e respostas da comunidade significa que os agentes de IA já conhecem a Elastic melhor do que a maioria das plataformas de dados. Mas essa profundidade vem com ruído. APIs obsoletas ficam ao lado das atuais. Padrões desatualizados têm uma classificação tão alta quanto práticas recomendadas. O agente reproduz com confiança uma abordagem que funcionou três versões atrás, porque nos seus dados de treinamento, funcionou. O resultado é um imposto de correção: os usuários inserem manualmente a documentação no contexto, corrigem a sintaxe alucinada e contornam o agente em vez de trabalharem com ele. Pior ainda, capacidades avançadas ficam completamente sem uso, não porque os usuários não precisem delas, mas porque o agente não sabe que elas existem.</p><p>Por isso, estamos tornando o <a href="https://github.com/elastic/agent-skills">Elastic Agent Skills</a> open source: expertise nativa na plataforma para Elasticsearch, Kibana, Elastic observabilidade e Elastic Security. Adicione ao runtime do agente que você já usa e evolua seu agente de um "generalista" que precisa adivinhar muita sintaxe para um especialista com expertise real, como a capacidade de usar muitos dos padrões arquitetônicos das próprias equipes de engenharia da Elastic. Esta versão inicial de prévia técnica foca em habilidades com máxima compatibilidade com o <a href="https://www.elastic.co/cloud/serverless">Elastic Cloud Serverless</a>, mas evoluirá logo para incluir suporte aprimorado para versões anteriores da plataforma.</p><p>Além disso, a Elastic está resolvendo esse problema dos dois lados. Para agentes na plataforma Elastic, o <a href="https://www.elastic.co/search-labs/blog/agent-builder-elastic-ga">Elastic Agent Builder</a> (agora disponível de forma geral) permite que você crie e converse com agentes de IA que herdam os controles de acesso aos seus dados, usem ferramentas integradas de busca e análise e trabalhem em contexto junto com seus dashboards, alertas e investigações. Estamos trabalhando muito para garantir experiências incríveis e agêntica na plataforma Elastic. Mas nem todo agente vive dentro da Elastic. Sua equipe já usa Cursor, Claude Code ou outros tempos de execução, e esses agentes também precisam usar a Elastic da maneira certa. É aí que entra o Agent Skills.</p><h2>Por que os agentes enfrentam dificuldades com plataformas especializadas</h2><p>Grandes modelos de linguagem (LLMs) são generalistas muito capazes. Eles podem escrever Python, explicar manifestos do Kubernetes e refatorar componentes do React porque os dados de treinamento são ricos em exemplos. Mas quando se trata de trabalho específico de plataforma, do tipo que envolve linguagens de consulta proprietárias, superfícies profundas de API e práticas recomendadas específicas do domínio, eles ficam aquém de maneiras previsíveis.</p><p>Para o Elasticsearch, a lacuna aparece concretamente:</p><ul><li><p><strong>A linguagem de consulta do Elasticsearch (ES|QL) é um território novo.</strong> Os LLMs são treinados em SQL, mas o ES|QL é uma linguagem de consulta baseada em pipes com sintaxe diferente, funções distintas e semântica distinta. Os agentes escrevem consultas que parecem plausíveis, mas não são analisadas. Eles confundem <code>WHERE</code> com <code>| WHERE</code>, inventam funções que não existem e ignoram o modelo de composição baseado em pipes.</p></li><li><p><strong>As interfaces de API são amplas e abrangentes.</strong> Elasticsearch, Kibana e Elastic Security expõem centenas de APIs em busca, ingestão, alertas, regras de detecção, gerenciamento de casos, dashboards e muito mais. Um agente armado apenas com dados de treinamento gerais precisa adivinhar qual endpoint chamar, como é o corpo da solicitação e como lidar com a resposta. Ele erra com frequência suficiente para acabar com a confiança.</p></li><li><p><strong>Práticas recomendadas não estão nos dados de treinamento.</strong> Quando você deve usar <code>semantic_text</code> em vez de um pipeline de embedding personalizado? Como você deve estruturar um pipeline de ingestão para um CSV de 10GB? Qual é a sintaxe correta da regra de detecção para uma técnica <a href="https://www.elastic.co/docs/solutions/security/detect-and-alert/mitre-attandckr-coverage">MITRE ATT&amp;CK®</a>? Agentes de uso geral não têm conhecimento curado e estruturado de forma confiável e específico para Elastic, carregado por padrão. Eles teriam que procurar, e mesmo que encontrassem, documentos brutos nem sempre codificam as decisões e práticas recomendadas que profissionais habilidosos utilizam.</p></li></ul><p>O resultado: os desenvolvedores passam mais tempo corrigindo a saída do agente do que passariam escrevendo o código eles mesmos. Essa é a experiência que ninguém esperava.</p><h2>Habilidades de agentes: conhecimento de plataforma, empacotado para agentes</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2099e0ccdf446fee/6a17074bd7c022e3e1de63d4/8d16ec00d16e70a916c5eef0aaa23fcc735b7186-1067x1280.png" alt="npx skills add elastic/agent-skills" /><p>As habilidades do agente são diretórios independentes de instruções, scripts e material de referência que os tempos de execução do agente podem carregar de forma dinâmica. Quando uma habilidade está ativa, o agente tem acesso ao contexto certo na hora certa: sintaxe de consulta, padrões de API, lógica de validação, exemplos trabalhados, para que ele possa completar as tarefas corretamente na primeira tentativa.</p><p>Cada habilidade segue a especificação aberta do <a href="https://agentskills.io">agentskills.io</a>: uma pasta com um arquivo <code>SKILL.md</code> contendo metadados e instruções estruturadas. Nenhum formato proprietário, sem bloqueio. As habilidades funcionam em diferentes ambientes de execução de agentes, incluindo Cursor, Claude Code, GitHub Copilot, Windsurf, Gemini CLI, Cline, Codex e <a href="https://agentskills.io">muitos outros</a>.</p><h3>O que há na versão inicial v0.1.0?</h3><p>O primeiro conjunto de habilidades abrange cinco áreas do Elastic Stack:</p><ul><li><p>Interação com APIs do Elasticsearch (busca, indexação, clustering)</p></li><li><p>Crie e gerencie conteúdo do Kibana, como dashboards, alertas, conectores e muito mais</p></li><li><p>Especialização em Elastic Observability</p></li><li><p>Conhecimento especializado para o Elastic Security</p></li><li><p>Criando agentes eficazes no Agent Builder</p></li></ul><h3>As habilidades podem ser combinadas</h3><p>Habilidades não são monolíticas. Eles são modulares por natureza. Seu agente carrega apenas as habilidades relevantes para a tarefa em questão. Trabalhando em uma consulta ES|QL? A habilidade ES|QL é ativada. Precisa criar um dashboard a partir desses resultados? A habilidade do dashboard melhora. Está avaliando a integridade do seu aplicativo? A habilidade de avaliação de serviço entra em jogo. Está investigando um alerta de segurança? A triagem se conecta às habilidades de gerenciamento de casos e resposta à medida que a investigação avança.</p><p>Essa capacidade de composição significa que você não precisa de um único e enorme prompt que tente cobrir tudo. Cada habilidade carrega exatamente o contexto que seu domínio exige, nada mais, nada menos.</p><h2>Para desenvolvedores que criam aplicativos de pesquisa e IA</h2><p>Se você está carregando dados no Elasticsearch, escrevendo consultas ou migrando índices, as habilidades reduzem o ciclo de geração de código, ocorrência de erros e busca nos documentos para descobrir o que deu errado.</p><p>Peça ao seu agente para carregar um arquivo CSV. Ele usará uma ferramenta de ingestão de streaming que gerencia a contrapressão e infere mapeamentos a partir dos dados. Não é um loop _bulk feito manualmente que executa e fica sem memória ao processar o primeiro arquivo grande. Peça para ele consultar o ES|QL e descobrir os nomes reais de índice e esquemas de campos, escrever consultas válidas com sintaxe correta, fazer agregações apropriadas e seleção de recursos compatível com a versão, em vez de dar um palpite no estilo SQL que exige três rodadas de depuração. Ao solicitar a reindexação em todos os clusters, o sistema segue todo o fluxo de trabalho operacional: cria o destino com mapeamentos explícitos, ajusta as configurações para otimizar a taxa de transferência, executa a tarefa de forma assíncrona e restaura as configurações de produção ao terminar, em vez de chamar o método _reindex, que omite metade das etapas que um operador experiente seguiria.</p><p>Em vez de um agente que te dá um ponto de partida plausível que você precisa corrigir, você tem um que codifica a disciplina operacional que faz a saída funcionar.</p><p><strong>Exemplos de impactos do uso das Habilidades do Elastic Agent</strong></p><p>Eval</p><p>O que a habilidade alterou</p><p>es-audit-query-failed-logins</p><p>Usou os padrões de consulta do log de auditoria da funcionalidade em vez de busca genérica</p><p>es-authz-role-mapping-ldap</p><p>Emitiu a estrutura correta de chamadas de API para mapeamento de funções</p><p>esql-basic-query</p><p>Criou a sintaxe de pipe ES|QL no Query DSL</p><p>esql-error-handling</p><p>Priorize o esquema em vez de tentar adivinhar os nomes dos campos</p><p>esql-schema-discovery</p><p>Nunca adivinhou um nome de índice</p><p>es-ingest-csv-with-infer</p><p>Usou --infer-mappings sozinho, evitou combinar com --source-format cvs, o que causa um índice vazio</p><p>es-ingest-json-file</p><p>Abordagem robusta de ingestão utilizada, capaz de lidar com arquivos grandes</p><p>es-reindex-local-async</p><p>O índice de destino foi criado primeiro com réplicas: 0 e refresh_interval: "-1", depois foi feita a reindexação assíncrona. A referencia ignorou a preparação</p><p>es-security-403-privileges</p><p>Segui o fluxo de trabalho de diagnóstico da habilidade para erros de privilégio em vez de conselhos genéricos</p><h2>Para equipes de segurança</h2><p>As equipes de segurança repetem os mesmos fluxos de trabalho operacionais diariamente: triagem de alertas, ajuste de regras de detecção e gerenciamento de casos. As habilidades do agente codificam esse conhecimento processual para que seu agente de IA possa executar esses fluxos de trabalho corretamente, chamando as APIs certas na ordem certa com os nomes de campo corretos. Para um guia prático que leva você do zero a um ambiente de Elastic Security totalmente povoado sem sair do seu IDE, consulte <a href="https://www.elastic.co/security-labs/agent-skills-elastic-security">Comece a usar o Elastic Security a partir do seu agente de IA</a>.</p><h2>Para equipes de observabilidade e operações</h2><p>O novo Agent Skills for Elastic Observability reduz o trabalho operacional de instrumentar sistemas complexos, gerenciar SLOs, analisar dados complexos e avaliar a integridade dos serviços. A incorporação da expertise nativa da Elastic diretamente aos agentes de IA permite que as equipes executem fluxos de trabalho complexos de observabilidade usando uma linguagem natural simples. Isso permite que as equipes de SREs e operações resolvam incidentes com mais rapidez e mantenham sistemas confiáveis com mais facilidade. Saiba mais no <a href="https://www.elastic.co/observability-labs/blog/elastic-agent-skills-observability-workflows">blog</a>.</p><h2>Open source, especificações abertas, impulsionado pela comunidade</h2><p>Estamos lançando o Agent Skills sob a licença Apache 2.0 porque acreditamos que o conhecimento dos agentes deve ser aberto. A especificação <a href="https://agentskills.io">agentskills.io</a> que as habilidades seguem é um padrão aberto, não um formato proprietário da Elastic. Queremos que as habilidades sejam um esforço comunitário e não um privilégio isolado.</p><h2>Parte de um panorama maior</h2><p>O Agent Skills é uma parte de uma iniciativa mais ampla para tornar o Elasticsearch a plataforma de dados mais amigável para agentes disponível. Para agentes que residem na plataforma Elasticsearch, o <a href="https://www.elastic.co/search-labs/blog/agent-builder-elastic-ga">Agent Builder</a> vai além, herdando os controles de acesso e permissões dos seus dados, fornecendo ferramentas integradas e personalizadas para pesquisa e análise, e permitindo que os usuários interajam com os agentes em contexto, juntamente com dashboards, alertas e investigações. Por fim, o suporte para habilidades chegará em breve ao Agent Builder, permitindo que o desenvolvedor tenha flexibilidade para aproveitar o Elastic Agent Skills, assim como as habilidades de qualquer outra fonte, para viabilizar chat seguro, com mais contexto e automação na plataforma Elasticsearch.</p><p>Para os agentes que residem em outros locais, estamos investindo no ecossistema aberto:</p><ul><li><p><strong>Expansão do servidor Model Context Protocol (MCP):</strong> ampliação do <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/mcp-server">endpoint MCP</a> no Agent Builder com mais ferramentas além das operações atuais de busca, ES|QL e indexação.</p></li><li><p><strong>Melhorias na autenticação:</strong> facilitar a conexão segura dos agentes, com o objetivo de eliminar a necessidade de copiar e colar manualmente as chaves de API.</p></li><li><p><strong>Documentação legível por LLM:</strong> publicar arquivos <code>llms.txt</code> e <code>AGENTS.md</code> para que os agentes possam descobrir e entender as APIs da Elastic por conta própria.</p></li><li><p><strong>Uma interface de linha de comando (CLI) para fluxos de trabalho de agentes:</strong> ferramentas de linha de comando que facilitam o gerenciamento de conexões e as operações comuns dos agentes.</p></li></ul><p>Habilidades são a camada que você pode usar hoje. O restante está chegando.</p><h2>Começar</h2><p><strong>Antes de começar: </strong>os agentes de codificação de IA operam com credenciais reais, acesso real ao shell e com todas as permissões do usuário que os executa. Quando esses agentes são direcionados para fluxos de trabalho de segurança, os riscos são maiores: você está entregando a um sistema automatizado o acesso à lógica de detecção, ações de resposta e telemetria sensível. Cada perfil de risco de organização é diferente. Antes de habilitar fluxos de trabalho de segurança orientados por IA, <strong>avalie quais dados o agente pode acessar, quais ações ele pode realizar e o que acontece se ele se comportar de forma inesperada</strong>.</p><p>Instale o Elastic Agent Skills no tempo de execução do seu agente:</p><p><code>npx skills add elastic/agent-skills</code></p><p>Isso detecta automaticamente os runtimes instalados do agente e posiciona as habilidades no diretório de configuração correto. A partir daí, seu agente os coleta automaticamente.</p><p>Você também pode acessar diretamente o <a href="https://github.com/elastic/agent-skills">catálogo de habilidades</a> e instalar habilidades individuais manualmente, copiando a pasta de habilidades para o diretório de configuração do agente.</p><p>Ainda não tem um cluster Elasticsearch? Inicie uma <a href="https://cloud.elastic.co/registration">avaliação gratuita do Elastic Cloud</a>. Leva cerca de um minuto para obter um ambiente totalmente configurado.</p><p><strong>Explorar o projeto:</strong></p><ul><li><p><a href="https://github.com/elastic/agent-skills">Repositório de habilidades do agente</a></p></li><li><p><a href="https://agentskills.io">Especificação agentskills.io</a></p></li><li><p><a href="https://www.elastic.co/docs">Documentação do Elasticsearch</a></p></li><li><p><a href="https://cloud.elastic.co/registration">Avaliação gratuita do Elastic Cloud</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-skills-elastic</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-skills-elastic</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Ferramentas de IA ]]></category>
    <dc:creator><![CDATA[Graham Hudgins,Matt Ryan]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbd233e8cf5c66c88/6a17074dc1e8a59502f8822a/09e64953819083168a9ecef0888c7f8bde1a43bd-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 16 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Linguagem de Expressão Comum (CEL): como a entrada CEL melhora a coleta de dados em integrações com o Elastic Agent]]></title>
    <description><![CDATA[Saiba como a Linguagem de Expressão Comum difere de outras linguagens de programação, como a estendemos para a entrada CEL do Filebeat e a flexibilidade que ela oferece para expressar a lógica de coleta de dados nas integrações do Elastic Agent.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/integrations">As integrações</a> do Elastic Agent permitem que os usuários façam a ingestão de dados para o Elasticsearch a partir de uma ampla variedade de fontes. Eles combinam lógica de coleta, pipelines de ingestão, dashboards e outros artefatos em um pacote que pode ser instalado e gerenciado a partir da interface web do Kibana.</p><p>Integrações configuram <a href="https://www.elastic.co/docs/reference/beats/filebeat/configuration-filebeat-options">entradas do Filebeat</a> para realizar a coleta de dados. Para coletar dados de APIs HTTP, usamos a <a href="https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-httpjson">entrada HTTP JSON</a>. No entanto, mesmo APIs básicas de listagem podem diferir bastante nos detalhes, e o modelo de transformações configuradas em YAML da entrada HTTP JSON pode tornar difícil e, às vezes, impossível expressar a lógica de coleta necessária.</p><p>A <a href="https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-cel">entrada em linguagem de expressão comum (CEL)</a> foi introduzida para permitir uma interação mais flexível com as APIs HTTP. A <a href="https://cel.dev/">CEL</a> é uma linguagem projetada para ser incorporada em aplicações que exigem uma maneira rápida, segura e extensível de expressar condições e transformações de dados. A entrada CEL permite que um desenvolvedor de integrações escreva uma expressão capaz de ler configurações, controlar o próprio estado, fazer solicitações, processar respostas e, por fim, retornar eventos prontos para serem ingeridos.</p><p>Neste artigo, vamos analisar como a CEL difere de outras linguagens de programação, como a estendemos para a entrada CEL, e a flexibilidade e o poder que isso oferece para expressar sua lógica de coleta de dados.</p><h2>CEL e como funciona na entrada</h2><p>A CEL é uma linguagem de expressões. Não possui instruções. Quando você escreve CEL, não indica o que fazer escrevendo instruções, mas sim qual valor produzir ao escrever uma expressão. Cada expressão CEL produz um valor, e expressões menores podem ser combinadas em uma expressão maior para produzir um resultado de acordo com regras mais complexas. Mais adiante, veremos como usar expressões para coisas que podem ser escritas com instruções em outras linguagens.</p><p>CEL é intencionalmente uma linguagem não Turing completa. Não permite loops ilimitados. Posteriormente, veremos como você pode processar listas e mapas usando macros, mas, ao evitar loops ilimitados, a linguagem garante um tempo de execução previsível e limitado para expressões individuais.</p><p>A entrada CEL é configurada com um programa CEL (uma expressão) e algum estado inicial. O estado será fornecido como entrada para o programa. O programa é avaliado para produzir um estado de saída. Se o estado de saída incluir uma lista de eventos, esses serão removidos e publicados. O restante do estado de saída será usado como entrada para a próxima avaliação. Se o estado de saída incluir um ou mais eventos e a bandeira <code>want_more: true</code>, a próxima avaliação será realizada imediatamente; caso contrário, ele irá hibernar pelo restante do intervalo configurado antes de continuar. Veja um diagrama simplificado do fluxo de controle da entrada:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0ec4ea57bfc2a2ff/6a17059f2b835f7d58f4b115/42671541f97e2dba808fd53969fe12f517917f9a-1600x529.png" alt="Fluxo de controle de entrada da Linguagem de Expressão Comum (CEL)" /><p>A saída de cada avaliação será passada como entrada para a próxima avaliação, enquanto a entrada for executada. Os dados de saída com a chave "<code>cursor</code>" serão mantidos no disco e recarregados após a reinicialização da entrada, mas o restante do estado não será preservado durante as reinicializações.</p><p>A linguagem CEL em si tem funcionalidade limitada e evita efeitos colaterais, mas é extensível. A implementação do <a href="https://github.com/google/cel-go">cel-go</a> acrescenta algumas funcionalidades, como sintaxe e tipos opcionais. A biblioteca <a href="https://github.com/elastic/mito">Mito</a> se baseia no cel-go e adiciona mais funcionalidades, incluindo a capacidade de fazer solicitações HTTP. A entrada da CEL usa a versão da CEL do Mito.</p><h2>Trabalhando com Mito</h2><p>Para criar ou fazer debug de uma integração usando a entrada CEL, o mais importante é entender qual estado de saída o seu programa CEL produzirá para um determinado estado de entrada. Durante o desenvolvimento, pode ser complicado executar o seu programa CEL pela entrada, cercado pela stack completa do Elastic. Uma maneira de ter um ciclo de feedback mais rápido é usar a ferramenta de linha de comando do Mito, que permite executar diretamente um programa CEL e ver a saída que ele produz para uma entrada específica.</p><p>Mito é escrito em Go e pode ser instalado da seguinte forma:</p>go install github.com/elastic/mito/cmd/mito@latest<p>Quando você executa um programa CEL com o Mito, normalmente fornece a ele dois arquivos: um arquivo JSON com o estado de entrada inicial e outro arquivo com o código-fonte do seu programa CEL:</p>mito -data state.json src.cel<p>Para facilitar o copiar e colar, os exemplos neste artigo são escritos como comandos únicos que fazem com que o shell crie arquivos temporários em tempo real, agrupando o conteúdo de cada arquivo em <code>&lt;(echo '...content...')</code>. No seu próprio desenvolvimento, trabalhar com arquivos reais será mais fácil.</p><h2>Busca de dados de problemas do GitHub</h2><p>O exemplo a seguir inclui um programa CEL completo que buscará dados sobre problemas na <a href="https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#list-repository-issues">API do GitHub</a>. Seu estado de entrada inicial tem uma URL para o endpoint da API e algumas informações sobre como se deve lidar com a paginação. O programa CEL usa os dados no estado de entrada para gerar uma solicitação. Ele decodificará a resposta, produzirá eventos a partir dela e os retornará como parte de seu estado de saída.</p>mito -data &lt;(echo '
  {
    "url": "https://api.github.com/repos/elastic/integrations/issues",
    "per_page": 3,
    "max_pages": 3
  }
') &lt;(echo '
  int(state.?cursor.page.orValue(1)).as(page,
    (
      state.url + "?" + {
        "state": ["all"],
        "sort": ["created"],
        "direction": ["asc"],
        "per_page": [string(state.per_page)],
        "page": [string(page)],
      }.format_query()
    ).as(full_url,
      request("GET", full_url).with({
        "Header": {
          "Accept": ["application/vnd.github+json"],
          "X-GitHub-Api-Version": ["2022-11-28"],
        }
      }).do_request().as(resp,
        resp.Body.decode_json().as(data,
          state.with({
            "events": data.map(i, {
              "html_url": i.html_url,
              "title": i.title,
              "created_at": i.created_at,
            }),
            "cursor": { "page": page + 1 },
            "want_more": size(data) == state.per_page &amp;&amp; page &lt; state.max_pages,
          })
        )
      )
    )
  )
')<p>Sua primeira avaliação produz a seguinte saída:</p>{
  "cursor": {
    "page": 2
  },
  "events": [
    {
      "created_at": "2018-09-14T09:47:35Z",
      "html_url": "https://github.com/elastic/integrations/issues/3250",
      "title": "Increase support of log formats in haproxy filebeat module"
    },
    {
      "created_at": "2019-02-06T12:37:37Z",
      "html_url": "https://github.com/elastic/integrations/issues/487",
      "title": "ETCD Metricbeat module needs polishing and grooming"
    },
    {
      "created_at": "2019-08-13T11:33:11Z",
      "html_url": "https://github.com/elastic/integrations/pull/1",
      "title": "Initial structure"
    }
  ],
  "max_pages": 3,
  "per_page": 3,
  "url": "https://api.github.com/repos/elastic/integrations/issues",
  "want_more": true
}<p>Os eventos serão removidos e, quando executados na entrada CEL, serão publicados para ingestão. O restante da saída será fornecido para a próxima avaliação do programa CEL como seu estado de entrada.</p><p></p><p>Para entender como esse programa CEL funciona, vamos analisar alguns exemplos menores de CEL e discutir mais detalhes sobre como a entrada CEL funciona.</p><h2>Noções básicas do CEL</h2><p>Na linguagem CEL, não há declarações; só existem expressões. Cada expressão CEL bem-sucedida é avaliada para um valor final. Aqui está uma das menores expressões de CEL que você pode escrever, junto com sua saída:</p>mito &lt;(echo '
  "hello" + " " + "world"
')"hello world"<p>Muitas expressões simples são intuitivas. Operações matemáticas são suportadas apenas em valores do mesmo tipo (por exemplo, <code>int</code> com <code>int</code>), então converta os tipos conforme necessário (aqui de <code>int</code> para <code>double</code>):</p>mito &lt;(echo '
  double((1 + 2) * (3 + 4)) / 2.0
')10.5<p>Não há variáveis na linguagem CEL, mas uma expressão pode receber um nome e ser usada em uma expressão maior com a ajuda da macro <a href="https://pkg.go.dev/github.com/elastic/mito/lib#hdr-As__Macro_-Collections"><code>as</code></a> de Mito. Neste exemplo, a expressão <code>(1 + 1)</code> avalia para o valor <code>2</code>, e <code>.as(n, ...)</code> dá a esse valor o nome <code>n</code> para uso na expressão <code>"one plus one is "+string(n)</code>:</p>mito &lt;(echo '
  (1 + 1).as(n, "one plus one is "+string(n))
')"one plus one is 2"<p>Também é possível acumular informações em um mapa e utilizá-las posteriormente na expressão, como demonstrado aqui usando <a href="https://pkg.go.dev/github.com/elastic/mito/lib#hdr-With-Collections"><code>with</code></a>:</p>mito &lt;(echo '
  { "key": "value" }.with({ "key2": "value2" }).as(data,
    {
      "data": data,
      "size": size(data),
    }
  )
'){
  "data": {
    "key": "value",
    "key2": "value2"
  },
  "size": 2
}<p>Observe esse exemplo novamente. Note que a parte aninhada, <code>({ "data": data, "size": size(data), })</code>, nos dá a forma do valor final. É um mapa com as chaves <code>"data"</code> e <code>"size"</code>. Os valores dessas chaves dependem de <code>data</code>, que é definido pela parte externa da expressão. Ler as expressões da CEL de dentro para fora pode ajudar a ver o que elas vão retornar.</p><p>A CEL não possui instruções de fluxo de controle, como <code>if</code>, mas a ramificação condicional pode ser feita com o operador ternário:</p>mito &lt;(echo '
  1 + 1 &lt; 12 ? "few" : "many"
')"few"<p>Ciclos ilimitados e recursão não são compatíveis, pois a CEL não é uma linguagem de Turing completa. Isso torna o tempo de execução previsível e proporcional ao tamanho dos dados de entrada e à complexidade da expressão.</p><p>Embora ciclos ilimitados não sejam possíveis em expressões CEL individuais, você pode processar listas e mapas usando macros como <a href="https://github.com/google/cel-spec/blob/master/doc/langdef.md#macros"><code>map</code></a>:</p>mito &lt;(echo '
  [1, 2, 3].map(x, x * 2)
')[2, 4, 6]<p>Nesta seção, abordamos:</p><ul><li><p>Strings, números, listas e mapas.</p></li><li><p>Concatenação de strings.</p></li><li><p>Operações matemáticas.</p></li><li><p>Conversão de tipo.</p></li><li><p>Condicionais.</p></li><li><p>Nomeando subexpressões.</p></li><li><p>Processando coleções.</p></li></ul><p>Em seguida, veremos como fazer solicitações HTTP.</p><h2>Requisições</h2><p>O Mito estende a CEL com a capacidade de fazer <a href="https://pkg.go.dev/github.com/elastic/mito/lib#HTTP">requisições HTTP</a>:</p>mito &lt;(echo '
  get("https://example.com").as(resp, string(resp.Body))
')"&lt;!doctype html&gt;&lt;html lang=\"en\"&gt;&lt;head&gt;&lt;title&gt;Example Domain&lt;/title&gt;..."<p>As requisições podem ser construídas explicitamente antes de serem executadas. Isso possibilita o uso de diferentes métodos HTTP e a adição de cabeçalhos e corpo da requisição.</p><p>Neste exemplo, criamos uma URL com a ajuda de <a href="https://pkg.go.dev/github.com/elastic/mito/lib#hdr-Format_Query-HTTP"><code>format_query</code></a>, adicionamos um cabeçalho à solicitação e analisamos o corpo da resposta com <a href="https://pkg.go.dev/github.com/elastic/mito/lib#hdr-Decode_JSON-JSON"><code>decode_json</code></a>. Quando você receber a opção <code>-log_requests</code>, o Mito loga informações detalhadas no formato JSON sobre cada requisição e resposta.</p>mito -log_requests &lt;(echo '
  request("GET",
    "https://postman-echo.com/get?" + {
        "q": ["query value"]
     }.format_query()
  ).with({
    "Header": { "Accept": ["application/json"] }
  }).do_request().as(resp, {
    "status": resp.StatusCode,
    "data": resp.Body.decode_json(),
  })
'){"time":"...","level":"INFO","msg":"HTTP request",...}
{"time":"...","level":"INFO","msg":"HTTP response",...}
{
  "data": {
    "args": {
      "q": "query value"
    },
    "headers": {
      "accept": "application/json",
      "accept-encoding": "gzip, br",
      "host": "postman-echo.com",
      "user-agent": "Go-http-client/2.0",
      "x-forwarded-proto": "https"
    },
    "url": "https://postman-echo.com/get?q=query+value"
  },
  "status": 200
}<h2>Gestão do estado e avaliações</h2><p>Agora que abordamos como fazer requisições e os fundamentos da CEL necessários para produzir o estado de saída desejado, vamos dar uma olhada mais detalhada no que devemos colocar no estado de saída e como isso nos permite direcionar o processamento posterior.</p><p>O programa CEL de uma integração precisa garantir que o estado de saída seja adequado para uso como entrada na próxima avaliação. A configuração define o estado inicial, que deve ser repetido na saída com quaisquer mudanças apropriadas. Uma maneira fácil de fazer isso é usar <code>state.with({ ... })</code>, para repetir o mapa de estados com algumas sobrescrições. Um padrão comum para programas pequenos é envolver o programa inteiro em <code>state.with()</code>, para que a propagação de estados não precise ser repetida em cada ramo que gera dados de saída (por exemplo, sucesso, erros).</p><p>Quando há valores de estado inicializados por uma avaliação em vez de codificados fixamente no estado inicial de entrada, o programa precisará verificar um valor existente antes de definir o inicial. Isso é algo em que o suporte para <a href="https://pkg.go.dev/github.com/google/cel-go/cel#OptionalTypes">sintaxe e tipos opcionais</a> pode ajudar. Ao usar um ponto de interrogação antes do nome do campo em uma chave de mapa, o acesso torna-se opcional: pode ou não resolver para um valor, mas acessos opcionais adicionais são possíveis e é fácil fornecer um padrão se não houver valor presente:
</p>mito -data &lt;(echo '{}') &lt;(echo '
  int(state.?counter.orValue(0)).as(counter,
    state.with({
      "counter": counter + 1,
      "want_more": counter + 1 &lt; 3,
    })
  )
'){ "counter": 1, "want_more": true }
{ "counter": 2, "want_more": true }
{ "counter": 3, "want_more": false }<p>Nesse exemplo, o valor contador lido do estado é convertido para <code>int</code> porque todos os números são serializados no estado como números de ponto flutuante, de acordo com as convenções estabelecidas pelo tipo de <code>Number</code> do JSON e JavaScript. Também deve ser notado que <code>"want_more": true</code> é respeitado aqui pelo Mito, mas quando executado na entrada CEL, a avaliação só será repetida se a saída também contiver eventos.</p><p>É uma exigência dos programas CEL executados pela entrada CEL que retornem uma chave <code>"events"</code> no mapa de saída. O valor pode ser uma lista de mapas de eventos, uma lista vazia ou um único mapa de eventos. O caso de evento único geralmente é usado para erros. O evento será publicado pela entrada, mas seu valor também será log, e se definir um valor <code>error.message</code> , ele será usado para atualizar o status de saúde da Fleet da integração. Se seu programa gerar um único evento que não seja erro, é melhor agrupá-lo em uma lista.</p><p>Confira novamente a saída anterior do nosso programa de problemas do GitHub:</p>{
  "url": "https://api.github.com/repos/elastic/integrations/issues",
  "per_page": 3,
  "max_pages": 3,
  "cursor": {
    "page": 2
  },
  "events": [
    { ... },
    { ... },
    { ... }
  ],
  "want_more": true
}<p>O programa gerenciou efetivamente o estado por:</p><ul><li><p>Repetindo valores de estado inicial em <code>url</code>, <code>per_page</code> e <code>max_pages</code>.</p></li><li><p>Adicionando estados que devem ser mantidos durante reinícios em <code>cursor.page</code>.</p></li><li><p>Eventos de retorno prontos para serem publicados na lista <code>events</code>.</p></li><li><p>Solicitar reavaliação imediata com <code>want_more: true</code>.</p></li></ul><p>Agora que você entende o acesso opcional e o gerenciamento de estado, bem como os conceitos básicos da CEL e as solicitações HTTP, o programa completo de problemas do GitHub deve estar legível. Tente executar o programa com o Mito e experimente algumas alterações.</p><h2>Revisão e recursos</h2><p>Neste artigo, analisamos o que é a CEL e como ela foi estendida na biblioteca Mito para uso na entrada CEL. Observamos a flexibilidade da CEL em um programa de exemplo que busca informações de problemas na API do GitHub e analisamos todos os detalhes necessários para entender esse programa, abrangendo o acesso às configurações no estado inicial, a interação com APIs HTTP, o retorno de eventos a serem ingeridos e o gerenciamento do estado para execuções posteriores do programa.</p><p>Para aprender mais e construir integrações usando a entrada da CEL, há vários recursos que valem a pena explorar:</p><ul><li><p><a href="https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-cel">Entrada CEL - Documentação do Filebeat</a></p></li><li><p><a href="https://pkg.go.dev/github.com/elastic/mito">Documentação Mito</a></p></li><li><p><a href="https://cel.dev/">Linguagem de expressão comum - website cel.dev</a></p></li><li><p><a href="https://www.elastic.co/docs/extend/integrations">Crie uma Integração - Documentação Elastic</a></p></li></ul><p>E talvez o recurso mais valioso para criar integrações com a entrada CEL seja o código CEL das integrações existentes do Elastic, que pode ser encontrado no GitHub:</p><p><a href="https://github.com/search?q=repo%3Aelastic%2Fintegrations+path%3A**%2Fcel.yml.hbs&amp;type=code"><code>cel.yml.hbs</code></a><a href="https://github.com/search?q=repo%3Aelastic%2Fintegrations+path%3A**%2Fcel.yml.hbs&amp;type=code"> arquivos no repositório de integrações Elastic - GitHub</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/common-expression-language-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/common-expression-language-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Chris Berkhout]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt330db607ffb818f9/6a1705a08b73cb8502189f4c/985c50bfabee3348494eb4307f0b3375a97a0644-1280x720.png" length="0" type="image/png"/>
    <pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Construtor de agentes além da caixa de bate-papo: apresentando a infraestrutura ampliada]]></title>
    <description><![CDATA[Saiba mais sobre o Elastic Agent Builder com infraestrutura ampliada, um agente de IA que permite operações ampliadas, desenvolvimento aprimorado e synthetics ampliados.]]></description>
    <content:encoded><![CDATA[<p><strong>Nós não falamos. Nós fazemos.</strong></p><p>Todos nós já vimos o crescimento dos agentes de IA. Eles são fantásticos em resumir textos, escrever trechos de código e responder a perguntas baseadas em documentação. Mas, para nós que trabalhamos com DevOps e engenharia de confiabilidade de sites (SRE), houve uma limitação frustrante. A maioria dos agentes está presa ao paradigma do call center, o que significa que eles podem ler, pensar e conversar, mas não conseguem entrar em contato e tocar na infraestrutura que deveriam estar gerenciando.</p><p>Para nosso último projeto de hackathon, decidimos eliminar essa limitação.</p><p>Nós construímos <strong>Infraestrutura Ampliada</strong>: um copiloto de infraestrutura que não apenas dá conselhos, mas também cria, implanta, monitora e corrige seu ambiente em tempo real.</p><h2><strong>O problema: copiar, formatar, colar</strong></h2><p>Os agentes padrão operam em um vácuo. Se o seu app for desativado e custar US$ 5 milhões para a empresa, um agente padrão poderá ler para você o manual de instruções para corrigi-lo. Mas <em>você</em> ainda precisa fazer o trabalho. Você terá que copiar o código, reformatá-lo para o seu ambiente e colá-lo no terminal.</p><p>Queríamos um agente que entendesse a diferença entre <em>falar</em> sobre o Kubernetes e <em>configurar</em> o Kubernetes.</p><h2><strong>O motor: o que é o Elastic Agent Builder?</strong></h2><p>Para construir isso, não começamos do zero. Construímos sobre o <a href="https://www.elastic.co/pt/elasticsearch/agent-builder"><strong>Elastic Agent Builder</strong></a>. Para quem não conhece, o Elastic Agent Builder é um framework projetado para desenvolver agentes rapidamente, e atua como a ponte entre um grande modelo de linguagem (LLM) (na nossa demonstração, usamos o Google Gemini) e dados privados armazenados no Elasticsearch.</p><p>O Agent Builder pode ser usado para IA conversacional, baseando-o em dados internos, como documentos ou registros. Mas seu recurso mais avançado é a capacidade de alocar <strong>ferramentas</strong> que permitem que o LLM saia da interface de bate-papo para realizar tarefas específicas. Vimos que, se levássemos esse recurso ao limite, poderíamos transformar o Agent Builder em uma potência de automação.</p><h2><strong>Fazendo funcionar: construindo a primeira versão</strong></h2><p>Quando começamos o projeto, sabíamos que queríamos que os agentes fossem capazes de mudar o mundo exterior. Tivemos uma ideia: e se construíssemos algum software "runner" (para executar qualquer comando que o agente pudesse imaginar no host)? E depois: e se os runners, o Elastic Agent Builder e o usuário estivessem em uma chamada tripla?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltec9d20da8c41a898/6a170704dc55debd4ce00d43/8dc8317c1301b8eb7b89438529e8d8d17411c95a-1024x559.png" alt="Agent Builder with Augmented Infrastructure architecture" /><p>Começamos desenvolvendo um projeto em Python, os Runners de Infraestrutura Ampliada, que era essencialmente um loop while(true) que consultava a API de conversas do Elastic Agent Builder a cada segundo e verificava uma sintaxe especial que havíamos criado:</p>{
"tool_name": "my_tool",
       "tool_arguments": "\{stringified json arguments\}"
}<p>Depois, atualizamos o prompt para ensiná-lo nossa nova sintaxe de chamada de ferramenta. Bill é o mantenedor do <a href="https://gofastmcp.com/getting-started/welcome">FastMCP</a>, o framework mais popular para a criação de servidores MCP (Model Context Protocol) em Python. Ele começou a trabalhar usando o cliente FastMCP com esse novo software de runner para montar servidores MCP e disponibilizar suas ferramentas ao runner. Quando o agente via isso, ele executava a chamada de ferramenta e enviava os resultados via POST de volta para a conversa como se o usuário tivesse enviado os resultados. Isso acionou o LLM para responder ao resultado, e seguimos em frente!</p><p>Foi ótimo, mas houve dois problemas principais:</p><ol><li><p>O agente despejava todo esse JSON diretamente na conversa com o usuário.</p></li><li><p>A primeira vez que as mensagens ficaram visíveis pela API de conversas foi quando uma rodada de conversa foi concluída (ou seja, quando o LLM respondeu).</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0596217e962f8464/6a17070647d49c3fef2d890c/7b3755aeae17722ff1bb9677712293e9195f96a0-1058x1034.png" alt="Issue when building agent with augment infrastructure" /><p>Então, começamos a descobrir como colocar isso em segundo plano.</p><p>Em seguida, passamos a dar ao agente uma ferramenta chamada call_external_tool com dois argumentos: o tool_name e os argumentos da ferramenta JSON em string. Essa chamada de ferramenta externa não retornava nada, mas, mais importante, seria visível na requisição GET para a API de conversas. Em seguida, demos permissão aos runners para escrever documentos diretamente no Elasticsearch, que o agente do Elastic Agent Builder poderia recuperar conforme necessário. O agente está sempre operando em resposta a uma mensagem do usuário, então precisamos iniciar o agente com uma mensagem de usuário para que ele busque os resultados e continue o processamento. Então pedimos aos agentes que inserissem uma pequena mensagem no chat para retomar a conversa:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta22be3c67ad2ff1f/6a170708cdacbf0ae87d295b/61ff59a57c68ed5fad492d19c0580644113a507d-1600x1321.png" alt="Agent Builder with Augmented Infrastructure demostration" /><p>Então, agora tínhamos chamadas de ferramentas externas. No entanto, devido ao segundo problema mencionado acima, tivemos que eliminar a parte final do pontapé inicial. Caso contrário, cada chamada de ferramenta externa exigiria uma rodada completa de conversas para recuperar os resultados!</p><h2><strong>Aprimorando: introduzindo fluxos de trabalho</strong></h2><p>Além das chamadas da linguagem de consulta Elasticsearch (ES|QL) e da ferramenta de busca de índice, os agentes do Agent Builder podem chamar ferramentas baseadas em fluxo de trabalho da Elastic. Fluxos de trabalho da Elastic oferecem uma forma flexível e fácil de gerenciar para executar uma sequência arbitrária e uma lógica de ações. Para nossos propósitos, tudo o que precisamos é que o fluxo de trabalho armazene uma solicitação de ferramenta externa para o Elasticsearch e retorne uma ID para pesquisar os resultados. Isso resulta na seguinte definição simples de fluxo de trabalho:</p>nome: chamada-ferramenta-ai
 ativado: verdadeiro
 gatilhos:
 - tipo: manual
 entradas:
 - nome: runner_id
 tipo: string
 - nome: chamadas_de_ferramenta
 tipo: string

 passos:
 - nome: solicitação_armazenar
 tipo: elasticsearch.create
 com:
 índice: solicitações-de-ferramentas-distribuídas
 id: "{{inputs.runner_id}}_{{ execution.id }}"
 documento:
 request_id: "{{ execution.id }}"
 runner_id: "{{inputs.runner_id}}"
 chamada_de_ferramenta: "{{inputs.tool_calls}}"
 status: "não tratado"

 - nome: resultado_de_saída
 tipo: console
 com:
 mensagem: "Ferramenta chamada, com ID de execução: {{ execution.id }}. Use este ID para consultar os resultados.<p>Com isso, em vez de depender da solicitação de chamada de ferramenta ser gravada na conversa, os runners podem simplesmente consultar o índice distributed-tool-requests do Elasticsearch para novas solicitações de ferramentas externas e registrar os resultados em outro índice do Elasticsearch com o execution.id fornecido.</p><p>Isso elimina os dois principais problemas mencionados acima:</p><ol><li><p>O histórico de conversas não está mais saturado com a carga útil das chamadas de ferramentas externas.</p></li><li><p>Como os runners estão consultando o índice do Elasticsearch em vez do histórico de conversas, eles não são bloqueados pela rodada de conversa a ser concluída para que os pedidos externos de ferramentas fiquem visíveis.</p></li></ol><p>O segundo ponto tem a grande vantagem de que o processamento das chamadas de ferramentas externas começa dentro da fase de pensamento do agente (e não quando a rodada de conversação é concluída). Isso nos permite instruir o LLM no prompt do sistema para sondar os resultados da ferramenta externa até que os resultados estejam disponíveis e elimina a necessidade da mensagem de inicialização. De modo geral, isso tem o efeito positivo de tornar a conversa mais natural: o LLM consegue processar várias solicitações de ferramentas externas em uma única rodada de conversa (em vez de exigir uma rodada de conversa para cada solicitação de ferramenta) e, portanto, consegue atender a solicitações de usuários mais complexas de uma só vez.</p><h2><strong>Juntando tudo</strong></h2><p>Para preencher a lacuna entre o LLM e o rack de servidores, desenvolvemos uma arquitetura específica usando as capacidades da ferramenta do Agent Builder:</p><ol><li><p><strong>Runners de infraestrutura ampliada:</strong> implantamos executantes leves dentro dos ambientes de destino (servidores, clusters Kubernetes, contas de nuvem). Esses executores são conectados diretamente à Elastic, usando endpoints seguros e segredos disponíveis apenas para cada um dos executores.</p></li><li><p><strong>Recuperação ES|QL:</strong> o copiloto usa o <strong>ES|QL da Elastic</strong> para realizar buscas híbridas. Ele não procura apenas conhecimento; procura <em>capacidades</em>. Ele consulta os executores runners para ver quais ferramentas estão disponíveis (por exemplo, list_ec2_instances, install_helm_chart).</p></li><li><p><strong>Execução do fluxo de trabalho:</strong> quando o agente decide sobre um curso de ação, ele cria um fluxo de trabalho estruturado.</p></li><li><p><strong>Ciclo de feedback:</strong> os runners executam o comando no local e enviam os resultados de volta ao Elasticsearch. O copiloto lê o resultado do índice e decide o próximo passo.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9726199693a10c5c/6a17070ae8fbced43a39fb9a/76be256da722c1965971fc506502768bd890f0c4-1290x1076.png" alt="Architecture using Agent Builder’s tool capabilities with Augmented Infrastructure" /><h2><strong>A demonstração: da interrupção à observabilidade</strong></h2><p>No vídeo, apresentamos dois casos distintos que demonstram como essa arquitetura pode melhorar.</p><h3><strong>Caso 1: Resgate do DevOps</strong></h3><p>Começamos com um usuário entrando em pânico por causa de uma queda de 5 milhões de dólares causada por um ponto cego no cluster Kubernetes deles.</p><ul><li><p><strong>O pedido:</strong> "como garantir que isso não aconteça de novo?"</p></li><li><p><strong>A ação:</strong> o agente não se limitou a oferecer um tutorial. Ele identificou o cluster, criou os espaços de nome necessários, gerou secrets do Kubernetes, instalou o OpenTelemetry Operator e forneceu na hora um link para um dashboard de APM em tempo real.</p></li><li><p><strong>O resultado:</strong> total observabilidade do Kubernetes e insights do aplicativo sem que o usuário escreva uma única linha de YAML.</p></li></ul><h3><strong>Caso 2: Transferência de segurança</strong></h3><p>Uma regra fundamental da segurança da infraestrutura é que você só pode proteger o que pode ver. Ao realizar nosso resgate de DevOps, o agente vê uma oportunidade de melhorar a segurança do ambiente.</p><p>Com um alerta iniciado a partir de uma investigação anterior relacionada ao Elastic Observability, demonstramos como um profissional de segurança pode interagir diretamente com sua infraestrutura: primeiro, para enumerar os ativos e recursos em seu ambiente de nuvem; e, segundo, para implantar as ferramentas necessárias para que o ambiente esteja seguro.</p><ul><li><p><strong>Descoberta:</strong> o copiloto enumerou os recursos da AWS para o profissional de segurança e identificou uma lacuna crítica: uma instância do Amazon Elastic Compute Cloud (EC2) e um cluster do Amazon Elastic Kubernetes Service (EKS) com endpoints públicos sem proteção de endpoint.</p></li><li><p><strong>Correção:</strong> com uma simples aprovação, o copiloto implantou a <strong>detecção estendida e resposta (XDR) e detecção e resposta na nuvem (CDR)</strong> do <strong>Elastic Security</strong> nos ativos vulneráveis, protegendo o ambiente em tempo real.</p></li><li><p><strong>Resultado:</strong> proteção dos ativos e recursos AWS implantados com segurança completa em tempo de execução.</p></li></ul><h2><strong>O futuro: tudo ampliado</strong></h2><p>Esse projeto comprova que o Elastic Agent Builder pode ser o cérebro central para operações distribuídas. Não estamos limitados apenas à infraestrutura. Nossa tecnologia de runners cobre:</p><ul><li><p><strong>Synthetics ampliados:</strong> diagnosticando erros TLS em executores globais.</p></li><li><p><strong>Desenvolvimento ampliado:</strong> criando pull requests e implementando CAPTCHAs em serviços frontend.</p></li><li><p><strong>Operações aprimoradas:</strong> para reconfiguração automática de resolvedores de DNS durante uma interrupção.</p></li></ul><h2><strong>Veja você mesmo</strong></h2><p>Acreditamos que o futuro da IA não se resume apenas ao suporte por chat; envolve <strong>Infraestrutura Ampliada</strong>. Envolve um parceiro que possa implantar, consertar, observar e proteger ao seu lado.</p><p>Confira o código e use os executores distribuídos (<a href="https://github.com/strawgate/augmented-infrastructure">GitHub</a>) e o Elastic Agent Builder no <a href="https://cloud.elastic.co/">Elastic Cloud Serverless</a> hoje mesmo!</p><ul><li><p>Crie um projeto serverless no Elastic Cloud.</p></li><li><p>Implante o código em um runner.</p></li><li><p>Prepare o runner.</p></li><li><p>Configure seu mcp.json.</p></li><li><p>Execute o runner, que criará automaticamente seu agente e as ferramentas.</p></li><li><p>Converse com um agente que pode raciocinar, planejar e executar ações nos seus runners distribuídos!</p></li></ul><p><strong>A equipe: </strong><em>Alex, Bill, Gil, Graham e Norrie</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-augmented-infrastructure</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-augmented-infrastructure</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Ferramentas de IA ]]></category>
    <dc:creator><![CDATA[Alexander Wert,Bill Easton,Gil Raphaelli,Graham Hudgins,Norrie Taylor]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6de9245ad57ccc00/6a17070cdc55deaa39e00d48/e08daf78f328e826f39d06329f6a5487f75d178d-1272x700.png" length="0" type="image/png"/>
    <pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Agent Builder agora em GA: envie agentes orientados por contexto em questão de minutos]]></title>
    <description><![CDATA[O Agent Builder agora está disponível na versão GA. Saiba como isso permite que você desenvolva agentes de IA orientados por contexto.]]></description>
    <content:encoded><![CDATA[<p>É com grande satisfação que anunciamos a disponibilidade geral do Agent Builder no Elastic Cloud Serverless e na próxima versão 9.3. O Agent Builder utiliza o poder do Elasticsearch como uma plataforma de engenharia de contexto para desenvolver de forma rápida agentes de IA contextuais e focados em dados.</p><p>Os agentes estão ganhando força, impulsionados pelo potencial de entregar ganhos de eficiência e melhores experiências para os clientes. Mas, na prática, fornecer aos agentes o contexto correto é difícil, principalmente quando se trabalha com dados empresariais desorganizados e não estruturados. Os desenvolvedores precisam gerenciar ferramentas, prompts, estado, lógica de raciocínio, modelos e, principalmente, recuperar o contexto relevante das fontes comerciais para fornecer resultados e ações precisos. O Elastic Agent Builder oferece esses componentes essenciais para desenvolver agentes seguros, confiáveis e orientados ao contexto.</p><h2>Principais funcionalidades do Agent Builder</h2><p>O Agent Builder aproveita os investimentos de longo prazo da Elastic na relevância de busca e retrieval-augmented generation, e trabalha para tornar o Elasticsearch o melhor banco de dados vetorial para simplificar o desenvolvimento de agentes de IA contextuais e focados em dados.</p><p>O Agent Builder permite que você:</p><ul><li><p>Comece com um agente conversacional integrado que pode responder a perguntas, realizar análises e conduzir investigações sobre quaisquer dados no Elasticsearch.</p></li><li><p>Passe de dados complexos não estruturados para um agente personalizado com uma experiência de desenvolvimento baseada em configuração.</p></li><li><p>Aproveite a relevância de pesquisa híbrida de ponta por meio do ES|QL integrado ou de ferramentas personalizadas para melhorar a qualidade do contexto e a confiabilidade do agente.</p></li><li><p>Execute fluxos de trabalho complexos (pré-visualização) como ferramentas reutilizáveis para enriquecer dados, atualizar registros, enviar mensagens e muito mais para automação baseada em regras.</p></li><li><p>Conecte-se a fontes de dados fora do Elasticsearch usando fluxos de trabalho e MCP para correlacionar e combinar o contexto dos agentes.</p></li><li><p>Integre-se a qualquer framework agêntico ou aplicação usando ferramentas integradas e personalizadas expostas via MCP, além da capacidade de conectar-se a MCPs externos (em pré-visualização), suporte para A2A e suporte completo à API.</p></li><li><p>Amplie os recursos do Agent Builder com integração a soluções de terceiros, como o LlamaIndex para processamento complexo de documentos ou o Arcade.dev para acesso seguro e estruturado a ferramentas.</p></li></ul><p>Para ampliar ainda mais a funcionalidade do Agent Builder, apresentamos o Elastic Workflows, nossos novos recursos de automação baseados em regras, agora em versão prévia técnica. Para tarefas organizacionais, os agentes às vezes precisam de certeza e confiabilidade de ações baseadas em regras, que geralmente são necessárias para implementar uma lógica comercial específica. O Elastic Workflows oferece aos agentes uma maneira simples e declarativa de orquestrar sistemas internos e externos para executar ações, coletar e transformar dados e contexto. Os fluxos de trabalho são totalmente componíveis, orientados a eventos e flexíveis, e podem ser expostos como ferramentas a um agente via MCP.</p><h2>De dados a agentes em questão de minutos</h2><p>Os agentes de desenvolvimento podem levar semanas de trabalho inicial para consolidar armazenamentos de dados separados, criar pipelines manuais, ajustar consultas e gerenciar orquestrações complexas. O Agent Builder reduz o tempo de desenvolvimento para os agentes, acabando com a necessidade de armazenamentos de dados separados, bancos de dados vetoriais, pipelines RAG, camadas de pesquisa, tradutores de consultas e orquestradores de ferramentas, permitindo que você se concentre na lógica do agente e na entrega do aplicativo.</p><p>O Agent Builder integra de forma nativa primitivas da plataforma Elasticsearch para agilizar o desenvolvimento de agentes.</p><ul><li><p>Comece com um agente conversacional integrado que pode conversar e raciocinar imediatamente com seus dados indexados.</p></li><li><p>Integre agentes em aplicações, dashboards ou sistemas de CI/CD com acesso interativo via Kibana, APIs ou MCP e A2A.</p></li><li><p>Crie com as ferramentas padrão para entender a estrutura dos seus dados, selecionar o índice apropriado, gerar consultas híbridas, semânticas e estruturadas otimizadas e criar visualizações configuráveis usando ES|QL com base em comandos em linguagem natural.</p></li></ul><p>Para se aprofundar, veja um <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">passo a passo prático</a> e completo.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8def92028138672/6a17e086af47b60cd8cdde96/b55b63eae40f72952967cc8f3ea4df4cd62d7d70-1080x608.gif" alt="Tutorial do Elastic Agent Builder" /><h2>Crie com o Elasticsearch, uma plataforma de dados completa para engenharia de contexto</h2><p>Para agentes de IA, a qualidade do contexto é essencial para fornecer raciocínio eficaz e reduzir os riscos de alucinação. Para muitos agentes de IA corporativa, os dados de negócios necessários para realizar uma tarefa são a peça fundamental de contexto. Como um armazenamento de dados altamente escalável, banco de dados vetorial e líder em relevância, o Elasticsearch já oferece muitas primitivas fortes de engenharia de contexto. A engenharia de contexto vai além da simples retrieval-augmented generation, permitindo que você personalize e redimensione como os dados são obtidos, ranqueados, filtrados e apresentados aos agentes, ajudando a reduzir ruído e ambiguidade.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4c10c1d09e9f81e/6a17e087577262feb31bcb4b/419b9b6f13739e0a8983249d8ac31478e73dac89-1600x901.png" alt="Diagrama do Agent Builder" /><p>O Elasticsearch oferece um mecanismo de contexto que combina busca lexical, busca vetorial e filtragem estruturada para recuperação de dados, o que <a href="https://www.elastic.co/search-labs/blog/context-engineering-relevance-ai-agents-elasticsearch">melhora o desempenho do LLM</a> ao garantir que o modelo opere em um contexto relevante e preciso. Essa capacidade é suportada por recuperação agêntica, juntamente com ferramentas integradas e lógica de busca que selecionam automaticamente os índices corretos e transformam a linguagem natural em consultas otimizadas para o contexto.</p><p>Com o Agent Builder, você garante que os agentes recebam primeiro o contexto mais útil com controles de relevância e classificação, permitindo que você ajuste a lógica de pontuação, classificação e filtragem. O Elasticsearch permite que você controle o que importa, por que importa e como é priorizado, em vez de depender de um comportamento opaco de recuperação. Tudo isso é sustentado pelo Elasticsearch como uma plataforma de dados escalável para armazenar e escalar todos os seus dados de texto, vetores, metadados, logs e muito mais em uma plataforma, facilitando o gerenciamento do contexto para os agentes.</p><h2>Executar fluxos de trabalho complexos como ferramentas reutilizáveis</h2><p>Enquanto agentes de IA permitem o raciocínio para tarefas complexas, grande parte da automação depende da execução confiável de ações baseadas em regras que aplicam lógica de negócios específica. O Elastic Workflows oferece uma maneira simples e declarativa de orquestrar sistemas internos e externos para realizar ações, coletar contexto ou dados e integrá-los como parte dos agentes. Definidos em YAML, os fluxos de trabalho são totalmente componíveis, permitindo que sejam tão simples ou complexos quanto o trabalho exigir. Isso oferece aos agentes uma maneira eficiente de agir em toda a plataforma e nas soluções do Elasticsearch, bem como com aplicativos de terceiros.</p><p>A integração de um fluxo de trabalho com o Agent Builder pode ser feita em três etapas (pré-requisito: habilitar fluxos de trabalho com detalhes fornecidos <a href="https://github.com/elastic/workflows">aqui</a>)</p><p>1. Criar e salvar um novo fluxo de trabalho usando o editor simples baseado em YAML com autopreenchimento e testes integrados.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt00585158429a3395/6a17e089e317916b122d5740/308888bf3d2fa013f9391a55be6a6fbd458b6dac-1600x998.png" alt="Fluxo de trabalho do Agent Builder" /><p>2. Crie uma nova ferramenta no Agent Builder com o tipo “Fluxo de trabalho” e informe uma descrição para ajudar o agente a determinar quando usar a ferramenta de fluxo de trabalho.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt874b6a1ce3a2ac34/6a17e08be9ea87b1dea9c4d9/c04810d30d226112c3610bd58e208607b213fc3d-1600x945.png" alt="Crie uma nova ferramenta no Agent Builder" /><p>3. Adicione a ferramenta de fluxo de trabalho ao seu agente personalizado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94a31cb60ef11ce6/6a17e08daf47b61f0dcdde9a/724cd4ac93c46efb0d339fd140e5caf138f8150f-1600x948.png" alt="Adicione a ferramenta de fluxo de trabalho ao seu agente personalizado." /><p>4. É isso aí! Agora o agente pode chamar o fluxo de trabalho dentro de uma conversa.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5143f401a06e8ba2/6a17e08fdbb4ffcfc6fb55de/8dfdd726ab89e31c48b79372650ce33946713dca-1600x929.png" alt="O agente de IA foi criado com o Elastic Agent Builder" /><h2>Seu agente, suas regras</h2><p>O Agent Builder não te prende a um único paradigma de desenvolvimento. Em vez disso, ele foi projetado para permitir abordagens de desenvolvimento abertas e flexíveis para agentes com controle total de dados, relevância, modelos, interoperabilidade, security e design de agentes.</p><p>As definições de agentes personalizados permitem que você escolha exatamente quais ferramentas um agente pode acessar, incorpore avisos de sistema personalizados, adapte as instruções do agente e defina limites de segurança. Os agentes permanecem independentes do modelo, permitindo que você configure com flexibilidade um LLM preferido, tanto nativo quanto em todo o ecossistema, sem ficar preso a um único provedor.</p><p>Crie ferramentas extensíveis que encapsulem lógica específica do domínio (por exemplo, filtros de índice específicos, junções ES|QL, pipelines analíticos) e restrinja-as para uso seguro em produção. O suporte completo à API permite a interoperabilidade com outras frameworks de agentes, com suporte nativo ao Protocolo de Contexto do Modelo (MCP). A integração A2A significa que você pode expor seus agentes Elastic a outros frameworks, serviços e apps clientes, reutilizando a mesma lógica de engenharia de dados e contexto em todas as integrações.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt309a0b3dd4cc367b/6a17e090ec0f8932045a6550/5e903ba24ffb3f40231e901f63bd494c89cb7757-1600x1004.png" alt="Configuração do agente de IA com Agent Builder da Elastic" /><p>O Agent Builder suporta desenvolvimento flexível e aberto e foi projetado para se integrar com frameworks e plataformas populares de agentes. Essas integrações podem ser essenciais para entregar agentes eficazes. Como descreve <strong>Sam Partee, cofundador da Arcade.dev</strong>,</p><p><em>"Sistemas agênticos falham hoje porque conectar IA a ferramentas e dados é algo complexo. O Elastic Agent Builder com Arcade.dev oferece aos desenvolvedores uma maneira estruturada e segura de lidar com a forma como os agentes recuperam o contexto, raciocinam e agem, levando os agentes da demonstração ao nível de produção."</em></p><p>O Agent Builder também aproveita a extensibilidade do Elasticsearch para lidar com dados complexos. Como descreve <strong>Jerry Liu, CEO da LlamaIndex </strong>,</p><p><em>“Extrair o contexto empresarial de fontes de dados não estruturadas é fundamental para a criação de agentes eficazes. O Elastic Agent Builder combinado com o processamento de documentos complexos do LlamaIndex fortalece a camada fundamental de contexto, ajudando as equipes a recuperar, processar e preparar dados para que os agentes possam raciocinar com mais precisão e oferecer melhores resultados."</em></p><h2>O que você pode construir?</h2><p>O Agent Builder já está sendo usado para vários casos de uso. Abaixo estão alguns exemplos e arquiteturas de referência para começar a usar agentes:</p><ul><li><p><strong>Automatizar infraestrutura: </strong>em cenários de suporte, os agentes têm sido usados para ler, pensar e conversar, mas até o momento, eles não conseguem acessar e tocar a infraestrutura que possam precisar gerenciar. A equipe de engenharia da Elastic criou um agente para <a href="https://www.elastic.co/search-labs/blog/agent-builder-augmented-infrastructure">gerenciamento automatizado de infraestrutura</a> como parte de um hackathon. O agente investiga ativamente problemas com a infraestrutura da aplicação e age de forma automatizada. Ele usa fluxos de trabalho para otimizar configurações, responder a problemas e redimensionar recursos, tudo com base em uma compreensão inteligente dos logs de infraestrutura.</p></li><li><p><strong>Análise de ameaças à segurança: </strong>um agente de vulnerabilidade de segurança foi desenvolvido com Elastic Agent Builder, MCP e Elasticsearch. Ele automatiza a análise de ameaças correlacionando dados de segurança internos com inteligência de ameaças externa. O agente realiza buscas semânticas em incidentes e configurações históricas, amplia os resultados com dados da internet em tempo real e aplica o raciocínio LLM para avaliar a relevância ambiental, priorizar riscos e produzir medidas corretivas viáveis. Consulte a <a href="https://www.elastic.co/search-labs/blog/agent-builder-mcp-reference-architecture-elasticsearch">arquitetura de referência</a><strong>.</strong></p></li><li><p><strong>Suporte técnico ao cliente: </strong>os agentes podem executar diversas tarefas de suporte, incluindo resumo de casos, identificação e criação de problemas duplicados e investigação técnica aprofundada. O Agent Builder permite isso com uma pesquisa híbrida de várias etapas para encontrar somente os problemas, soluções e procedimentos relacionados mais relevantes e formular hipóteses de causa raiz e planos de remediação. O Agent Builder pode simplificar a arquitetura de <a href="https://www.elastic.co/blog/generative-ai-customer-support-elastic-support-assistant">sistemas de suporte</a> complexos e acelerar o tempo de entrega.</p></li><li><p><strong>Descoberta de produtos e conteúdo:</strong> o Agent Builder simplifica o processo de <a href="https://www.elastic.co/search-labs/blog/build-voice-agents-elastic-agent-builder">expor catálogos complexos de produtos para experiências conversacionais</a>, ao mesmo tempo em que permite que as organizações mantenham flexibilidade para incluir a própria lógica e requisitos de negócios.</p></li><li><p><strong>Crie você mesmo:</strong> participe do <a href="https://elasticsearch.devpost.com/">Hackathon do Agent Builder,</a> que ocorrerá de 22 de janeiro a 27 de fevereiro de 2026. Trabalhe com a comunidade para criar agentes de IA orientados por contexto e em várias etapas que combinem buscar, fluxos de trabalho, ferramentas e raciocínio para automatizar tarefas do mundo real*</p></li></ul><h2>Comece a criar agentes personalizados agora</h2><p>Comece com um <a href="https://cloud.elastic.co/registration?onboarding_token=search&amp;pg=en-enterprise-search-page">teste do Elastic Cloud</a> e confira a documentação <a href="https://www.elastic.co/docs/solutions/search/elastic-agent-builder">aqui</a>. Para clientes existentes, o Agent Builder está disponível no Cloud Serverless e no nível Empresarial no Elastic Cloud Hosted e autogerenciado.</p><p>* <a href="https://elasticsearch.devpost.com/rules">Clique aqui</a> para ver os termos, condições e requisitos de elegibilidade para o hackathon</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-elastic-ga</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-elastic-ga</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Elastic Cloud Serverless]]></category>
    <dc:creator><![CDATA[Anish Mathur,Evan Castle]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5ffa581514d8b8c/6a17e092dbb4fff61afb55e2/6840eb7dbb884055ab0e965dcfd614fec54936af-2210x1440.png" length="0" type="image/png"/>
    <pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Construindo agentes de voz com o Elastic Agent Builder]]></title>
    <description><![CDATA[Explorando como funcionam os agentes de voz e como construir um usando o Elastic Agent Builder e o LiveKit.]]></description>
    <content:encoded><![CDATA[<p>A IA ficou presa em uma caixa de vidro. Você digita comandos, ela responde com texto, e pronto. É útil, mas distante, como ver alguém se mover atrás de uma tela. Este ano, 2026, será o ano em que as empresas vão quebrar esse vidro e trazer agentes de IA para produtos, onde realmente entregam valor.</p><p>Uma das maneiras pelas quais o vidro será quebrado é pela adoção de <em>agentes de voz</em>, que são agentes de IA que reconhecem a fala humana e sintetizam áudio gerado por computador. Com o crescimento das transcrições de baixa latência, modelos de linguagem grandes e rápidos (LLMs) e modelos de texto para fala que soam humanos, isso se tornou possível.</p><p>Os agentes de voz também precisam ter acesso a dados empresariais para se tornarem realmente valiosos. Neste artigo, aprenderemos como funcionam os agentes de voz e criaremos um para a ElasticSport, uma loja fictícia de equipamentos esportivos para atividades ao ar livre, usando <a href="https://livekit.io/">LiveKit</a> e <a href="https://www.elastic.co/elasticsearch/agent-builder">Elastic Agent Builder</a>. Nosso agente de voz será sensível ao contexto e funcionará com nossos dados.</p><h2>Como funciona</h2><p>Existem dois paradigmas no mundo dos agentes de voz: o primeiro usa modelos de fala para fala, e o segundo usa um pipeline de voz que consiste em fala para texto, LLM e texto para fala. Modelos de fala para fala têm os próprios benefícios, mas os pipelines de voz oferecem muito mais personalização das tecnologias usadas e de como o contexto é gerenciado, além de controle sobre o comportamento do agente. Vamos focar o modelo de pipeline de voz.</p><h3>Principais componentes</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7dbeb09a3743f38d/6a17de9caf47b67330cdde7d/b237501903f9c3a71fe1b7755c3990e40c5495c8-1600x653.png" alt="Arquitetura para construir um agente de voz de IA com o Elastic Agent Builder" /><h4>Transcrição (fala para texto)</h4><p>A transcrição é o ponto de entrada no pipeline de voz. O componente de transcrição recebe como entrada quadros de áudio brutos, transcreve a fala em texto e gera esse texto como saída. O texto transcrito é armazenado em buffer até que o sistema detecte que a fala do usuário terminou, momento em que a geração do LLM é iniciada. Diversos fornecedores terceirizados oferecem transcrições de baixa latência. Ao selecionar um, leve em consideração a latência e a precisão da transcrição, e certifique-se de que ele suporte transcrições em fluxo contínuo.</p><p></p><p>Exemplos de APIs de terceiros: <a href="https://www.assemblyai.com/">AssemblyAI</a>, <a href="https://deepgram.com/product/speech-to-text">Deepgram</a>, <a href="https://platform.openai.com/docs/guides/realtime-transcription">OpenAI</a>, <a href="https://elevenlabs.io/speech-to-text">ElevenLabs</a></p><h4>Detecção de curva</h4><p>A detecção de turno é o componente do pipeline que detecta quando o falante termina de falar e a geração deve começar. Uma maneira comum de fazer isso é por meio de um modelo de detecção de atividade de voz (VAD), como o <a href="https://github.com/snakers4/silero-vad">Silero VAD</a>. O VAD utiliza níveis de energia do áudio para detectar quando o áudio contém fala e quando a fala terminou. No entanto, o VAD sozinho não consegue identificar a diferença entre pausa e fim da fala. Por isso, muitas vezes é combinado com um modelo de fim de enunciado que prevê se o falante terminou de falar, com base na transcrição intermediária ou no áudio bruto.</p><p>Exemplos (Hugging Face): <a href="https://huggingface.co/livekit/turn-detector">livekit/turn-detector</a>, <a href="https://huggingface.co/pipecat-ai/smart-turn-v3">pipecat-ai/smart-turn-v3</a></p><h4>Agente</h4><p>O agente é o núcleo de um pipeline de voz. É responsável por entender a intenção, reunir o contexto certo e formular uma resposta em formato de texto. <a href="https://www.elastic.co/elasticsearch/agent-builder">O Elastic Agent Builder</a>, com suas capacidades integradas de raciocínio, biblioteca de ferramentas e integração de fluxos de trabalho, é um agente capaz de trabalhar sobre seus dados e interagir com serviços externos.</p><h4>LLM (texto para texto)</h4><p>Ao selecionar um LLM para o Elastic Agent Builder, há duas características principais a considerar: benchmarks de raciocínio de LLM e tempo até o primeiro token (TTFT).</p><p>Benchmarks de raciocínio indicam quão bem o LLM consegue gerar respostas corretas. Os benchmarks a serem considerados são aqueles que avaliam a adesão à conversa em múltiplos turnos e os benchmarks de inteligência, como o MT-Bench e o conjunto de dados Humanity's Last Exam, respectivamente.</p><p>Os benchmarks TTFT avaliam a rapidez com que o modelo produz seu primeiro token de saída. Existem outros tipos de benchmarks de latência, mas a TTFT é particularmente importante para agentes de voz, pois a síntese de áudio pode começar assim que o primeiro token é recebido, resultando em menor latência entre os turnos, uma conversa com sensação natural.</p><p>Normalmente, é preciso fazer uma troca entre essas duas características porque modelos mais rápidos geralmente têm um desempenho pior em benchmarks de raciocínio.</p><p>Exemplos (Hugging Face): <a href="https://huggingface.co/openai/gpt-oss-20b">openai/gpt-oss-20b</a>, <a href="https://huggingface.co/openai/gpt-oss-120b">openai/gpt-oss-120b</a></p><h4>Síntese (texto para fala)</h4><p>A parte final do pipeline é o modelo de conversão de texto em fala. Esse componente é responsável por converter a saída de texto do LLM em fala audível. Semelhante ao LLM, a latência é uma característica a ser observada ao selecionar um provedor de texto para fala. A latência de texto para fala é medida pelo tempo até o primeiro byte (TTFB). Esse é o tempo que leva para receber o primeiro byte de áudio. Menor TTFB também reduz a latência de giro.</p><p>Exemplos: <a href="https://elevenlabs.io/text-to-speech-api">ElevenLabs</a>, <a href="https://cartesia.ai/sonic">Cartesia</a>, <a href="https://www.rime.ai/">Rime</a></p><h4>Construção do pipeline de voz</h4><p>O Elastic Agent Builder pode ser integrado a um pipeline de voz em vários níveis diferentes:</p><ol><li><p>Ferramentas apenas do Agent Builder: fala para texto → LLM (com ferramentas Agent Builder) → texto para fala</p></li><li><p>Agent Builder como MCP: fala para texto → LLM (com acesso ao Agent Builder via MCP) → texto para fala</p></li><li><p>Agent Builder como núcleo: conversão de fala em texto → Agent Builder → conversão de texto em fala</p></li></ol><p>Para este projeto, escolhi o Agent Builder como abordagem núcleo. Com essa abordagem, toda a funcionalidade do Agent Builder e dos fluxos de trabalho pode ser utilizada. O projeto usa o LiveKit para orquestrar a conversão de fala em texto, detecção de turnos e conversão de texto em fala, e implementa um node LLM personalizado que se integra diretamente ao Agent Builder.</p><h2>Agente de voz do suporte da Elastic</h2><p>Criaremos um agente de voz de suporte personalizado para uma loja de esportes fictícia chamada ElasticSport. Os clientes poderão ligar para a linha de ajuda, solicitar recomendações de produtos, encontrar detalhes do produto, verificar o status do pedido e receber as informações do pedido por mensagem de texto. Para isso, primeiro precisamos configurar um agente personalizado e criar ferramentas para executar a Elasticsearch linguagem de consulta (ES|QL) e fluxos de trabalho.</p><h3>Configurando o agente</h3><h4>Prompt</h4><p>O prompt orienta o agente qual a personalidade que deve ter e como responder. É importante ressaltar que há alguns prompts específicos de voz que garantem que as respostas sejam sintetizadas em áudio adequadamente e que os mal-entendidos sejam recuperados de forma graciosa.</p>You are a Sales Assistant at ElasticSport, an outdoor sport shop specialized in hiking and winter equipment. 

[Profile]
- name: Iva
- company: ElasticSport
- role: Sales Assistant
- language: en-GB
- description: ElasticSport virtual sales assistant

[Context]
- Ask clarifying questions to understand the context.
- Use available tools to answer the user's question.
- Use the knowledge base to retrieve general information

[Style]
- Be informative and comprehensive.
- Maintain a professional, friendly and polite tone.
- Mimic human behavior and speech patterns.
- Be concise. Do not over explain initially

[Response Guideline]
- Present dates in spelled-out month date format (e.g., January fifteenth, two thousand and twenty-four).
- Avoid the use of unpronounceable punctuation such as bullet points, tables, emojis.
- Respond in plain text, avoid any formatting.
- Spell out numbers as words for more natural-sounding speech.
- Respond in short and concise sentences. Responses should be 1 or 2 sentences long.

[ERROR RECOVERY]
### Misunderstanding Protocol
1. Acknowledge potential misunderstanding
2. Request specific clarification<h4>Fluxos de trabalho</h4><p>Vamos adicionar um pequeno fluxo de trabalho para enviar um SMS pela API de mensagens do Twilio. O fluxo de trabalho será exposto ao agente personalizado como uma ferramenta, resultando em uma experiência de usuário em que o agente poderá enviar um SMS ao chamador durante a chamada. Isso permite que o autor da chamada, por exemplo, pergunte: "Você pode enviar os detalhes sobre <em>X</em> por texto?"</p>name: send sms
enabled: true
triggers:
  - type: manual
inputs:
  - name: message
    type: string
    description: The message to send to the phone number.

  - name: phone_number
    type: string
    description: The phone number to send the message to.

consts:
  TWILIO_ACCOUNT: "****"
  BASIC_AUTH: "****"
  FROM_PHONE_NNUMBER: "****"
steps:
  - name: http_step
    type: http
    with:
      url: https://api.twilio.com/2010-04-01/Accounts/{{consts.TWILIO_ACCOUNT}}/Messages.json
      method: POST
      headers:
        Content-Type: application/x-www-form-urlencoded
        Authorization: Basic {{consts.BASIC_AUTH | base64_encode}}
      body: From={{consts.FROM_PHONE_NNUMBER}}&amp;To={{inputs.phone_number}}&amp;Body={{inputs.message}}
      timeout: 30s<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt960a9395fb0985bf/6a17de9e4b055d1dff4320f0/b057e71b0a7c50eb3da47cd4f95e77ec7b4c6126-1600x1245.png" alt="Crie uma nova ferramenta para agente de voz com IA com o construtor Elastic Agent" /><h4>Ferramentas ES|QL</h4><p>As ferramentas a seguir permitem que o agente forneça respostas relevantes fundamentadas em dados reais. O repositório de exemplo contém um script de configuração para iniciar o Kibana com conjuntos de dados de produtos, pedidos e base de conhecimento.</p><ul><li><p><strong>Product.search</strong></p></li></ul><p>O conjunto de dados de produtos contém 65 produtos fictícios. Este é um documento de exemplo:</p>{
      "sku": "ort3M7k",
      "name": "Ortovox Free Rider 26 Backpack",
      "price": 189,
      "currency": "USD",
      "image": "https://via.placeholder.com/150",
      "description": "The Ortovox Free Rider 26 is a technical freeride backpack with a dedicated safety compartment and diagonal ski carry system. Perfect for backcountry missions.\n\nKey Features:\n- 26L capacity\n- Diagonal ski carry system\n- Safety equipment compartment\n- Helmet holder\n- Hydration system compatible",
      "category": "Accessories",
      "subCategory": "Backpacks",
      "brand": "Ortovox",
      "sizes": ["One Size"],
      "colors": ["Black", "Blue", "Orange"],
      "materials": ["Nylon", "Polyester"]
    }<p>Os campos de nome e descrição são mapeados como <code>semantic_text</code>, permitindo que o LLM use busca semântica via ES|QL para recuperar produtos relevantes. A consulta de busca híbrida realiza correspondência semântica em ambos os campos, com um peso um pouco maior aplicado às correspondências no campo do nome usando um boost.</p><p>A consulta primeiro recupera os 20 melhores resultados classificados pela pontuação inicial de relevância. Esses resultados são então reclassificados com base no campo de descrição usando o modelo de inferência <code>.rerank-v1-elasticsearch</code> e, finalmente, reduzidos para os cinco produtos mais relevantes.</p>type: ES|QL
toolId: products.search
description: Use this tool to search through the product catalogue by keywords.
query: |
    FROM products
        METADATA _score
      | WHERE
          MATCH(name, ?query, {"boost": 0.6}) OR
            MATCH(description, ?query, {"boost": 0.4})
      | SORT _score DESC
      | LIMIT 20
      | RERANK ?query
            ON description
            WITH {"inference_id": ".rerank-v1-elasticsearch"}
      | LIMIT 5

parameters:
    query: space separated keywords to search for in catalogue<ul><li><p><strong>Knowledgebase.search</strong></p></li></ul><p>Os conjuntos de dados da base de conhecimento contêm documentos do seguinte formato, onde os campos de título e conteúdo são armazenados como texto semântico:</p>{
        id: "8273645",
        createdAt: "2025-11-14",
        title: "International Orders",
        content: `International orders are processed through our international shipping partner. Below are the countries we ship to and average delivery times.
        Germany: 3-5 working days
        France: 3-5 working days
        Italy: 3-5 working days
        Spain: 3-5 working days
        United Kingdom: 3-5 working days
        United States: 3-5 working days
        Canada: 3-5 working days
        Australia: 3-5 working days
        New Zealand: 3-5 working days
        `
}<p>E a ferramenta usa uma consulta semelhante à ferramenta<code>product.search</code>:</p>type: "ES|QL"
toolId: knowledgebase.search
description: Use this tool to search the knowledgebase.
query: |
  FROM knowledge_base
    METADATA _score
  | WHERE
      MATCH(title, ?query, {"boost": 0.6}) OR
      MATCH(content, ?query, {"boost": 0.4})
  | SORT _score DESC
  | LIMIT 20
  | RERANK ?query
      ON content
      WITH {"inference_id": ".rerank-v1-elasticsearch"}
  | LIMIT 5

parameters:
  query: space separated keywords or natural language phrase to semantically search for in the knowledge base<ul><li><p><strong>Orders.search</strong></p></li></ul><p>A última ferramenta que adicionaremos é aquela usada para recuperar pedidos por <code>order_id</code>:</p>type: "ES|QL"
toolId: order.search
description: Use this tool to retrieve an order by its ID.
query: |
  FROM orders
    METADATA _score
  | WHERE order_id == ?order_id
  | SORT _score DESC
  | LIMIT 1

parameters:
  order_id: "the ID of the order"<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfaaf9634f27f70d7/6a17dea07f6f15b8d2c09a3d/d22bdd540a95b5a9c2bd5f308620835e8e6f7ecb-1600x1361.png" alt="configurando agente de voz" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8f4c704ab96c294a/6a17dea23e03d74af14f2b7e/d91709a50fb5391876b714885242d998b2b21027-1600x1443.png" alt="Ferramentas de agente de voz" /><p>Após configurar o agente e anexar esses fluxos de trabalho e ES|QL para o agente, o agente pode ser testado dentro do Kibana.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdbfd2934a9582c04/6a17dea463baff1532741b5e/8691f41624247a6b1352d158c970031e1426ce5e-1600x1056.png" alt="Testando agente de voz" /><p>Além de construir um agente de suporte ElasticSport, o agente, fluxos de trabalho e ferramentas podem ser adaptados a outros casos de uso, como um agente de vendas que qualifica leads, um agente de serviço para reparos residenciais, reservas para um restaurante ou um agente de agendamento de consultas.</p><p></p><p>A parte final é conectar o agente que acabamos de criar com modelos LiveKit, texto para fala e fala para texto. O repositório (link no fim do artigo) contém um node personalizado do LLM Elastic Agent Builder que pode ser usado com o LiveKit. Basta trocar o <code>AGENT_ID</code> pelo seu e vinculá-lo com sua instância Kibana.</p><h2>Para começar</h2><p>Confira o código e experimente <a href="https://github.com/KDKHD/elastic_agent_builder_livekit">você mesmo aqui</a>. </p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-voice-agents-elastic-agent-builder</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-voice-agents-elastic-agent-builder</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Kenneth Kreindler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2732d87a324baa78/6a17dea6e9ea873632a9c4cc/43ceabb9e2c0966261c188bd40e03178d5a91e5c-1280x720.png" length="0" type="image/png"/>
    <pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Gerenciando a memória agentiva com o Elasticsearch]]></title>
    <description><![CDATA[Criando agentes mais conscientes do contexto e eficientes gerenciando memórias usando o Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Na disciplina emergente da <strong>engenharia de contexto</strong>, é fundamental fornecer aos agentes de IA as informações certas no momento certo. Um dos aspectos mais importantes da engenharia de contexto é o gerenciamento da <strong>memória</strong> de uma IA. Assim como os humanos, sistemas de IA dependem tanto de memória de curto prazo quanto de memória de longo prazo para recordar informações. Se quisermos que agentes de grandes modelos de linguagem (LLM) mantenham conversas lógicas, lembrem das preferências do usuário ou construam sobre resultados ou respostas anteriores, precisamos equipá-los com mecanismos de memória eficazes.</p><p>Afinal, tudo no contexto influencia as respostas da IA. O princípio <em>Lixo entra, lixo saí</em> continua válido.</p><p>Neste artigo, vamos apresentar o que as memórias de curto e longo prazo significam para agentes de IA, especificamente:</p><ul><li><p>A diferença entre memória de curto e longo prazo.</p></li><li><p>Como elas se relacionam com as técnicas de Retrieval-Augmented Generation (RAG) com bancos de dados vetoriais, como o Elasticsearch, e por que é necessário um gerenciamento cuidadoso da memória.</p></li><li><p>Os riscos de negligenciar a memória, incluindo transbordamento de contexto e envenenamento do contexto.</p></li><li><p>Boas práticas, como a eliminação do contexto, o resumo e a recuperação apenas do que é relevante, visam manter a memória de um agente útil e segura.</p></li><li><p>Por fim, vamos abordar como a memória pode ser compartilhada e propagada em sistemas multiagente para permitir que agentes colaborem sem confusão usando o Elasticsearch.</p></li></ul><h2>Memória de curto prazo versus memória de longo prazo em agentes de IA</h2><p><em><strong>Memória de curto prazo</strong></em> em um agente de IA geralmente se refere ao contexto conversacional imediato ou estado — essencialmente, o histórico atual da conversa ou mensagens recentes na sessão ativa. Isso inclui a consulta mais recente do usuário e as trocas de mensagens recentes. É muito semelhante à informação que uma pessoa mantém em mente durante uma conversa em andamento.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blteb714ce810d1c472/6a170f321949f782cbe7aaf6/4fbcc6f68055b2bccefc4176297a4ca50056dc0d-764x498.png" alt="Memória agentiva de curto e longo prazo" /><p>Frameworks de IA frequentemente mantêm essa memória transitória como parte do estado do agente (por exemplo, usando um mecanismo de ponto de verificação para armazenar o estado da conversa, conforme abordado <a href="https://docs.langchain.com/oss/python/langgraph/persistence#checkpoints">por este exemplo do LangGraph</a>). A memória de curto prazo tem <em><strong>escopo de sessão</strong></em>, ou seja, existe em uma única conversa ou tarefa e é redefinida ou apagada quando a sessão termina, a menos que seja explicitamente salva em outro lugar. Um exemplo de memória de curto prazo ligada a sessões seria o <a href="https://help.openai.com/en/articles/8914046-temporary-chat-faq"><strong>chat temporário</strong></a>disponível no ChatGPT.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4b8680e22d4e1185/6a170f341949f78bbae7aafa/150bdf209cda5ed20b59cddf34e624ad1a8016aa-1100x577.png" alt="Memória de frameworks de IA" /><p><em><strong>A memória de longo prazo</strong></em>, por outro lado, refere-se a informações que persistem <strong>ao longo de conversas ou sessões</strong>. Este é o conhecimento que um agente retém ao longo do tempo, fatos que aprendeu anteriormente, preferências do usuário ou quaisquer dados que pedimos para ele lembrar permanentemente.</p><p>A memória de longo prazo geralmente é implementada armazenando e recuperando dados de uma fonte externa, como um arquivo ou banco de dados vetorial fora do contexto imediato da janela. Diferentemente do histórico de chats de curto prazo, a memória de longo prazo não é incluída automaticamente em todas as solicitações. Em vez disso, com base em um determinado cenário, o agente deve <strong>recordá-lo</strong> ou recuperá-lo quando as ferramentas relevantes forem invocadas. Na prática, a memória de longo prazo pode incluir informações de perfil do usuário, respostas ou análises anteriores produzidas pelo agente, ou uma base de conhecimento que o agente pode consultar.</p><p>Por exemplo, se você tiver um agente de planejamento de viagens, a <em>memória de curto prazo</em> conterá detalhes da consulta de viagem atual (datas, destino, orçamento) e quaisquer perguntas subsequentes feitas durante o chat; enquanto a <em>memória de longo prazo</em> poderá armazenar as preferências gerais de viagem do usuário, itinerários anteriores e outros dados compartilhados em sessões anteriores. Quando o usuário retornar posteriormente, o agente poderá recorrer a esse histórico (por exemplo, o usuário adora praias e montanhas, tem um orçamento médio de 100.000 rúpias indianas, possui uma lista de lugares para visitar antes de morrer e prefere vivenciar história e cultura em vez de atrações voltadas para crianças), de modo que não trate o usuário como uma folha em branco a cada vez.</p><p>A memória de curto prazo (histórico de chats) fornece contexto e continuidade imediatos, enquanto a memória de longo prazo fornece um contexto mais amplo que o agente pode usar quando necessário. Os frameworks de agentes de IA mais avançados permitem ambas as coisas: mantêm o controle dos diálogos recentes para manter o contexto <em>e</em> oferecem mecanismos para consultar ou armazenar informações em um repositório de longo prazo. O gerenciamento da memória de curto prazo garante que ela permaneça dentro da janela de contexto, enquanto o gerenciamento da memória de longo prazo ajuda o agente a basear as respostas com base em interações e personalidades anteriores.</p><h2>Memória e RAG na engenharia de contexto</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt98c1514741bea460/6a170f36509168083ce1bbae/46635aa11ceff89b8d6a26ac3e22da52407d82f3-1600x900.png" alt="Memória e RAG na engenharia de contexto" /><p><em><strong>Como damos a um agente de IA uma memória útil de longo prazo na prática?</strong></em></p><p>Uma abordagem proeminente para a memória de longo prazo é a <em><strong>memória semântica</strong></em>, frequentemente implementada por meio de <strong>retrieval-augmented generation (RAG)</strong>. Isso envolve acoplar o LLM a um armazenamento de conhecimento externo ou a um datastore habilitado por vetor, como o Elasticsearch. Quando o LLM precisa de informações além do que está no prompt ou em seu treinamento integrado, ele realiza uma recuperação semântica contra o Elasticsearch e injeta os resultados mais relevantes no prompt como contexto. Dessa forma, o contexto efetivo do modelo inclui não apenas a conversa recente (memória de curto prazo), mas também fatos pertinentes de longo prazo obtidos em tempo real. O LLM então fundamenta sua resposta tanto em seu próprio raciocínio quanto nas informações recuperadas, combinando efetivamente memória de curto prazo e memória de longo prazo para produzir uma resposta mais precisa e consciente do contexto.</p><p>O <strong>Elasticsearch </strong>pode ser usado para implementar memória de longo prazo para agentes de IA. Aqui está um exemplo de alto nível de como o contexto pode ser recuperado do Elasticsearch para memória de longo prazo.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt44f5a6887b0bca32/6a170f37a6c2b9c735e797be/41ccbc7b5171e8170ac300139a963c0708816ba6-1600x900.png" alt="RAG em ação" /><p>Dessa forma, o agente "se lembra" pesquisando dados relevantes em vez de armazenar tudo em seu prompt limitado, <strong>onde isso leva a diferentes riscos.</strong></p><p><strong>Usar RAG com o Elasticsearch ou qualquer armazenamento vetorial oferece múltiplos benefícios:</strong></p><p>Primeiro, ele <strong>amplia o conhecimento</strong> do modelo além do limite de treinamento. O agente pode recuperar informações atualizadas ou dados específicos do domínio que o LLM talvez não conheça. Isso é crucial para perguntas sobre eventos recentes ou tópicos especializados.</p><p>Em segundo lugar, recuperar o contexto sob demanda ajuda a reduzir alucinações, especialmente porque os LLMs não são treinados com dados proprietários ou altamente especializados relativos ao seu caso de uso específico, o que é muito provável que os exponha a alucinações. Em vez de o LLM adivinhar ou inventar novas informações, como tem sido incentivado pela avaliação, conforme destacado em um artigo recente da OpenAI (<a href="https://arxiv.org/pdf/2509.04664">Why Language Models Hallucinate</a>), o modelo pode ser fundamentado em referências factuais do Elasticsearch. Naturalmente, o LLM depende da confiabilidade dos dados no armazenamento vetorial para realmente evitar desinformação e os dados relevantes são recuperados de acordo com as medidas de relevância do núcleo.</p><p>Terceiro, o RAG permite que um agente trabalhe com bases de conhecimento muito maiores do que qualquer coisa que você poderia encaixar em um prompt. Em vez de inserir documentos inteiros, como longos artigos de pesquisa ou documentos de políticas, na janela de contexto e correr o risco de sobrecarga ou de informações irrelevantes <a href="https://www.elastic.co/search-labs/blog/agentic-memory-management-elasticsearch#context-poisoning">contaminarem</a> o raciocínio do modelo, o RAG se baseia em <a href="https://www.elastic.co/search-labs/blog/chunking-strategies-elasticsearch">fragmentação</a>. Documentos grandes são divididos em partes menores e semanticamente significativas, e o sistema recupera apenas os poucos trechos mais relevantes para a consulta. Dessa forma, o modelo não precisa de um contexto de um milhão de tokens para parecer conhecedor; ele só precisa de acesso aos pedaços certos de um corpus muito maior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4c90f81a56db0a33/6a170f3960084be7ba3c462e/e6897356c9f0940e35a63d005e9cd20bc33e5dd7-1600x931.png" alt="Evolução da engenharia de contexto de LLM" /><p>Vale ressaltar que, com o aumento das janelas de contexto do LLM (<a href="https://www.anthropic.com/news/1m-context">alguns modelos agora suportam centenas de milhares ou até milhões de tokens</a><em>)</em>, surgiu um debate sobre se o RAG está "morto". Por que não enviar todos os dados para o prompt? Se você pensa da mesma forma, consulte este maravilhoso artigo de meus colegas Jeffrey Rengifo e Eduard Martin, <a href="https://www.elastic.co/search-labs/blog/rag-vs-long-context-model-llm">Longer context ≠ better: Why RAG still matters</a>. Isso evita o problema de "lixo entra, lixo sai": o LLM fica focado nos poucos pedaços que importam, em vez de passar por meio de ruído.</p><p>Dito isso, integrar o Elasticsearch ou qualquer armazenamento vetorial em uma arquitetura de agente de IA fornece <strong>memória de longo prazo</strong>. O agente armazena conhecimento externamente e o recolhe como contexto de memória quando necessário. Isso poderia ser implementado como uma <em>arquitetura</em>, onde, após cada consulta do usuário, o agente realiza uma busca no Elasticsearch por informações relevantes e então adiciona os principais resultados ao prompt antes de chamar o LLM. A resposta também pode ser salva de volta no armazenamento de longo prazo se contiver informações novas úteis (criando um ciclo de retroalimentação de aprendizado). Ao usar essa memória baseada em recuperação, o agente permanece informado e atualizado, sem precisar condensar tudo o que sabe em cada prompt, mesmo que a janela de contexto suporte <em>um milhão de tokens</em>. Essa técnica é uma pedra angular da engenharia de contexto, combinando os pontos fortes da recuperação de informação e da IA generativa. </p><p>Aqui está um exemplo de um estado gerenciado de conversa em memória usando o sistema de ponto de verificação do LangGraph para memória de curto prazo durante a sessão. (Consulte nosso <a href="https://github.com/someshwaranM/elastic-context-engineering-short-term-long-term-memory">app de engenharia de contexto de suporte</a>).</p># Initialize chat memory (Note: This is in-memory only, not persistent)
memory = MemorySaver()

# Create a LangGraph agent
langgraph_agent = create_react_agent(model=llm, tools=tools, checkpointer=memory)

...
...
# Only process and display checkpoints if verbose mode is enabled
if args.verbose:
    # List all checkpoints that match a given configuration
    checkpoints = memory.list({"configurable": {"thread_id": "1"}})
    # Process the checkpoints
    process_checkpoints(checkpoints)<p>Veja como ele armazena <strong>pontos de verificação</strong>:</p>Checkpoint:
Timestamp: 2025-12-30T09:19:41.691087+00:00
Checkpoint ID: 1f0e560a-c2fa-69ec-8001-14ee5373f9cf
User: Hi I'm Som, how are you? (Message ID: ad0a8415-5392-4a58-85ad-84154875bbf2)
Agent: Hi Som! I'm doing well, thank you! How about you? (Message ID: 
56d31efb-14e3-4148-806e-24a839799ece)
Agent:  (Message ID: lc_run--019b6e8e-553f-7b52-8796-a8b1fbb206a4-0)

Checkpoint:
Timestamp: 2025-12-30T09:19:40.350507+00:00
Checkpoint ID: 1f0e560a-b631-6a08-8000-7796d108109a
User: Hi I'm Som, how are you? (Message ID: ad0a8415-5392-4a58-85ad-84154875bbf2)
Agent: Hi Som! I'm doing well, thank you! How about you? (Message ID: 
56d31efb-14e3-4148-806e-24a839799ece)

Checkpoint:
Timestamp: 2025-12-30T09:19:40.349027+00:00
Checkpoint ID: 1f0e560a-b62e-6010-bfff-cbebe1d865f6<p>Para a memória de longo prazo, veja como realizamos a busca semântica no Elasticsearch para recuperar conversas anteriores relevantes usando embeddings de vetor após resumir e a indexar pontos de verificação no Elasticsearch.</p>Functions: 
retrieve_from_elasticsearch() 

# Enhanced Elasticsearch retrieval with rank_window and verbose display
def retrieve_from_elasticsearch(query: str, k: int = 5, rank_window: int = None) -&gt; tuple[List[Dict[str, Any]], str]:
    """
    Retrieve context from Elasticsearch with score-based ranking
    
    Args:
        query: Search query
        k: Number of results to return
        rank_window: Number of candidates to retrieve before ranking (default: args.rank_window)
        
    Returns:
        Tuple of (retrieved_documents, formatted_context_string)
    """
    if not es_client or not es_index_name:
        return [], "Elasticsearch is not available. Cannot search long-term memory."
    
    if rank_window is None:
        rank_window = args.rank_window
    
    try:
        # Check if index exists and has documents
        if not es_client.indices.exists(index=es_index_name):
            return [], "No previous conversations stored in long-term memory yet."
        
        # Get document count
        try:
            doc_count = es_client.count(index=es_index_name)["count"]
            if doc_count == 0:
                return [], "Long-term memory is empty. No previous conversations to search."
        except Exception as e:
            return [], f"Error checking memory: {str(e)}"
        
        # Generate embedding for the query
        try:
            query_embedding = embeddings.embed_query(query)
        except Exception as e:
            return [], f"Error generating embedding: {str(e)}"
        
        # Perform semantic search using kNN with rank_window
        try:
            search_body = {
                "knn": {
                    "field": "vector",
                    "query_vector": query_embedding,
                    "k": k,
                    "num_candidates": rank_window  # Retrieve more candidates, then rank top k
                },
                "_source": ["text", "content", "message_type", "timestamp", "thread_id"],
                "size": k
            }
            
            response = es_client.search(index=es_index_name, body=search_body)
            
            if not response.get("hits") or len(response["hits"]["hits"]) == 0:
                return [], "No relevant previous conversations found in long-term memory."
            
            # Extract documents with scores
            retrieved_docs = []
            for hit in response["hits"]["hits"]:
                source = hit["_source"]
                score = hit["_score"]
                retrieved_docs.append({
                    "content": source.get("content", source.get("text", "")),
                    "message_type": source.get("message_type", "unknown"),
                    "timestamp": source.get("timestamp", "unknown"),
                    "thread_id": source.get("thread_id", "unknown"),
                    "score": score
                })
            
            # Format context string
            context_parts = []
            for i, doc in enumerate(retrieved_docs, 1):
                context_parts.append(doc["content"])
            
            context_string = "\n\n".join(context_parts)
            
            # Verbose display
            if args.verbose:
                rich.print(f"\n[bold yellow]🔍 RETRIEVAL ANALYSIS[/bold yellow]")
                rich.print("="*80)
                rich.print(f"[blue]Query:[/blue] {query}")
                rich.print(f"[blue]Retrieved:[/blue] {len(retrieved_docs)} documents (from {rank_window} candidates)")
                rich.print(f"[blue]Total context length:[/blue] {len(context_string)} characters\n")
                
                for i, doc in enumerate(retrieved_docs, 1):
                    rich.print(f"[cyan]📄 Document {i} | Score: {doc['score']:.4f} | Type: {doc['message_type']}[/cyan]")
                    rich.print(f"[cyan]   Timestamp: {doc['timestamp']} | Thread: {doc['thread_id']}[/cyan]")
                    content_preview = doc['content'][:200] + "..." if len(doc['content']) &gt; 200 else doc['content']
                    rich.print(f"[cyan]   Content: {content_preview}[/cyan]")
                    rich.print("-" * 80)
            
            return retrieved_docs, context_string
            
        except Exception as e:
            return [], f"Error searching memory: {str(e)}"
            
    except Exception as e:
        return [], f"Error accessing long-term memory: {str(e)}"<p>Agora que exploramos como a memória de curto prazo e a memória de longo prazo são indexadas e buscadas usando os pontos de verificação do LangGraph no Elasticsearch, vamos tirar um tempo para entender por que a indexação e o despejo das conversas completas podem ser arriscados.</p><h2>Riscos de não gerenciar a memória de contexto</h2><p>Como estamos falando muito sobre engenharia de contexto, junto com memória de curto e longo prazo, vamos entender o que acontece se não gerenciarmos bem a memória e o contexto de um agente.</p><p>Infelizmente, muitas coisas podem dar errado quando o contexto de uma IA se torna extremamente longo ou contém informações erradas. À medida que as janelas de contexto aumentam, <strong>surgem novos modos de falha</strong>, como:</p><ul><li><p><strong>Envenenamento de contexto</strong></p></li><li><p><strong>Distração contextual</strong></p></li><li><p><strong>Confusão de contexto</strong></p></li><li><p><strong>Conflito de contexto</strong></p></li><li><p><strong>Vazamento de contexto e conflitos de conhecimento</strong></p></li><li><p><strong>Alucinações e desinformação</strong></p></li></ul><p>Vamos analisar esses problemas e outros riscos que surgem do gerenciamento inadequado de contexto:</p><h3>Envenenamento de contexto</h3><p>O <em>envenenamento do contexto</em> refere-se a quando informações incorretas ou prejudiciais acabam no contexto e "envenenam" as saídas subsequentes do modelo. Um exemplo comum é uma alucinação do modelo que é tratada como fato e inserida no histórico da conversa. O modelo pode então construir sobre esse erro em respostas posteriores, agravando o erro. Em ciclos iterativos de agentes, uma vez que uma informação falsa entra no contexto compartilhado (por exemplo, em um resumo das notas de trabalho do agente), ela pode ser reforçada repetidamente. </p><p><a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf">Pesquisadores da DeepMind, no lançamento do relatório Gemini 2.5</a> (TL;DR, veja <a href="https://www.dbreunig.com/2025/06/17/an-agentic-case-study-playing-pok%C3%A9mon-with-gemini.html">aqui</a>), observaram o seguinte em um agente que jogava <em>Pokémon</em>: se o agente alucinasse um estado incorreto de jogo e isso fosse registrado em seu <em>contexto </em>(a memória de objetivos), o agente criaria <strong>estratégias sem sentido</strong> em torno de um objetivo impossível e ficaria preso. Em outras palavras, uma memória envenenada pode levar o agente pelo caminho errado indefinidamente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd56e9e0681f32239/6a170f3b4a531bd79536aa21/3f2facf5aad67613ad557422e09ec23a66adc0ed-1600x1388.png" alt="Envenenamento de contexto" /><p>O envenenamento de contexto pode acontecer inocentemente (por engano) ou até mesmo de forma mal-intencionada, por exemplo, por meio de ataques de injeção de prompt, onde um usuário ou terceiro introduz uma instrução oculta ou um fato falso que o agente então lembra e segue.</p><p><strong>Contramedidas recomendadas:</strong></p><p>Com base nos insights de <a href="https://www.wiz.io/academy/data-poisoning">Wiz</a>, <a href="https://zerlo.net/en/blog/what-is-llm-data-poisoning">Zerlo</a> e <a href="https://www.anthropic.com/research/small-samples-poison">Anthropic</a>, as contramedidas para envenenamento de contexto se concentram em evitar que informações ruins ou enganosas entrem no prompt, na janela de contexto ou no pipeline de recuperação de um LLM. Os principais passos incluem:</p><ul><li><p>Verifique o contexto constantemente: monitore a conversa ou o texto recuperado para qualquer coisa suspeita ou prejudicial, não apenas o prompt inicial.</p></li><li><p>Use fontes confiáveis: pontue ou rotule documentos com base na credibilidade para que o sistema prefira informações confiáveis e ignore dados com pontuação baixa.</p></li><li><p>Identifique dados incomuns: use ferramentas que detectem conteúdo estranho, fora de lugar ou manipulado, e remova-o antes que o modelo os utilize.</p></li><li><p>Filtre entradas e saídas: adicione proteções de segurança para que textos prejudiciais ou enganosos não possam entrar facilmente no sistema ou ser repetidos pelo modelo.</p></li><li><p>Mantenha o modelo atualizado com dados limpos: atualize regularmente o sistema com informações verificadas para combater qualquer dado errado que tenha escapado.</p></li><li><p>Com supervisão humana: peça para as pessoas revisarem as saídas importantes ou compará-las com fontes conhecidas e confiáveis.</p></li></ul><p>Hábitos simples do usuário também ajudam, como redefinir chats longos, compartilhar apenas informações relevantes, dividir tarefas complexas em etapas menores e manter anotações claras fora do modelo.</p><p>Juntas, essas medidas criam uma defesa em camadas que protege os LLMs contra envenenamento do contexto e mantém as saídas precisas e confiáveis.</p><p>Sem contramedidas mencionadas aqui, um agente pode lembrar-se de instruções, como ignorar diretrizes anterioresou fatos triviais inseridos por um invasor, levando a saídas prejudiciais.</p><h3>Distração contextual</h3><p>A <em>distração de contexto</em> ocorre quando um contexto se alonga tanto que o modelo foca demais no contexto, negligenciando o que aprendeu durante o treinamento. Em casos extremos, isso se assemelha <a href="https://en.wikipedia.org/wiki/Catastrophic_interference"><em>ao esquecimento catastrófico</em></a>; ou seja, o modelo efetivamente "esquece" seu conhecimento subjacente e fica excessivamente apegado à informação que lhe é apresentada. Estudos anteriores mostraram que LLMs frequentemente perdem o foco quando o prompt é extremamente longo.</p><p>O agente Gemini 2.5, por exemplo, suportava uma janela de um milhão de tokens, mas quando seu contexto crescia além de um certo ponto (na ordem de 100.000 tokens em um experimento), ele começava a <strong>se fixar em repetir suas ações passadas</strong> em vez de apresentar novas soluções. De certa forma, o agente tornou-se prisioneiro de sua extensa história. Ele continuava observando seu longo log de movimentos anteriores (o contexto) e imitando-os, em vez de usar seu conhecimento de treinamento subjacente para criar estratégias novas e inovadoras.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91ea0056bbda6e2d/6a170f3d2b835fdd2bf4b2db/e08e5b6d2e8ec7e3511d455985eed3d7fa6241e0-1352x636.png" alt="Distração contextual " /><p>Isso é contraproducente. Queremos que o modelo use o contexto relevante para ajudar no raciocínio, não para sobrepor sua capacidade de pensar. Notavelmente, mesmo modelos com janelas enormes exibem essa <a href="https://research.trychroma.com/context-rot"><em>deterioração de contexto</em></a>: seu desempenho se degrada de forma não uniforme à medida que mais tokens são adicionados. Parece haver um <em>orçamento de atenção</em>. Como humanos com memória de trabalho limitada, um LLM tem uma capacidade finita para atender a tokens, e à medida que esse orçamento é esticado, sua precisão e foco caem.</p><p>Como mitigação, você pode evitar distração do contexto usando fragmentação, engenharia das informações corretas, resumo regular do contexto e técnicas de avaliação e monitoramento para medir a precisão da resposta usando pontuação.</p><p>Esses métodos mantêm o modelo baseado no contexto relevante e em seu treinamento subjacente, reduzindo o risco de distração e melhorando a qualidade geral do raciocínio.</p><h3>Confusão de contexto</h3><p>A <em>confusão de contexto</em> ocorre quando o conteúdo supérfluo no contexto é usado pelo modelo para gerar uma resposta de baixa qualidade. Um ótimo exemplo é fornecer a um agente um grande conjunto de ferramentas ou definições de API que ele pode usar. Se muitas dessas ferramentas não estiverem relacionadas à tarefa atual, o modelo ainda pode tentar usá-las de forma inadequada, simplesmente porque elas estão presentes no contexto. Experimentos descobriram que fornecer <em>mais</em> ferramentas ou documentos pode <em>prejudicar</em> o desempenho se não forem todos necessários. O agente começa a cometer erros, como chamar a função errada ou fazer referência a um texto irrelevante. </p><p>Em um caso, um pequeno modelo <strong>Llama 3.1 8B</strong> falhou em uma tarefa ao receber 46 ferramentas para considerar, mas teve sucesso quando recebeu apenas 19 ferramentas. As ferramentas extras criaram confusão, mesmo que o contexto estivesse dentro dos limites de duração. A questão subjacente é que qualquer informação no prompt será <em>atendida</em> pelo modelo. Se não souber ignorar algo, esse algo pode influenciar sua saída de maneiras indesejadas. Pedaços irrelevantes podem “roubar” parte da atenção do modelo e desviá-lo (por exemplo, um documento irrelevante pode fazer com que o agente responda a uma pergunta diferente da feita). A confusão de contexto frequentemente se manifesta como o modelo produzindo uma resposta de baixa qualidade que integra contextos não relacionados. Consulte o trabalho de pesquisa: <a href="https://arxiv.org/pdf/2411.15399">Menos é mais: otimizando a chamada de funções para execução LLM em dispositivos de borda.</a></p><p>Isso nos lembra que mais contexto nem sempre é melhor, especialmente se não for <strong>selecionado</strong> para ser relevante.</p><h3>Conflito de contexto</h3><p>O <em>conflito de contexto</em> ocorre quando <strong>partes do contexto se contradizem</strong>, causando inconsistências internas que comprometem o raciocínio do modelo. Um conflito pode acontecer se o agente acumular várias informações que estão em conflito. </p><p>Por exemplo, imagine um agente que obteve dados de duas fontes: uma diz que <em>o voo A parte às 17h</em>, e a outra diz que <em>o voo A parte às 18h</em>. Se ambos os fatos estiverem presentes no contexto, o modelo inadequado não terá como saber qual está correto; poderá ficar confuso ou produzir uma resposta incorreta ou não similar.</p><p>O conflito de contexto também ocorre com frequência em conversas com várias interações, em que as <strong>tentativas anteriores</strong> de resposta do modelo ainda permanecem no contexto junto com informações refinadas posteriormente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd86976266867c0ed/6a170f3e66c4f9c785f8c105/500d7a80dc8db1923f9b5ca84728eed64fa296f7-1316x580.png" alt="Conflito de contexto" /><p>Um <a href="https://arxiv.org/pdf/2505.06120">estudo realizado</a> pela Microsoft e pela Salesforce mostra que, ao dividir uma consulta complexa em várias interações com o chatbot (adicionando detalhes gradualmente), a precisão final cai significativamente em comparação com a apresentação de todos os detalhes em uma única solicitação. Por quê? Porque as primeiras interações contêm respostas intermediárias parciais ou incorretas do modelo, e essas permanecem no contexto. Quando o modelo tenta responder posteriormente com todas as informações, sua <em>memória</em> ainda inclui as tentativas erradas, que entram em conflito com as informações corrigidas e o desviam do caminho. Basicamente, o contexto da conversa entra em conflito consigo mesmo. O modelo pode, sem querer, usar um contexto desatualizado (de uma interação anterior) que não se aplica depois que novas informações são adicionadas.</p><p>Em sistemas de agentes, o choque de contexto é especialmente perigoso, pois um agente pode combinar saídas de diferentes ferramentas ou subagentes. Se essas saídas discordarem, o contexto agregado será inconsistente. O agente pode, então, ficar travado ou produzir resultados sem sentido ao tentar conciliar as contradições. Evitar conflitos de contexto envolve garantir que o contexto seja <strong>novo e consistente</strong>,por exemplo, limpar ou atualizar qualquer informação desatualizada e não misturar fontes que não tenham sido verificadas quanto à consistência.</p><h3>Vazamento de contexto e conflitos de conhecimento</h3><p>Em sistemas onde múltiplos agentes ou usuários compartilham um estoque de memória, há o risco de informações transbordarem entre os contextos.</p><p>Por exemplo, se os dados de embeddings de dois usuários diferentes residirem no mesmo banco de dados vetorial sem o devido controle de acesso, um agente que responde à consulta do Usuário A pode, acidentalmente, recuperar parte da memória do Usuário B. Esse <em><strong>vazamento entre contextos</strong></em> pode expor informações privadas ou apenas criar confusão nas respostas.</p><p>De acordo com o <a href="https://wtit.com/blog/2025/04/17/owasp-top-10-for-llm-applications-2025/">OWASP Top 10 for LLM Applications</a>, os bancos de dados vetoriais multilocatários devem se proteger contra esse tipo de vazamento:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte433216805a66d29/6a170f404a531b2c4e36aa25/8f0ccf0b2f7bd6715c14aceee2deffb213d50bd9-1600x936.png" alt="Vazamento de contexto" /><p>De acordo com <a href="https://wtit.com/blog/2025/04/17/owasp-top-10-for-llm-applications-2025/">LLM08:2025 — Fraquezas em Vetores e Embeddings</a><em>,</em> um dos riscos comuns é o vazamento de contexto:</p><em>Em ambientes multi-inquilinos onde várias classes de usuários ou aplicativos compartilham o mesmo banco de dados vetorial, existe o risco de vazamento de contexto entre usuários ou consultas. Erros de conflito de conhecimento na federação de dados podem ocorrer quando dados de múltiplas fontes se contradizem. Isso também pode ocorrer quando um LLM não consegue substituir o conhecimento antigo que aprendeu durante o treinamento pelos novos dados do Retrieval Augmentation.</em><p>Outro aspecto é que um LLM pode ter dificuldade em substituir seu <strong>conhecimento integrado</strong> por novas informações da memória. Se o modelo foi treinado em algum fato e o contexto recuperado diz o oposto, o modelo pode ficar confuso sobre qual confiar. Sem um design adequado, o agente pode misturar contextos ou não conseguir atualizar o conhecimento antigo com novas evidências, levando a respostas desatualizadas ou incorretas.</p><h3><strong>Alucinações e desinformação</strong></h3><p>Embora a <em>alucinação </em>(o LLM inventando informações plausíveis, mas falsas) seja um problema conhecido, mesmo sem contextos longos, o gerenciamento inadequado da memória pode amplificá-lo. Você pode ter que se preocupar com o fato de que o LLM não está preparado para isso. </p><p>Se faltar um fato crucial na memória do agente, o modelo pode simplesmente <strong>preencher a lacuna com um palpite</strong> e, se esse palpite entrar no contexto (envenenando-o), o erro persistirá. </p><p>O relatório de segurança OWASP LLM <a href="https://wtit.com/blog/2025/04/17/owasp-top-10-for-llm-applications-2025/"><strong>(LLM09:2025 — Desinformação)</strong></a> destaca a desinformação como uma vulnerabilidade central: os modelos de aprendizagem de linguagem (LLMs) podem produzir respostas confiantes, porém fabricadas, e os usuários podem confiar excessivamente nelas. Um agente com uma memória de longo prazo ruim ou desatualizada pode citar com segurança algo que era verdadeiro no ano passado, mas é falso agora, a menos que sua memória seja mantida atualizada. </p><p>A dependência excessiva da saída da IA (seja pelo usuário ou pelo próprio agente em um loop) pode piorar isso. Se ninguém nunca conferir as informações na memória, o agente pode acumular falsidades. É por isso que o RAG é frequentemente usado para reduzir alucinações: ao recuperar uma fonte autoritativa, o modelo não precisa inventar fatos. Mas se sua recuperação extrair o documento errado (digamos, um que contenha informações erradas) ou se uma alucinação precoce não for eliminada, o sistema poderá propagar essa desinformação por meio de suas ações. </p><p>O resultado final: deixar de gerenciar a memória pode levar a <strong>saídas incorretas e enganosas</strong>, o que pode ser prejudicial, especialmente se os riscos forem altos (por exemplo, conselhos ruins em um domínio financeiro ou médico). Um agente precisa de mecanismos para verificar ou corrigir seu conteúdo de memória, não apenas confiar incondicionalmente em qualquer coisa que esteja no contexto.</p><p>Em resumo, dar a um agente de IA uma memória infinitamente longa ou despejar todas as coisas possíveis em seu contexto <em>não</em> é uma receita para o sucesso.</p><h2>Práticas recomendadas para o gerenciamento de memória em aplicações LLM</h2><p>Para evitar as armadilhas acima, os desenvolvedores e pesquisadores criaram uma série de <strong>práticas recomendadas para gerenciar o contexto e a memória</strong> nos sistemas de IA. Essas práticas visam manter o contexto de trabalho da IA enxuto, relevante e atualizado. Aqui estão algumas das principais estratégias, além de exemplos de como elas ajudam.</p><h3>RAG: use contexto direcionado</h3><p>Grande parte do conceito RAG já foi abordada na seção anterior, portanto, este texto serve como um conjunto conciso de lembretes práticos:</p><ul><li><p>Use recuperação direcionada, não carregamento em massa: recupere apenas os trechos mais relevantes em vez de enviar documentos inteiros ou históricos completos de conversas para o prompt.</p></li><li><p>Considere o RAG como uma recuperação de memória sob demanda: busque o contexto apenas quando necessário, em vez de carregar tudo adiante entre as interações.</p></li><li><p>Prefira estratégias de recuperação com base na relevância: abordagens como busca semântica top k, fusão de classificação recíproca ou filtragem de carga de ferramentas ajudam a reduzir o ruído e melhorar o aterramento.</p></li><li><p>Janelas de contexto maiores não eliminam a necessidade do RAG: dois parágrafos altamente relevantes quase sempre são mais eficazes do que 20 páginas vagamente relacionadas.</p></li></ul><p>Dito isso, o RAG não se trata de adicionar mais contexto; trata-se de adicionar o contexto certo.</p><h3>Configuração de ferramentas</h3><p>O <em>carregamento de ferramentas</em> consiste em fornecer a um modelo apenas as ferramentas de que ele realmente precisa para uma tarefa. O termo vem de jogos: você escolhe um carregamento que se adequa à situação. Muitas ferramentas atrasam você; as erradas causam falhas. LLMs se comportam da mesma forma, segundo o artigo <a href="https://arxiv.org/abs/2411.15399">Menos é mais</a>. Depois que você passa por ~30 ferramentas, as descrições começam a se sobrepor e o modelo fica confuso. Depois de ~100 ferramentas, o fracasso é quase garantido. Isso não é um problema de janela de contexto, é confusão de contexto.</p><p>Uma solução simples e eficaz é o <a href="https://arxiv.org/abs/2505.03275"><strong>RAG-MCP</strong></a>. Em vez de inserir todas as ferramentas no prompt, as descrições das ferramentas são armazenadas em um banco de dados vetorial e somente as mais relevantes são recuperadas por solicitação. Na prática, isso mantém o carregamento pequeno e focado, encurta drasticamente os prompts e pode melhorar a precisão da seleção de ferramentas em até 3 vezes.</p><p>Modelos menores batem nessa barreira ainda mais cedo. A pesquisa mostra que um modelo 8B falha com dezenas de ferramentas, mas tem sucesso assim que o equipamento é cortado. Selecionar ferramentas dinamicamente, às vezes primeiro com um LLM, raciocinar sobre o que ele acha que precisa, pode aumentar o desempenho em 44%, além de reduzir o consumo de energia e a latência. A conclusão é que a maioria dos agentes precisa apenas de algumas ferramentas, mas à medida que seu sistema cresce, o carregamento de ferramentas e o RAG-MCP se tornam decisões de design de primeira ordem.</p><h3>Eliminação de contexto: limite o tempo do histórico de chat</h3><p>Se uma conversa continuar por várias interações, o histórico de chat acumulado pode ficar muito extenso, causando um excesso de contexto ou distraindo demais o modelo. </p><p><em>Aparar</em> significa remover ou encurtar programaticamente as partes menos importantes do diálogo à medida que ele cresce. Uma forma simples é eliminar as interações mais antigas da conversa quando você atingir um determinado limite, mantendo apenas as <em>N</em> mensagens mais recentes. Uma eliminação mais sofisticada pode remover digressões irrelevantes ou instruções anteriores que não são mais necessárias. O objetivo é <strong>manter a janela de contexto desobstruída</strong> de notícias antigas. </p><p>Por exemplo, se o agente resolveu um subproblema há 10 interações e nós seguimos em frente desde então, podemos excluir essa parte do histórico do contexto (assumindo que não será mais necessário). Muitas implementações baseadas em chat fazem isso: elas mantêm uma janela móvel de mensagens recentes. </p><p>Aparar pode ser tão simples quanto "esquecer" as partes mais iniciais de uma conversa depois que elas foram resumidas ou consideradas irrelevantes. Ao fazer isso, reduzimos o risco de erros de excesso de contexto e também diminuímos a <a href="https://www.elastic.co/search-labs/blog/agentic-memory-management-elasticsearch#context-distraction"><strong>distração do contexto</strong></a>, para que o modelo não veja e se distraia com conteúdo antigo ou fora do tema. Essa abordagem é muito parecida com como os humanos podem não lembrar cada palavra de uma conversa de uma hora, mas manterão os destaques. </p><p>Se você está confuso sobre a eliminação de contexto, como destacado pelo autor Drew Breunig <a href="https://www.dbreunig.com/2025/06/26/how-to-fix-your-context.html#tool-loadout:~:text=Provence%20is%20fast%2C%20accurate%2C%20simple%20to%20use%2C%20and%20relatively%20small%20%E2%80%93%20only%201.75%20GB.%20You%20can%20call%20it%20in%20a%20few%20lines%2C%20like%20so%3A">aqui</a>, o uso do modelo Provence (`<a href="https://huggingface.co/naver/provence-reranker-debertav3-v1">naver/provence-reranker-debertav3-v1`</a>), um eliminador de contexto leve (1,75 GB), eficiente e preciso para resposta a perguntas, pode fazer a diferença. Ele pode reduzir documentos grandes apenas para o texto mais relevante para uma determinada consulta. Você pode chamá-lo em intervalos específicos.</p><p>Veja como invocamos o modelo 'provence-reranker' em nosso código para eliminar o contexto:</p># Context pruning with Provence
def prune_with_provence(query: str, context: str, threshold: Optional[float] = None) -&gt; str:
    """
    Prune context using Provence reranker model
    
    Args:
        query: User's query/question
        context: Original context to prune
        threshold: Relevance threshold (0-1) for Provence reranker.
                   If None, uses args.pruning_threshold.
                   0.1 = conservative (recommended, no performance drop)
                   0.3-0.5 = moderate to aggressive pruning
    
    Returns:
        Pruned context with only relevant sentences
    """
    if provence_model is None:
        return context
    
    if threshold is None:
        threshold = args.pruning_threshold
    
    try:
        # Use Provence's process method
        provence_output = provence_model.process(
            question=query,
            context=context,
            threshold=threshold,
            always_select_title=False,
            enable_warnings=False
        )
        
        # Extract pruned context from output
        pruned_context = provence_output.get('pruned_context', context)
        reranking_score = provence_output.get('reranking_score', 0.0)
        
        # Log statistics
        original_length = len(context)
        pruned_length = len(pruned_context)
        reduction_pct = ((original_length - pruned_length) / original_length * 100) if original_length &gt; 0 else 0
        
        if args.verbose:
            rich.print(f"[cyan]📊 Pruning stats: {pruned_length}/{original_length} chars ({reduction_pct:.1f}% reduction, threshold={threshold:.2f}, rerank_score={reranking_score:.3f})[/cyan]")
        
        return pruned_context if pruned_context else context
        
    except Exception as e:
        rich.print(f"[yellow]⚠️ Error in Provence pruning: {str(e)}[/yellow]")
        rich.print(f"[yellow]⚠️ Falling back to original context[/yellow]")
        return context<p>Usamos o modelo Provence reranker (`naver/provence-reranker-debertav3-v1`) para pontuar a relevância da frase. A filtragem baseada em limiar mantém as sentenças acima do limiar de relevância. Além disso, introduzimos um mecanismo de fallback, no qual retornamos ao contexto original se a eliminação falhar. Por fim, o logging de estatísticas acompanha a porcentagem de redução em modo detalhado.</p><h3>Resumo do contexto: condense informações antigas em vez de descartá-las completamente</h3><p>O <em>resumo</em> é um complemento para redução. Quando a história ou a base de conhecimento se tornar muito grande, você pode usar o LLM para gerar um breve resumo dos pontos importantes e usar esse resumo no lugar do conteúdo completo daqui para frente, como fizemos no código acima.</p><p>Por exemplo, se um assistente de IA tiver tido uma conversa de 50 interações, em vez de enviar todas as 50 interações para o modelo na interação 51 (o que provavelmente não caberia), o sistema poderia pegar as interações de 1 a 40, fazer com que o modelo as resumisse em um parágrafo e, em seguida, fornecer apenas esse resumo mais as 10 últimas interações na próxima solicitação. Dessa forma, o modelo ainda sabe o que foi discutido sem precisar de todos os detalhes. Os primeiros usuários de chatbots faziam isso manualmente perguntando: "Você pode resumir o que discutimos até agora?" e então continuando em uma nova sessão com o resumo. Agora isso pode ser automatizado. O resumo não apenas economiza espaço na janela de contexto, mas também pode reduzir <strong>a confusão/distração do contexto</strong> ao eliminar detalhes extras e reter apenas os fatos mais importantes.</p><p>Veja como usamos modelos OpenAI (você pode usar qualquer LLMs) para condensar o contexto preservando todas as informações relevantes, eliminando redundância e duplicação.
</p># Context summarization
def summarize_context(query: str, context: str) -&gt; str:
    """
    Summarize context using LLM to reduce duplication and focus on relevant information
    
    Args:
        query: User's query/question
        context: Context to summarize
        
    Returns:
        Summarized context
    """
    try:
        summary_prompt = f"""You are an expert at summarizing conversation context.

Your task: Analyze the provided conversation context and produce a condensed summary that fully answers or supports the user's specific question.

The summary must:
1. Preserve every fact, detail, and information that directly relates to the question
2. Eliminate redundancy and duplicate information
3. Maintain chronological flow when relevant
4. Focus on information that helps answer: "{query}"

Context to summarize:
{context}

Provide a concise summary that preserves all relevant information:"""

        summary = llm.invoke(summary_prompt).content
        
        if args.verbose:
            original_length = len(context)
            summary_length = len(summary)
            reduction_pct = ((original_length - summary_length) / original_length * 100) if original_length &gt; 0 else 0
            rich.print(f"[cyan]📝 Summarization stats: {summary_length}/{original_length} chars ({reduction_pct:.1f}% reduction)[/cyan]")
        
        return summary
        
    except Exception as e:
        rich.print(f"[yellow]⚠️ Error in context summarization: {str(e)}[/yellow]")
        rich.print(f"[yellow]⚠️ Falling back to original context[/yellow]")
        return context<p>É importante ressaltar que, quando o contexto é resumido, o modelo tem menos probabilidade de ser sobrecarregado por detalhes triviais ou erros passados (presumindo que o resumo seja preciso). </p><p>No entanto, o resumo deve ser feito com cuidado. Um resumo ruim pode omitir um detalhe crucial ou até mesmo introduzir um erro. É basicamente mais um prompt para o modelo ("resuma isso"), então ele pode alucinar ou perder nuances. A melhor prática é resumir de forma incremental e talvez manter alguns fatos canônicos sem resumo.</p><p>Ainda assim, tem se mostrado muito útil. <a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf">No cenário do agente Gemini, </a>resumir o contexto a cada ~100k tokens era uma forma de combater a tendência do modelo de se repetir. O resumo funciona como uma memória comprimida da conversa ou dos dados. Como desenvolvedores, podemos implementar isso fazendo com que um agente chame periodicamente uma função de resumo (talvez um LLM menor ou uma rotina dedicada) no histórico de conversas ou em um documento longo. O resumo resultante substitui o conteúdo original no prompt. Essa tática é amplamente usada para manter os contextos dentro de limites e destilar as informações.</p><h3>Quarentena de contexto: isole contextos sempre que possível</h3><p>Isso é mais relevante em sistemas de agentes complexos ou fluxos de trabalho de múltiplas etapas. A ideia da segmentação de contexto é dividir uma grande tarefa em tarefas menores e isoladas, cada uma com seu próprio contexto, de modo que você nunca acumule um contexto enorme que contenha tudo. Cada subagente ou subtarefa trabalha em uma parte do problema com um contexto focado e, em seguida, um agente, supervisor ou coordenador de nível superior integra os resultados.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09d1eac7442aea2b/6a170f42dc55deb10de00ea7/f2de68c3339883d7658e633af3948f29f427e6cf-1600x900.png" alt="Quarentena de contexto" /><p><a href="https://www.anthropic.com/engineering/multi-agent-research-system">A estratégia de pesquisa da Anthropic utiliza múltiplos subagentes</a>, cada um investigando um aspecto diferente de uma questão, com suas próprias janelas de contexto, e um agente líder que lê os resultados sintetizados desses subagentes. Essa abordagem paralela e modular significa que nenhuma janela de contexto única fica excessivamente inchada. Também reduz a chance de mistura de informações irrelevantes, cada tópico permanece no tópico (sem confusão de contexto) e não carrega bagagem desnecessária ao responder sua subpergunta específica. De certa forma, é como seguir fios de pensamento separados que só compartilham seus resultados, não todo o processo de pensamento.</p><p>Em sistemas multiagente, essa abordagem é essencial. Se o Agente A estiver lidando com a tarefa A e o Agente B estiver lidando com a tarefa B, não há motivo para que um dos agentes consuma o contexto completo do outro, a menos que seja realmente necessário. Em vez disso, os agentes podem trocar apenas as informações necessárias. Por exemplo, o Agente A pode passar um resumo consolidado de suas descobertas para o Agente B por meio de um agente supervisor, enquanto cada subagente mantém seu próprio thread de contexto dedicado. Essa configuração não exige supervisão; ela depende de um agente supervisor com ferramentas habilitadas e compartilhamento de contexto mínimo e controlado.</p><p>No entanto, projetar seu sistema de modo que agentes ou ferramentas operem com a sobreposição mínima necessária de contexto pode aumentar muito a clareza e o desempenho. Pense nisso como <strong>microsserviços para IA</strong>, cada componente lida com seu contexto e você passa mensagens entre eles de forma controlada, em vez de um contexto monolítico. Essas práticas recomendadas são frequentemente usadas em combinação. Além disso, isso dá a você a flexibilidade de cortar histórico trivial, resumir mensagens ou conversas antigas importantes, transferir os logs detalhados para o Elasticsearch para contexto de longo prazo e usar a recuperação para trazer de volta qualquer coisa relevante quando necessário.</p><p>Como mencionado <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents#:~:text=While%20some%20models,to%20the%20LLM">aqui</a>, o princípio orientador é que o contexto é um recurso limitado e precioso. Você quer que cada token do prompt ganhe seu valor, ou seja, ele deve contribuir para a qualidade da saída. Se algo na memória não está fazendo sua parte (ou pior, causando confusão ativamente), então deve ser eliminado, resumido ou mantido fora.</p><p>Como desenvolvedores, agora podemos programar o contexto da mesma forma que programamos o código, decidindo quais informações incluir, como formatá-las e quando omiti-las ou atualizá-las. Seguindo essas práticas, podemos fornecer aos agentes LLM o contexto necessário para executar tarefas sem incorrer nas falhas descritas anteriormente. O resultado são agentes que lembram do que deveriam, esquecem o que não precisam e recuperam o que precisam a tempo.</p><h2>Conclusão</h2><p>Memória não é algo que você adiciona a um agente; é algo que você projeta. A memória de curto prazo é o bloco de trabalho do agente, e a memória de longo prazo é seu armazenamento de conhecimento duradouro. O RAG serve de ponte entre os dois, transformando um armazenamento de dados passivo, como o Elasticsearch, em um mecanismo de recuperação ativo que pode ancorar as saídas e manter o agente atualizado.</p><p>Mas a memória é uma faca de dois gumes. No momento em que você deixa o contexto crescer sem controle, você gera envenenamento, distração, confusão e conflitos e, em sistemas compartilhados, até mesmo vazamento de dados. Por isso, o trabalho mais importante com a memória não é "armazenar mais", mas sim "selecionar melhor": recuperar seletivamente, eliminar agressivamente, resumir cuidadosamente e evitar misturar contextos não relacionados, a menos que a tarefa realmente o exija.</p><p>Na prática, uma boa engenharia de contexto se assemelha a um bom projeto de sistemas: contextos menores e suficientes, interfaces controladas entre os componentes e uma clara separação entre o estado bruto e o estado refinado que você realmente deseja que o modelo veja. Se feito corretamente, você não acaba com um agente que lembra de tudo — você acaba com um agente que lembra das coisas certas, na hora certa, pelo motivo certo.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agentic-memory-management-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agentic-memory-management-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Someshwaran Mohankumar]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3bad6b045392e641/6a170f43a29299c189d010cc/80907fd072e72d6ec902470b449c9f337957a0d7-1280x720.png" length="0" type="image/png"/>
    <pubDate>Fri, 16 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Introdução ao Elastic Agent Builder e Strands Agents SDK]]></title>
    <description><![CDATA[Aprenda a criar um agente com o Elastic Agent Builder e explore como usar o agente via protocolo A2A orquestrado com o Strands Agents SDK.]]></description>
    <content:encoded><![CDATA[<p>Você tem uma ideia para um agente de IA? Provavelmente isso envolve fazer algo com os dados, porque se um agente for iniciar uma ação útil, ele precisa tomar uma decisão e precisa dos dados certos para tomar a decisão certa.</p><p>O Elastic Agent Builder facilita a criação de agentes de IA conectados a dados. Mostraremos como fazer isso neste post do blog. Vamos passar por todos os passos necessários para criar um agente com uma ferramenta MCP que acesse os dados armazenados no Elastic. Depois, usaremos o Strands Agents SDK e os recursos Agent2Agent (A2A) para operar o agente. O <a href="https://strandsagents.com/">Strands Agents SDK</a> é uma plataforma de desenvolvimento de IA multiagente que você pode usar para criar apps agentes com código suficiente para garantir o resultado desejado.</p><p>Vamos construir um agente de IA que jogue RPS+, uma versão do clássico jogo Pedra, Papel e Tesoura com um diferencial: oferece aos jogadores algumas opções extras.</p><h2>Pré-requisitos</h2><p>Aqui está o que é necessário para seguir as etapas deste post do blog:</p><ul><li><p>Um editor de texto rodando no seu computador local</p><ul><li><p><a href="https://code.visualstudio.com/download">Visual Studio Code</a> é o que usaremos para as instruções de exemplo neste post do blog</p></li></ul></li><li><p><a href="https://www.python.org/downloads/">Python 3.10 ou superior</a> rodando no seu computador local</p></li></ul><h2>Crie um projeto serverless</h2><p>A primeira coisa de que precisamos é de um projeto Elasticsearch Serverless, que inclua o Elastic Agent Builder.</p><p>Acesse <a href="http://cloud.elastic.co/">cloud.elastic.co</a> e crie um novo projeto Elasticsearch Serverless.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3472edce39ec0b81/6a17060e66c4f93c17f8bf57/31b6a5c1c30dacbb4d5e58d1c566071e7143a0c8-1600x879.gif" alt="" /><h2>Crie um índice e adicione dados</h2><p>Em seguida, adicionaremos alguns dados ao nosso projeto Elasticsearch. Abra as Ferramentas de desenvolvedor, onde podemos executar comandos para criar um novo índice e inserir alguns dados. Selecione Ferramentas de desenvolvedor no menu de navegação de nível superior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaedaa94068c07a17/6a17060f961e697558c4ce5f/f97d5af077504463155655a9e27c171a7f974f71-1600x879.jpg" alt="" /><p>Copie e cole o seguinte comando PUT na área de entrada de solicitações do console Ferramentas de desenvolvedor. Essa declaração cria um índice Elasticsearch chamado "game-docs".</p>PUT /game-docs
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "content": { 
        "type": "text"
      },
      "filename": { "type": "keyword" },
      "last_modified": { "type": "date" }
    }
  }
}<p>Clique no botão <strong>Enviar solicitação</strong> que aparece no lado direito da declaração em Ferramentas de desenvolvedor. Você deve ver uma notificação confirmando que o índice <em>game-docs</em> foi criado na área de resposta das Ferramentas de desenvolvedor.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt430c357b479d93af/6a170611a6c2b98191e79624/be0555a1930e4d4f58b7ed8b669c9b702532ed17-1600x880.jpg" alt="" /><p>Um índice chamado <em>game-docs</em> é um ótimo lugar para armazenar os dados do jogo que estamos criando. Vamos colocar um documento chamado <em>rps+-md</em> nesse índice que contém todos os dados que nosso jogo requer. Copie e cole o seguinte comando PUT no console Ferramentas de desenvolvedor.</p>PUT /game-docs/_doc/rps+-md
{
  "title": "Rock Paper Scissors +",
  "content": "
# Game Name
RPS+

# Starting Prompt
Let's play RPS+ !
---
What do you choose?

# Game Objects
1. Rock 🪨 👊
2. Paper 📜 🖐
3. Scissors ✄ ✌️
4. Light ☼ 👍
5. Dark Energy ☄ 🫱

# Judgement of Victory
* Rock beats Scissors
  * because rocks break scissors
* Paper beats Rock
  * because paper covers rock
* Scissors beat Paper
  * because scissors cut paper
* Rock beats Light
  * because you can build a rock structure to block out light
* Paper beats Light
  * because knowledge stored in files and paper books helps us understand light
* Light beats Dark Energy
  * because light enables humans to lighten up and laugh in the face of dark energy as it causes the eventual heat death of the universe
* Light beats Scissors
  * because light is needed to use scissors safely
* Dark Energy beats Rock
  * because dark energy rocks more than rocks. It rocks rocks and everything else in its expansion of the universe
* Dark Energy beats Paper
  * because humans, with their knowledge stored in files and paper books, can't explain dark energy 
* Scissors beat Dark Energy
  * because a human running with scissors is darker than dark energy

# Invalid Input
I was hoping for an worthy opponent
  - but alas it appears that time has past
  - but alas there's little time for your todo list when [todo:fix this] is so vast

# Cancel Game
The future belongs to the bold. Goodbye..
",
  "filename": "RPS+.md",
  "last_modified": "2025-11-25T12:00:00Z"
}<p>Clique no botão <strong>Enviar solicitação</strong> ao lado da declaração para executá-la e adicionar o documento <em>rps+-md</em> ao índice game-docs.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt64d49e13754d5b25/6a17061214b270524be3c55d/3c01d8a4602de5c33337457591a388a4a4e3fad3-1600x879.jpg" alt="" /><p>Agora devemos ter alguns dados para consultar e, com o Agent Builder, isso está mais simples do que nunca.</p><p>Selecione <strong>Agentes</strong> no menu de navegação principal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb4d374bf2ba9135c/6a1706147d8d67468570e63e/82dbd2e9a439cabd5a5eea3d0ce005b87df0c3ea-1600x879.jpg" alt="" /><p>Agora, é preciso perguntar ao Elastic AI Agent padrão: "Quais dados eu tenho?"</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc0f879cf28772718/6a1706161949f7f25ee7a92d/f7a2f39c9d1486bdf02d9e88a732b540ac2e2cd1-1600x872.gif" alt="" /><p>O Elastic AI Agent avalia os dados e retorna uma explicação concisa sobre os dados que possuímos.</p><h2>Crie uma ferramenta</h2><p>Ok, agora temos alguns dados no Elastic, vamos utilizá-los. O Agent Builder inclui suporte integrado para criar ferramentas <a href="https://modelcontextprotocol.io/">MCP</a> que ajudam os agentes a acessar os dados necessários para ter o contexto correto para a tarefa. Vamos criar uma ferramenta simples que recupere os dados do nosso jogo.</p><p>Clique no menu de ações do Agent Builder.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7802a6b94e81440c/6a170618ab7f085287db9db4/0e327c202674dda33bcc0e494d2b588fa8b32e4f-1600x879.png" alt="" /><p>Selecione <strong>Ver todas as ferramentas </strong>nas opções do menu.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9f52ffe114fb6ea7/6a17061a4a531b801b36a884/1ebf58650e9fb56750d3f0b1700fab50b44f9bdf-1600x879.png" alt="" /><p>Clique <strong>+ Nova Ferramenta.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8090769f6c4d1899/6a17061c286714294093e219/6c03a7f28b99ac2d805f34f39948979893316a00-1600x879.png" alt="" /><p>No formulário <strong>Criar Ferramenta</strong>, selecione <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql"><strong>ES|QL.</strong></a>Selecione a ferramenta <strong>Tipo</strong> e insira os valores a seguir.</p><p>Para o <strong>ID da Ferramenta</strong>:</p>example.get_game_docs<p>Para <strong>Descrição</strong>:</p>Get RPS+ doc from Elasticsearch game-docs index.<p>Para <strong>Configuração, </strong>insira a seguinte consulta na área de texto <strong>Mecanismo de consulta ES|QL: </strong></p>FROM game-docs | WHERE filename == "RPS+.md"<p>O formulário <strong>Criar ferramenta</strong> que você preencheu deve ter esta aparência: Clique em <strong>Salvar</strong> para criar a ferramenta.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt77034c305198217a/6a17061e66c4f9e54ef8bf5e/b6c93e344600f319b9d2c3030020cf2d171ac1c4-1600x1312.png" alt="" /><p>Temos uma ferramenta nova no suporte de ferramentas. As ferramentas não devem ficar num suporte; elas devem ser usadas. Vamos criar um agente que possa usar nossa nova ferramenta personalizada.</p><h2>Crie um agente e atribua uma ferramenta a ele.</h2><p>Criar um agente é muito simples com o Agent Builder. Você só precisa digitar as instruções do agente com alguns detalhes. Vamos criar um agente agora.</p><p>Clique no botão <strong>Gerenciar agentes.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaa8a83fc2f3758a9/6a1706201949f71a10e7a931/53934b93db07187e251d4b321cb9ca647e2fd51b-1600x858.png" alt="" /><p>Clique<strong> + Novo agente.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3778403c5101a000/6a17062160084be12f3c449e/fae3ad8f31e71a6dfd044e1daa025a4e280b4e68-1600x490.png" alt="" /><p>Insira as informações a seguir no formulário <strong>Novo Agente</strong>.</p><p>Para o <strong>ID do Agente, </strong>insira o texto abaixo:</p>rps_plus_agent<p>Na área de texto de <strong>Instruções personalizadas, </strong>insira as seguintes instruções:</p>When prompted, if the prompt contains an integer, then select the corresponding numbered item in the list of "Game Objects" from your documents. Otherwise select a random game object. This is your chosen game object for a single round of the game.

# General Game Rules
* 2 players
    - the user: the person playing the game
    - you: the agent playing the game and serving as the game master
* Each player chooses a game object which will be compared and cause them to tie, win or lose.

# Start the game
1. This is the way each new game always starts. You make the first line of your response only the name of your chosen game object. 

2. The remainder of your response should be the "Starting Prompt" text from your documents and generate a list of "Game Objects" for the person playing the game to choose a game object from.  

# End of Game: The game ends in one of the following three outcomes:
1. Invalid Input: If the player responds with an invalid game object choice, respond with variations of the "Invalid Input" text from your documents and then end the game.

2. Tie: The game ends in a tie if the user chooses the same game object as your game object choice.

3. Win or Lose: The game winner is decided based on the "Judgement of Victory" conditions from your documents. Compare the user's game object choice and your game object choice and determine who chose the winning game object.

# Game conclusion
Respond with a declaration of the winner of the game by outputting the corresponding text in the "Judgement of Victory" section of your documents.<p>Para o <strong>Nome de exibição, </strong>insira o texto abaixo:</p>RPS+ Agent<p>Para a <strong>Descrição de exibição, </strong>insira o texto abaixo:</p>An agent that plays the game RPS+<p>Dê ao agente a ferramenta personalizada que criamos anteriormente, clicando na guia <strong>Ferramentas</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5b0fe00abdde07c/6a17062314b2704bc4e3c563/1778f64bc3a1b4004998dc3668ef7f666788e193-1600x1390.png" alt="" /><p>Selecione somente a ferramenta <em>example.get_game_docs</em> que criamos anteriormente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2210212e07e06104/6a170625a929cf3277ae08d1/7d734cd80161bcc058817482eb330ffcf1cb567b-1600x1363.png" alt="" /><p>Clique em <strong>Salvar</strong> para criar o novo agente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6e3afc1918e26f14/6a170627ab7f084746db9db8/c0014faf605ce50c03679ed0d073bd9f3ae7234d-1600x468.png" alt="" /><p>Vamos testar nosso novo agente. Há um link prático para iniciar um bate-papo com qualquer agente da lista de agentes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blteb4b69dc5971d3a0/6a1706286f7f046840914743/b7d6943ad90a4f68691207caf66b81742e712145-1600x560.png" alt="" /><p>Basta digitar “iniciar jogo” e o jogo começará. Funciona!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5b621d602223dff/6a17062ab339d568a1769ef8/984d008e4cc3f08cc1f101720673b0f7347c066c-1600x874.gif" alt="" /><p>O agente exibe a escolha de objeto de jogo na parte superior da resposta. Isso é útil porque podemos ver a escolha do agente e confirmar que o jogo está funcionando conforme o esperado. No entanto, saber a escolha do oponente antes de escolher não torna o jogo de Pedra, Papel e Tesoura muito divertido. Para aperfeiçoar e aprimorar o jogo até a forma final, podemos usar uma plataforma de orquestração de agentes que pode controlar agentes com código.</p><p>Agora é a hora do Strands Agents SDK.</p><h2>Strands Agents SDK</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73901ec745a97fbf/6a17062c964cea23c808bab3/c195bba6ff2754f5d8fda174a0c1d247bc283710-456x156.png" alt="" /><p>Se você tem curiosidade em experimentar novas estruturas de desenvolvimento de agentes, então vale a pena dar uma chance ao <a href="https://strandsagents.com/latest/">Strands Agents SDK</a>. O <a href="https://aws.amazon.com/blogs/opensource/introducing-strands-agents-an-open-source-ai-agents-sdk/">Strands Agents SDK foi lançado pela AWS (maio de 2025)</a> como uma implementação open source <a href="https://github.com/strands-agents/sdk-python">em Python</a>, e agora também existe uma versão <a href="https://dev.to/aws/strands-agents-now-speaks-typescript-a-side-by-side-guide-12b3">em Typescript</a>.</p><h2>Começando com o Strands Agents SDK em Python</h2><p>Preparem seus motores de programação, pois agora vamos percorrer o processo de clonagem e execução de um aplicativo de exemplo que usa Strands Agents para controlar o <em>agente RPS+</em> por meio do protocolo A2A. Vamos criar uma versão aperfeiçoada do jogo RPS+ para que a escolha do agente seja revelada depois que você fizer a sua escolha, pois, afinal, é a adivinhação e o resultado surpreendente que tornam divertidos jogos como o Pedra, Papel e Tesoura.</p><p>No seu computador local, abra o <a href="https://code.visualstudio.com/download">Visual Studio Code</a> e abra um novo terminal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3de752025d62993f/6a17062d0c4857f16501a997/2339cc37c89a3524f2b2a21684bc61dae958e1cf-915x460.jpg" alt="" /><p>No terminal recém-aberto, execute o seguinte comando para clonar o repositório Elasticsearch Labs:</p>git clone https://github.com/elastic/elasticsearch-labs<p>Execute o seguinte <em>cd </em>comando para alterar o diretório para o diretório elasticsearch-labs:</p>cd elasticsearch-labs<p>Em seguida, execute o seguinte comando para abrir o repositório no Visual Studio Code:</p>code .<p>No Visual Studio File Explorer, expanda as pastas <em>contenting-blog-content</em> e <em>agent-builder-a2a-strands-agents</em> e abra o arquivo <em>elastic_agent_builder_a2a_rps+.py.</em> Veja a aparência do arquivo aberto no Visual Studio Code:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt65ef8036a70bcaf1/6a17062f1949f7af36e7a935/d153b19e0e016c701576edb99ccab5af7c554f34-1484x1530.jpg" alt="" /><p>Aqui está o conteúdo de <em>elastic_agent_builder_a2a_rps+.py </em>que você deve ver no seu editor de texto:</p>import asyncio
from dotenv import load_dotenv
from uuid import uuid4
import httpx
import os
import random
from a2a.client import A2ACardResolver, ClientConfig, ClientFactory
from a2a.types import Message, Part, Role, TextPart

DEFAULT_TIMEOUT = 60  # set request timeout to 1 minute


def create_message(*, role: Role = Role.user, text: str, context_id=None) -&gt; Message:
    return Message(
        kind="message",
        role="user",
        parts=[Part(TextPart(kind="text", text=text))],
        message_id=uuid4().hex,
        context_id=context_id,
    )


async def main():
    load_dotenv()
    a2a_agent_host = os.getenv("ES_AGENT_URL")
    a2a_agent_key = os.getenv("ES_API_KEY")
    custom_headers = {"Authorization": f"ApiKey {a2a_agent_key}"}

    async with httpx.AsyncClient(
        timeout=DEFAULT_TIMEOUT, headers=custom_headers
    ) as httpx_client:
        # Get agent card
        resolver = A2ACardResolver(httpx_client=httpx_client, base_url=a2a_agent_host)
        agent_card = await resolver.get_agent_card(
            relative_card_path="/rps_plus_agent.json"
        )
        # Create client using factory
        config = ClientConfig(
            httpx_client=httpx_client,
            streaming=True,
        )
        factory = ClientFactory(config)
        client = factory.create(agent_card)
        # Use the client to communicate with the agent
        print("\nSending 'start game' message to Elastic A2A agent...")
        random_game_object = random.randint(1, 5)
        msg = create_message(text=f"start with game object {random_game_object}")
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                context_id = event.context_id
                response_complete = event.parts[0].root.text
                # Get agent choice from the first line of the response
                parsed_response = response_complete.split("\n", 1)
                agent_choice = parsed_response[0]
                print(parsed_response[1])
        # User choice sent for game results from the agent
        prompt = input("Your Choice  : ")
        msg = create_message(text=prompt, context_id=context_id)
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                print(f"Agent Choice : {agent_choice}")
                print(event.parts[0].root.text)


if __name__ == "__main__":
    asyncio.run(main())<p>Vamos revisar o que está acontecendo nesse código. Começando pelo método <em><code>main()</code></em>, o código começa acessando as variáveis de ambiente para a URL do agente e a Chave da API. Depois, usamos esses valores para criar um <em><code>httpx</code></em><code> client</code> que podemos usar para obter o cartão de agente para o agente. O cliente então usa os detalhes do cartão do agente para enviar uma solicitação "iniciar jogo" ao agente. Uma coisa interessante a notar aqui é que incluímos um valor <code>random_game_object</code> como parte do pedido <code>"start game"</code>. Esse valor é um número aleatório gerado com o módulo <em>aleatório</em> da biblioteca padrão do Python. A razão para fazer isso é que os poderosos LLMs (que possibilitam agentes de IA) não são bons em aleatoriedade. Não tema, Python vem pra salvar.</p><p>Continuando com o código, quando o agente responde à solicitação "iniciar jogo", o código remove a seleção de objeto de jogo do agente e a salva na variável <em>agent_choice</em>. O restante da resposta é exibido como texto para o usuário final. Em seguida, o usuário é solicitado a fornecer a entrada da sua escolha de objeto de jogo, que é enviada ao agente. O código então exibe a escolha do objeto de jogo do agente junto com a determinação final do agente sobre o resultado do jogo.</p><h2>Definindo a URL do seu agente e a chave de API como variáveis de ambiente</h2><p>Como o app de exemplo estará rodando no seu computador local, para nos comunicarmos com nosso agente Agent Builder, precisamos fornecer ao Strands Agents SDK uma URL A2A e uma chave API para o agente. O exemplo de app usa um arquivo chamado <em>.env</em> para armazenar esses valores.</p><p>Faça uma cópia do <em>arquivo env.example</em> e nomeie o novo arquivo como <em>.env</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta17961cbcb42985c/6a170631b0367dc5a072bc55/25ead5f15a17dedb777132a082097cffb06cae4d-1600x843.jpg" alt="" /><p>Volte para o Elastic Agent Builder, onde podemos obter os dois valores que precisamos.</p><p>Selecione <strong>Exibir todas as ferramentas</strong> no menu de ação do Agent Builder no canto superior direito da página.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt140885d7ebfcb969/6a1706327d8d67b17670e646/9c4f4e4a3bd76e11e0a182fa007a2f6aec7777b4-1600x880.jpg" alt="" /><p>Clique no menu suspenso <strong>Servidor MCP</strong> na parte superior da página Ferramentas e selecione <strong>Copiar URL do Servidor MCP.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc153c2caa27e949b/6a170634a292997793d00f6d/6cde0de678bb6f81bef8a59deffb110ad6c6ce26-1600x882.jpg" alt="" /><p>Cole o <strong>URL do servidor MCP</strong> no arquivo <em>.env</em> como um substituto para o valor do espaço reservado <strong>&lt;YOUR-ELASTIC-AGENT-BUILDER-URL&gt; </strong>. Agora precisamos fazer uma atualização no URL, ou seja, substituir o texto final “mcp” por “a2a”, pois o <a href="https://a2a-protocol.org/">protocolo A2A</a> é o que o Agent Strands SDK usará para se comunicar com o agente em execução no Elastic Agent Builder.</p><p>A URL editada deve ficar assim:</p>https://rps-game-project-12345a.kb.us-east-1.aws.elastic.cloud/api/agent_builder/a2a<p>Outro valor que precisamos obter enquanto estamos aqui no Elastic Cloud é uma chave API. Clique em <strong>Elasticsearch </strong>na navegação de nível superior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltada5de819f31d8ff/6a170635b339d55ae9769efc/651676b9be65178cdad50b5d24f26441c0bf3f97-1600x549.jpg" alt="" /><p>Clique no <strong>botão Copiar chave API </strong>para copiar a chave API.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta18f85790df00706/6a170637cf4f257145b2d0bd/17f1e2ed5c7682630c71e75b0b09ffb1d9036210-1600x879.jpg" alt="" /><p>Agora, de volta ao Visual Studio Code, cole a chave API no <em>.env</em> para substituir o texto provisório <strong>&lt;YOUR-ELASTIC-API-KEY&gt; </strong>. Seu arquivo <em>.env</em> deve ficar assim:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92ab4b37cdcca85e/6a1706386f7f0472ed914747/a357947e07f29c8c03382e00c7baedf04a399297-1600x286.jpg" alt="" /><h2>Execute o app de exemplo</h2><p>Abra um novo terminal no Visual Studio Code.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8702d826849755d0/6a17063a60084b45ca3c44a2/33e1174c68ea1ed47c7fe62ab6a6da657c606f56-1413x711.jpg" alt="" /><p>Comece executando o seguinte comando <em>cd</em> no terminal:</p>cd elasticsearch-labs/supporting-blog-content/agent-builder-a2a-strands-agents<p>Execute o seguinte comando para criar um ambiente virtual Python.</p>python -m venv .venv<p>Dependendo do sistema operacional do seu computador local, execute o seguinte comando para ativar o ambiente virtual.</p><ul><li><p>MacOS/Linux</p></li></ul>source .venv/bin/activate<ul><li><p>Windows</p></li></ul>.venv\Scripts\activate<p>O app de exemplo usa o Strands Agents SDK e agora estamos no ponto em que precisamos instalá-lo. Execute o seguinte comando para instalar o Strands Agents SDK junto com todas as dependências necessárias da biblioteca Python.</p>pip install -r requirements.txt<p>Hora de liberar a plataforma de lançamento e começar a contagem regressiva. Estamos prontos para executar este app. Afastem-se. Vamos executá-lo usando o seguinte comando:</p>python elastic_agent_builder_a2a_rps+.py<p>Você deve ser desafiado com uma partida de RPS+. Parabéns e boa sorte!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbb3715672995fcfa/6a17063c6234e07b76db195f/041df81fbf1776f09e1243af0a435c4c0af6aca1-1600x948.gif" alt="" /><h2>Crie seus aplicativos de IA com contexto relevante</h2><p>Construir um Agente de IA agora é uma habilidade disponível na sua caixa de ferramentas. E você já viu como é fácil usar agentes Elastic Agent Builder via A2A em frameworks de desenvolvimento de agentes como o Strands Agents SDK. <a href="https://cloud.elastic.co/registration?utm_source=agentic-ai-category&amp;utm_medium=search-labs&amp;utm_campaign=agent-builder">Experimente a Elastic</a> para criar agentes de IA conectados ao contexto relevante em seus dados personalizados.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-a2a-strands-agents-guide</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-a2a-strands-agents-guide</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Jonathan Simon]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3472edce39ec0b81/6a17060e66c4f93c17f8bf57/31b6a5c1c30dacbb4d5e58d1c566071e7143a0c8-1600x879.gif" length="0" type="image/gif"/>
    <pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Introdução do suporte ao Elasticsearch no Google MCP Toolbox for Databases]]></title>
    <description><![CDATA[Veja como o suporte ao Elasticsearch agora está disponível no Google MCP Toolbox for Databases e adote as ferramentas ES|QL para integrar seu índice com segurança a qualquer cliente MCP.]]></description>
    <content:encoded><![CDATA[<p>Neste artigo, vamos explicar como usar o Google MCP Toolbox com o <a href="https://github.com/elastic/elasticsearch">Elasticsearch</a> para construir uma ferramenta simples de extração de informações de um índice do Elasticsearch.</p><p>Recentemente, contribuímos para o projeto open source <a href="https://github.com/googleapis/genai-toolbox">Google MCP Toolbox for Databases</a>, adicionando suporte ao Elasticsearch como banco de dados.</p><p>Com esse novo recurso, agora você pode usar o Google MCP Toolbox para se conectar ao Elasticsearch e "conversar" diretamente com seus dados.</p><h2>Elasticsearch</h2><p>Precisamos ter uma instância do Elasticsearch em execução. Você pode ativar uma avaliação gratuita no <a href="https://www.elastic.co/cloud">Elastic Cloud</a> ou instalá-lo localmente usando o <a href="https://github.com/elastic/start-local">script start-local</a>:</p>curl -fsSL https://elastic.co/start-local | sh<p>Isso instalará o Elasticsearch e o Kibana no seu computador e gerará uma chave API para ser usada na configuração do Google MCP Toolbox.</p><p>A chave API será mostrada como saída do comando anterior e armazenada em um arquivo .env na pasta elastic-start-local.</p><h2>Instale o conjunto de dados de exemplo</h2><p>Após a instalação, você pode fazer login no Kibana usando o nome do usuário <em>elastic</em> e a senha gerada pelo script start-local (armazenada em um arquivo .env).</p><p>Você pode instalar o conjunto de dados de <strong>pedidos de comércio eletrônico </strong>disponível no Kibana. Inclui um único índice chamado <strong>kibana_sample_data_ecommerce</strong> contendo informações sobre 4.675 pedidos de um website de comércio eletrônico. Para cada pedido, temos as seguintes informações:</p><ul><li><p>Informações do cliente (nome, ID, data de nascimento, e-mail, etc.)</p></li><li><p>Data do pedido</p></li><li><p>ID do pedido</p></li><li><p>Produtos (lista de todos os produtos com preço, quantidade, ID, categoria, desconto, etc.)</p></li><li><p>SKU</p></li><li><p>Preço total (sem impostos, com impostos)</p></li><li><p>Quantidade total</p></li><li><p>Informações geográficas (cidade, país, continente, localização, região)</p></li></ul><p>Para instalar os dados de exemplo, abra a página <strong>Integrações</strong> no Kibana (busque por “Integração” na barra de busca superior) e instale os “Dados de Exemplo”. Confira os detalhes na documentação aqui: <a href="https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana">https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana</a>.</p><p>O objetivo deste artigo é mostrar como é fácil configurar o Google MCP Toolbox para se conectar ao Elasticsearch e interagir com o <strong>índice kibana_sample_data_ecommerce</strong> usando linguagem natural.</p><h2>Google MCP Toolbox</h2><p>O Google MCP Toolbox é um servidor MCP open source projetado para facilitar a interação de aplicações e agentes de IA com bancos de dados de forma segura e eficiente. Antes chamado de "GenAI Toolbox for Databases", o projeto foi renomeado após adotar total compatibilidade com o <a href="https://www.anthropic.com/news/model-context-protocol">Protocolo de Contexto de Modelo</a> (MCP). Seu objetivo é eliminar o trabalho pesado tradicionalmente exigido ao conectar agentes a bancos de dados, lidando com agrupamento de conexões, autenticação, observabilidade e outras preocupações operacionais nos bastidores.</p><p>Essencialmente, o Toolbox permite que desenvolvedores definam ferramentas reutilizáveis e de alto nível que encapsulam interações com bancos de dados. Essas ferramentas podem então ser invocadas por qualquer cliente que cumpra o MCP — como um agente de IA — sem exigir que o cliente implemente consultas SQL de baixo nível ou gerencie conexões de banco de dados. Essa abordagem reduz drasticamente a quantidade de código padrão necessário para construir agentes conscientes de banco de dados, tornando possível integrar operações avançadas de dados em apenas algumas linhas de lógica de aplicação. Uma vez definida uma ferramenta, ela pode ser compartilhada entre vários agentes, frameworks ou linguagens (Figura 1).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte90070297ee83546/6a16fa29964cea694b08b972/137cea290bb70ad5da21853f9a6358cef4cf7451-1248x1056.png" alt="" /><p>Uma grande vantagem de usar o Toolbox é o modelo de segurança integrado. Fluxos de autenticação, como OAuth2 e OIDC, são aceitos de forma nativa, permitindo que os desenvolvedores evitem manipular ou armazenar credenciais confidenciais de bancos de dados em agentes. A plataforma também fornece recursos de observabilidade, incluindo métricas e rastreamento, no OpenTelemetry, que é essencial para depuração, monitoramento e implantações de produção. No geral, o MCP Toolbox serve como uma interface unificada, segura e extensível para interagir com seus dados de qualquer sistema habilitado pelo MCP.</p><h2>Como instalar o MCP Toolbox</h2><p>Você pode instalar o servidor MCP Toolbox no Linux usando o seguinte comando:</p>export VERSION=0.21.0
curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox<p>Para instalá-lo no macOS ou Windows, siga as instruções detalhadas <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/#installing-the-server">aqui</a>.</p><h2>Configure o Toolbox para Elasticsearch</h2><p>Para configurar o MCP Toolbox para Elasticsearch, precisamos criar um arquivo <strong>tools.yaml</strong> , conforme segue:</p>sources:
  my-cluster:
    kind: elasticsearch
    addresses:
      - http://localhost:9200
    apikey: &lt;insert-here-api-key&gt;

tools:
  customer-orders:
    kind: elasticsearch-esql
    source: my-cluster
    description: Get the orders made by a customer identified by name.
    query: |
    	FROM kibana_sample_data_ecommerce | WHERE MATCH(customer_full_name, ?name, {"operator": "AND"})
    parameters:
      - name: name
        type: string
        description: The customer name.

toolsets:
  elasticsearch-tools:
    - customer-orders<p>Você precisa trocar o valor <strong>&lt;insert-here-api-key&gt;</strong> por uma chave API válida do Elasticsearch. Se você estiver rodando o Elasticsearch localmente usando o start-local, pode encontrar a chave API no arquivo .env gerado pelo start-local, sob a variável <strong>ES_LOCAL_API_KEY</strong> . Se você estiver usando o Elastic Cloud, poderá gerar uma chave de API seguindo o procedimento descrito <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys">aqui</a>.</p><p>As ferramentas anteriores contêm a seguinte consulta ES|QL para Elasticsearch:</p><p>Se você não conhece o ES|QL, é uma linguagem de consulta desenvolvida pela Elastic, semelhante ao SQL, que pode ser usada para buscar em um ou mais índices. Saiba mais sobre ES|QL na documentação oficial <a href="https://www.elastic.co/docs/reference/query-languages/esql">aqui</a>.</p><p>A consulta acima busca todos os pedidos armazenados no <strong>índice kibana_sample_data_ecommerce</strong> que contêm o nome do cliente especificado, usando o parâmetro <strong>?name</strong> (o ponto de interrogação indica um parâmetro).</p><p>O nome do cliente é definido na configuração YAML anterior usando a string de tipo e a descrição "O nome do cliente".</p><p>Essa ferramenta pode ser usada para responder a perguntas sobre os pedidos de um cliente - por exemplo: <em>Quantos pedidos o cliente Foo fez em outubro de 2025?</em></p><p>As descrições das ferramentas e seus parâmetros são essenciais para extrair as informações relevantes da solicitação em linguagem natural do usuário. Essa extração é realizada usando o recurso de <strong>chamada de função</strong> de um modelo de linguagem grande (LLM). Na prática, um LLM pode determinar qual função (ferramenta) precisa ser executada para obter as informações necessárias, juntamente com os parâmetros apropriados para essa função.</p><p>Para saber mais sobre chamadas de função, sugerimos o artigo <a href="https://www.elastic.co/search-labs/blog/function-calling-with-elastic">Chamadas de função do OpenAI com Elasticsearch</a>, de Ashish Tiwari.</p><h2>Execute o servidor Toolbox</h2><p>Você pode executar o MCP Toolbox usando o arquivo tools.yaml anterior com o seguinte comando:</p>./toolbox --tools-file tools.yaml --ui<p>O parâmetro<strong> –ui</strong> executa uma aplicação web em <a href="http://127.0.0.1:5000/ui">http://127.0.0.1:5000/ui</a> (Figura 2).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0fb3953fae603572/6a16fa2aa6c2b92763e794fb/3caf2339b632bafd5847af1ed8b33b518a25b8a2-1600x314.png" alt="" /><p>Você pode selecionar <strong>Ferramentas</strong> &gt; <strong>customer-orders</strong> e inserir o nome do cliente no campo <strong>Nome</strong> do parâmetro (por exemplo, Gwen Sanders) e clicar no botão <strong>Executar</strong>. Você deve ver uma resposta JSON conforme a Figura 3.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltca02df8c78cb39ff/6a16fa2c961e6909b5c4cd22/b167e0142afb8919d9cedf6d0fa431d33d0e55f8-1600x933.png" alt="" /><p>A configuração está concluída, e o MCP Toolbox pode executar a ferramenta <strong>customer-orders</strong> para se comunicar com o Elasticsearch, rodando o ES|QL.</p><h2>Usando o MCP Toolbox com Gemini CLI</h2><p>Podemos usar qualquer cliente MCP para nos comunicar com o MCP Toolbox for Databases. Por exemplo, podemos usar o <a href="https://github.com/google-gemini/gemini-cli">Gemini CLI</a>, uma ferramenta de linha de comando, para usar o Gemini. Você pode instalar o Gemini CLI seguindo as instruções descritas <a href="https://geminicli.com/docs/get-started/installation/">aqui</a>.</p><p>Gemini CLI oferece uma extensão pré-configurada para MCP Toolbox, disponível em <a href="https://github.com/gemini-cli-extensions/mcp-toolbox">gemini-cli-extensions/mcp-toolbox</a>. Você pode instalar esta extensão executando o seguinte comando:</p>gemini extensions install https://github.com/gemini-cli-extensions/mcp-toolbox<p>Após a instalação, você precisa ir para o diretório em que armazenou o arquivo de configuração tools.yaml do MCP Toolbox e executar a CLI do Gemini da seguinte forma (essa etapa é necessária para que a CLI do Gemini seja configurada automaticamente com o MCP Toolbox):</p>gemini<p>Você deve ver uma saída conforme a Figura 4.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf7245c10b9e32cd6/6a16fa2d964cea073208b976/0f22df6d3da13c1dc50dcb560414fa7c630eb9a7-1434x341.png" alt="" /><p>Você pode verificar se a MCP Toolbox está conectada usando o seguinte comando:</p>/mcp list<p>Você deve ver a <strong>mcp_toolbox</strong> com as ferramentas<strong> de pedidos de clientes</strong> listadas (Figura 5).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte857b42dbe604203/6a16fa2f8b73cb531b189e33/97edbc40de9e44f469f6f3a09427532be167de0e-493x155.png" alt="" /><p>Se o MCP Toolbox estiver conectado à interface de comando Gemini, agora podemos tentar fazer algumas perguntas, como: "<em>Me dê os pedidos da cliente Gwen Sanders</em>." A CLI Gemini então solicitará permissão para executar a ferramenta de pedidos do cliente ao servidor mcp_toolbox (veja a Figura 6).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb7ea752c1a39da7/6a16fa30cdacbfdf937d27ff/c052f3b5e49436903b804280c0065f67ee02444b-1432x284.png" alt="" /><p>Após a confirmação, a CLI Gemini executará a solicitação para a MCP Toolbox, recebendo uma resposta JSON como resultado e usando para formatar a resposta (Figura 7).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb9f6e04987137a9f/6a16fa320811ae2297e9fef7/7ea5128f1705951c2757af6da4b456d394d4a080-1432x734.png" alt="" /><p>A resposta da Gemini CLI emitirá um relatório indicando que Gewn Sanders fez apenas um pedido de 2 produtos, totalizando 132 euros.</p><h2>SDKs do MCP Toolbox</h2><p>O Google MCP Toolbox também oferece um SDK para acessar todas as funcionalidades de um programa escrito em Go, Python e Javascript.</p><p>Por exemplo, o Python SDK está disponível no Github na seguinte página: <a href="https://github.com/googleapis/mcp-toolbox-sdk-python">https://github.com/googleapis/mcp-toolbox-sdk-python.</a></p><p>Precisamos criar um agente simples para conectar à MCP Toolbox. Precisamos instalar os seguintes pacotes:</p>pip install toolbox-core
pip install google-adk<p>E crie um novo projeto de agente usando o comando a seguir:</p>adk create my_agent<p>Isso criará um novo diretório chamado <strong>my_agent</strong> com um <strong>arquivo agent.py</strong>.</p><p>Atualize <strong>my_agent/agent.py</strong> com o seguinte conteúdo para conectar ao Toolbox:</p>from google.adk import Agent
from google.adk.apps import App
from toolbox_core import ToolboxSyncClient

client = ToolboxSyncClient("http://127.0.0.1:5000")

root_agent = Agent(
    name='root_agent',
    model='gemini-2.5-flash',
    instruction="You are a helpful AI assistant designed to search information about a dataset of ecommerce orders.",
    tools=client.load_toolset(),
)

app = App(root_agent=root_agent, name="my_agent")<p>Crie um arquivo <strong>.env</strong> com sua chave API do Google:</p>echo 'GOOGLE_API_KEY="YOUR_API_KEY"' &gt; my_agent/.env<p>Por fim, podemos executar o agente e observar os resultados. Para executar o agente, você pode executar o seguinte comando:</p>adk run my_agent<p>Ou pode servi-lo por meio de uma interface web:</p>adk web --port 8000<p>Em ambos os casos, você pode interagir com a MCP Toolbox usando uma interface de perguntas e respostas. Por exemplo, você pode fazer a pergunta anterior: <em>Me dê os pedidos da cliente Gwen Sanders</em>.</p><p>Para saber mais sobre os diferentes SDKs, consulte <a href="https://googleapis.github.io/genai-toolbox/sdks/">esta página de documentação</a>.</p><h2>Conclusão</h2><p>Neste artigo, demonstramos a integração com o Elasticsearch para o Google MCP Toolbox for Databases. Usando um arquivo de configuração YAML simples, podemos definir um conjunto de ferramentas que traduzem perguntas de linguagem natural em consultas do Elasticsearch usando a linguagem ES|QL.</p><p>Mostramos como interagir com os conjuntos de dados kibana_sample_data_ecommerce, que contém pedidos de um website de e-commerce. Com esse arquivo de configuração, basta executar o servidor MCP Toolbox e conectar a ele a partir de qualquer cliente MCP.</p><p>Por fim, demonstramos como usar o Gemini CLI como cliente para conectar-se ao MCP Toolbox for Databases e consultar os dados de comércio eletrônico armazenados no Elasticsearch. Executamos uma consulta em linguagem natural para obter informações sobre pedidos de um cliente específico identificado pelo nome.</p><p>À medida que o ecossistema MCP continua crescendo, esse padrão — definições leves de ferramentas apoiadas por uma infraestrutura segura e pronta para produção — gera novas oportunidades para criar agentes cada vez mais capazes e com reconhecimento de dados com o mínimo esforço. Seja experimentando localmente com os conjuntos de dados de amostra da Elastic ou integrando capacidades de buscar em uma aplicação maior, o MCP Toolbox tem uma base confiável e extensível para interagir com os dados do Elasticsearch usando linguagem natural.</p><p>Para saber mais sobre o desenvolvimento de aplicações de IA agêntica, leia o artigo <a href="https://search-labs-redesign.vercel.app/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Criando fluxos de trabalho de IA agêntica com Elasticsearch</a>, de Anish Mathur e Dana Juratoni.</p><p>Para saber mais informações sobre o Google MCP Toolbox, visite <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/">https://googleapis.github.io/genai-toolbox/getting-started/introduction/</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Enrico Zimuel,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt72d49893c51407cf/6a16fa33cf4f2502bab2cf7e/425a48691f436ed47c9bdfaf5d561ac122b2c472-1062x668.png" length="0" type="image/png"/>
    <pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Crie um fluxo de trabalho de busca por IA financeira usando LangGraph.js e Elasticsearch]]></title>
    <description><![CDATA[Aprenda a usar o LangGraph.js com o Elasticsearch para criar um fluxo de trabalho de busca financeira com IA que converte consultas em linguagem natural em filtros dinâmicos e condicionais para análise de investimentos e do mercado.]]></description>
    <content:encoded><![CDATA[<p>A criação de aplicativos de busca com IA geralmente envolve a coordenação de múltiplas tarefas, recuperação e extração de dados em um fluxo de trabalho integrado. O LangGraph simplifica esse processo ao permitir que os desenvolvedores orquestrem agentes de IA usando uma estrutura baseada em nós. Neste artigo, vamos construir uma solução financeira usando <a href="https://langchain-ai.github.io/langgraphjs/">LangGraph.js</a></p><h2>O que é LangGraph</h2><p><a href="https://langchain-ai.github.io/langgraphjs/">LangGraph</a> é um framework para construir agentes de IA e orquestrá-los em um fluxo de trabalho para criar aplicações assistidas por IA. O LangGraph possui uma arquitetura de nós onde podemos declarar funções que representam tarefas e atribuí-las como nós do fluxo de trabalho. O resultado de múltiplos nós interagindo será um gráfico. O LangGraph faz parte do ecossistema mais amplo <a href="https://js.langchain.com/docs/introduction/">LangChain</a>, que oferece ferramentas para construir sistemas de IA modulares e componíveis.</p><p>Para entender melhor por que o LangGraph é útil, vamos resolver uma situação problemática usando-o.</p><h2>Visão geral da solução</h2><p>Em uma empresa de capital de risco, os investidores têm acesso a um grande banco de dados com muitas opções de filtragem, mas quando se deseja combinar critérios, o processo se torna difícil e lento. Isso pode fazer com que algumas startups relevantes não sejam encontradas para investimento. Isso resulta em gastar muitas horas tentando identificar os melhores candidatos, ou até mesmo em perder oportunidades.</p><p>Com o LangGraph e o Elasticsearch, podemos realizar buscar filtradas utilizando linguagem natural, eliminando a necessidade de os usuários construírem manualmente solicitações complexas com dezenas de filtros. Para torná-lo mais flexível, o fluxo de trabalho decide automaticamente com base na entrada do usuário entre dois tipos de consultas:</p><ul><li><p><strong>Consultas focadas em investimento</strong>: essas consultas visam aspectos financeiros e de financiamento de startups, como <a href="https://www.investopedia.com/articles/personal-finance/102015/series-b-c-funding-what-it-all-means-and-how-it-works.asp">rodadas de financiamento</a>, avaliação ou <a href="https://www.investopedia.com/terms/r/revenue.asp">receita</a>. <em>Exemplo:</em> "Encontre startups com financiamento Série A ou Série B entre US$ 8 milhões e US$ 25 milhões e receita mensal acima de US$ 500 mil."</p></li><li><p><strong>Consultas focadas no mercado</strong>: essas consultas concentram-se em <a href="https://en.wikipedia.org/wiki/Vertical_market">verticais da indústria</a>, <a href="https://en.wikipedia.org/wiki/Target_market">mercados geográficos</a> ou <a href="https://www.investopedia.com/terms/b/businessmodel.asp">modelos de negócios</a>, ajudando a identificar oportunidades em setores ou regiões específicos. <em>Exemplo:</em> “Encontre startups de fintech e saúde em São Francisco, Nova York ou Boston.”</p></li></ul><p>Para manter a robustez das consultas, faremos com que o LLM crie <a href="https://www.elastic.co/docs/solutions/search/search-templates">modelos de busca</a> em vez de <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl">consultas DSL</a> completas. Assim, você sempre recebe a consulta que quer, e o LLM só precisa preencher as lacunas e não carregar a responsabilidade de construir a consulta que você precisa toda vez.</p><h2>O que você precisa para começar</h2><ul><li><p>APIKey do Elasticsearch</p></li><li><p>APIKey do OpenAPI</p></li><li><p>Node 18 ou mais recente</p></li></ul><h2>Instruções passo a passo</h2><p>Nesta seção, vamos ver como o app ficará. Para isso, usaremos o <a href="https://www.typescriptlang.org/">TypeScript</a>, um superconjunto do JavaScript que adiciona tipos estáticos para tornar o código mais confiável, fácil de manter e mais seguro, detectando erros precocemente e, ao mesmo tempo, permanecendo totalmente compatível com o JavaScript existente.</p><p>O fluxo dos nós terá a seguinte aparência:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt90db8f03f372608c/6a170986dc55de6e16e00d93/b47d7f238c4964a6febc0de7fe5e68b186f539c3-363x555.png" alt="" /><p>A imagem acima é gerada pelo LangGraph e representa o fluxo de trabalho que define a ordem de execução e a lógica condicional entre nós:</p><ul><li><p><strong>decideStrategy: </strong>utiliza um LLM para analisar a consulta do usuário e decidir entre duas estratégias de busca especializadas: focada em investimento ou focada no mercado.</p></li><li><p><strong>prepareInvestSearch: </strong>extrai valores de filtro da consulta e constrói um modelo pré-definido enfatizando parâmetros financeiros e relacionados ao financiamento.</p></li><li><p><strong>prepareMarketSearch</strong>: também extrai valores de filtro, mas constrói parâmetros dinamicamente enfatizando o mercado, o setor e o contexto geográfico.</p></li><li><p><strong>executeSearch: </strong>envia a consulta construída para o Elasticsearch usando um modelo de busca e recupera os documentos correspondentes de inicialização.</p></li><li><p><strong>visualizeResults: </strong>formata os resultados finais em um resumo claro e legível que mostra atributos-chave da startup, como financiamento, setor e receita.</p></li></ul><p>Esse fluxo inclui uma <a href="https://langchain-ai.github.io/langgraphjs/how-tos/branching/?h=conditional#how-to-create-branches-for-parallel-node-execution">ramificação condicional</a>, funcionando como uma instrução “if”, que determina se deve usar o caminho de busca de investimentos ou de mercado com base na entrada do usuário. Essa lógica de decisão, conduzida pelo LLM, torna o fluxo de trabalho adaptável e sensível ao contexto, um mecanismo que exploraremos com mais detalhes nas próximas seções.</p><h3>Estado do LangGraph</h3><p>Antes de ver cada nó individualmente, precisamos entender como os nós se comunicam e compartilham dados. Para isso, o LangGraph nos permite definir o estado do fluxo de trabalho. Isso define o estado compartilhado que será passado entre os nós.</p><p>O estado funciona como um container compartilhado que armazena dados intermediários ao longo do fluxo de trabalho: começa com a consulta em linguagem natural do usuário, depois mantém a estratégia de busca selecionada, os parâmetros preparados para o Elasticsearch, os resultados de busca recuperados e, finalmente, a saída formatada.</p><p>Essa estrutura permite que cada nó leia e atualize o estado, garantindo um fluxo consistente de informações desde a entrada do usuário até a visualização final.</p>const VCState = Annotation.Root({
  input: Annotation&lt;string&gt;(), // User's natural language query
  searchStrategy: Annotation&lt;string&gt;(), // Search strategy chosen by LLM
  searchParams: Annotation&lt;any&gt;(), // Prepared search parameters
  results: Annotation&lt;any[]&gt;(), // Search results
  final: Annotation&lt;string&gt;(), // Final formatted response
});<h3>Configure o aplicativo</h3><p>Todo o código desta seção pode ser encontrado no <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch">repositório elasticsearch-labs</a>.</p><p>Abra um terminal na pasta em que o app estará localizado e inicialize um app Node.js com o comando:</p>npm init -y<p>Agora podemos instalar as dependências necessárias para este projeto:</p>npm install @elastic/elasticsearch @langchain/langgraph @langchain/openai @langchain/core dotenv zod &amp;&amp; npm install --save-dev @types/node tsx typescript<ul><li><p><strong><code>@elastic/elasticsearch</code></strong>: Nos ajuda a lidar com requisições do Elasticsearch, como ingestão e recuperação de dados.</p></li><li><p><strong><code>@langchain/langgraph</code></strong>: dependência de JS para fornecer todas as ferramentas LangGraph.</p></li><li><p><strong><code>@langchain/openai</code></strong>Cliente OpenAI LLM para LangChain.</p></li><li><p>@langchain/núcleo: fornece os blocos de construção fundamentais para apps LangChain, incluindo modelos de prompt.</p></li><li><p><strong><code>dotenv</code></strong>: Dependência necessária para usar variáveis de ambiente em JavaScript.</p></li><li><p><strong><code>zod</code></strong>: Dependência para digitar dados.</p></li></ul><p><code>@types/node</code> <code>tsx</code> <code>typescript</code> nos permite escrever e executar o código TypeScript.</p><p>Agora, crie os seguintes arquivos:</p><ul><li><p><code>elasticsearchSetup</code><a href="http://ingest.ts/"><code>.ts</code></a>: Criará os mapeamentos de índice, carregará o conjunto de dados de um arquivo JSON e fará a ingestão dos dados no Elasticsearch.</p></li><li><p><a href="http://main.ts/"><code>main.ts</code></a>: incluirá o aplicativo LangGraph.</p></li><li><p><code>.env</code>: arquivo para armazenar as variáveis de ambiente</p></li></ul><p>No arquivo <code>.env</code>, vamos adicionar as seguintes variáveis de ambiente:</p>ELASTICSEARCH_ENDPOINT="your-endpoint-here"
ELASTICSEARCH_API_KEY="your-key-here"
OPENAI_API_KEY="your-key-here"<p>O APIKey da OpenAPI não será usado diretamente no código; em vez disso, será usado internamente pela biblioteca <code>@langchain/openai</code>.</p><p>Toda a lógica relacionada à criação de mapeamentos, modelos de busca e ingestão de conjuntos de dados pode ser encontrada no arquivo <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a>. Nos próximos passos, vamos focar no arquivo <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/main.ts"><code>main.ts</code></a> . Além disso, você pode verificar o conjunto de dados para entender melhor como os dados aparecem no <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/dataset.json"><code>dataset.json</code></a>.</p><h3>Aplicativo LangGraph</h3><p>No arquivo <code>main.ts</code>, vamos importar algumas dependências necessárias para consolidar a aplicação LangGraph. Neste arquivo, você também deve incluir as funções de nós e a declaração de estado. A declaração do gráfico será feita em um método <code>main</code> nos próximos passos. O arquivo <code>elasticsearchSetup.ts</code> conterá ajudantes Elasticsearch que vamos usar dentro dos nós em etapas futuras.</p>import { writeFileSync } from "node:fs";
import { StateGraph, Annotation, START, END } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import {
  esClient,
  ingestDocuments,
  createSearchTemplates,
  INDEX_NAME,
  INVESTMENT_FOCUSED_TEMPLATE,
  MARKET_FOCUSED_TEMPLATE,
  createIndex,
} from "./elasticsearchSetup.js";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });<p>Como mencionado anteriormente, o cliente LLM será usado para gerar os parâmetros de busca do Elasticsearch com base na pergunta do usuário.</p>async function saveGraphImage(app: any): Promise&lt;void&gt; {
  try {
    const drawableGraph = app.getGraph();
    const image = await drawableGraph.drawMermaidPng();
    const arrayBuffer = await image.arrayBuffer();

    const filePath = "./workflow_graph.png";
    writeFileSync(filePath, new Uint8Array(arrayBuffer));
    console.log(`📊 Workflow graph saved as: ${filePath}`);
  } catch (error: any) {
    console.log("⚠️  Could not save graph image:", error.message);
  }
}<p>O método acima gera a imagem do gráfico em formato PNG e usa a <a href="https://mermaid.ink/">API Mermaid.INK</a> nos bastidores. Isso é útil se você quiser ver como os nós do app interagem entre si com uma visualização estilizada.</p><h3>Nós do LangGraph</h3><p>Agora vamos analisar cada nó em detalhes:</p><h3>nó decideSearchStrategy</h3><p>O node <code>decideSearchStrategy</code> analisa a entrada do usuário e determina se realiza uma buscar focada em investimento ou no mercado. Ele utiliza um LLM com um esquema de saída estruturado (definido com Zod) para classificar o tipo de consulta. Antes de tomar a decisão, o sistema recupera os filtros disponíveis do índice por meio de uma agregação, garantindo que o modelo tenha um contexto atualizado sobre setores, locais e dados de financiamento.</p><p>Para extrair os valores possíveis dos filtros e enviá-los ao LLM, vamos usar uma consulta de <a href="https://www.elastic.co/docs/explore-analyze/query-filter/aggregations">agregação</a> para recuperá-los diretamente do índice do Elasticsearch. Essa lógica é alocada em um método chamado <code>getAvailableFilters</code>:</p>async function getAvailableFilters() {
  try {
    const response = await esClient.search({
      index: INDEX_NAME,
      size: 0,
      aggs: {
        industries: {
          terms: { field: "industry", size: 100 },
        },
        locations: {
          terms: { field: "location", size: 100 },
        },
        funding_stages: {
          terms: { field: "funding_stage", size: 20 },
        },
        business_models: {
          terms: { field: "business_model", size: 10 },
        },
        lead_investors: {
          terms: { field: "lead_investor", size: 100 },
        },
        funding_amount_stats: {
          stats: { field: "funding_amount" },
        },
      },
    });

    return response.aggregations;
  } catch (error) {
    console.error("❌ Error getting available filters:", error);
    return {};
  }
}<p>Com a consulta de agregação acima, temos os seguintes resultados:</p>{
  "industries": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "logistics",
        "doc_count": 5
      },
      ...
    ]
  },
  "locations": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "San Francisco, CA",
        "doc_count": 4
      },
      {
        "key": "New York, NY",
        "doc_count": 3
      },
      ...
    ]
  },
  "funding_stages": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "Series A",
        "doc_count": 8
      },
      ...
    ]
  },
  "business_models": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "B2B",
        "doc_count": 13
      },
      ...
    ]
  },
  "lead_investors": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "Battery Ventures",
        "doc_count": 1
      },
      {
        "key": "Benchmark Capital",
        "doc_count": 1
      },
      ...
    ]
  },
  "funding_amount_stats": {
    "count": 20,
    "min": 4500000,
    "max": 35000000,
    "avg": 14075000,
    "sum": 281500000
  }
}<p>Veja todos os resultados <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/responses/aggregationsResponse.json">aqui</a>.</p><p>Para ambas as estratégias, usaremos busca híbrida para detectar tanto a parte estruturada da pergunta (filtros) quanto as partes mais subjetivas (semântica). Aqui está um exemplo de ambas as consultas usando <a href="https://www.elastic.co/docs/solutions/search/search-templates">templates de busca</a>:</p>await esClient.putScript({
      id: INVESTMENT_FOCUSED_TEMPLATE,
      script: {
        lang: "mustache",
        source: `{
          "size": 5,
          "retriever": {
            "rrf": {
              "retrievers": [
                {
                  "standard": {
                    "query": {
                      "semantic": {
                        "field": "semantic_field",
                        "query": "{{query_text}}"
                      }
                    }
                  }
                },
                {
                  "standard": {
                    "query": {
                      "bool": {
                        "filter": [
                          {"terms": {"funding_stage": {{#join}}{{#toJson}}funding_stage{{/toJson}}{{/join}}}},
                          {"range": {"funding_amount": {"gte": {{funding_amount_gte}}{{#funding_amount_lte}},"lte": {{funding_amount_lte}}{{/funding_amount_lte}}}}},
                          {"terms": {"lead_investor": {{#join}}{{#toJson}}lead_investor{{/toJson}}{{/join}}}},
                          {"range": {"monthly_revenue": {"gte": {{monthly_revenue_gte}}{{#monthly_revenue_lte}},"lte": {{monthly_revenue_lte}}{{/monthly_revenue_lte}}}}}
                        ]
                      }
                    }
                  }
                }
              ],
              "rank_window_size": 100,
              "rank_constant": 20
            }
          }
        }`,
      },
    });<p>Veja as consultas detalhadas no arquivo <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts#L119"><code>elasticsearchSetup.ts</code></a> . No nó a seguir, será decidido qual das duas consultas será usada:</p>// Node 1: Decide search strategy using LLM
async function decideSearchStrategy(state: typeof VCState.State) {
  // Zod schema for specialized search strategy decision
  const SearchDecisionSchema = z.object({
    search_type: z
      .enum(["investment_focused", "market_focused"])
      .describe("Type of specialized search strategy to use"),
    reasoning: z
      .string()
      .describe("Brief explanation of why this search strategy was chosen"),
  });

  const decisionLLM = llm.withStructuredOutput(SearchDecisionSchema);

  // Get dynamic filters from Elasticsearch
  const availableFilters = await getAvailableFilters();

  const prompt = `Query: "${state.input}"
    Available filters: ${JSON.stringify(availableFilters, null, 2)}

    Choose between two specialized search strategies:
    
    - investment_focused: For queries about funding stages, funding amounts, monthly revenue, lead investors, financial performance
    
    - market_focused: For queries about industries, locations, business models, market segments, geographic markets
    
    Analyze the query intent and choose the most appropriate strategy.
  `;

  try {
    const result = await decisionLLM.invoke(prompt);
    console.log(
      `🤔 Search strategy: ${result.search_type} - ${result.reasoning}`
    );

    return {
      searchStrategy: result.search_type,
    };
  } catch (error: any) {
    console.error("❌ Error in decideSearchStrategy:", error.message);
    return {
      searchStrategy: "investment_focused",
    };
  }
}<h3>nós prepareInvestmentSearch e prepareMarketSearch</h3><p>Ambos os nós usam uma função auxiliar compartilhada, <code>extractFilterValues</code>, que utiliza o LLM para identificar filtros relevantes mencionados na entrada do usuário, como setor, localização, estágio de financiamento, modelo de negócios, etc. Estamos usando este esquema para construir nosso <a href="https://www.elastic.co/docs/solutions/search/search-templates">modelo de busca</a>.</p>// Extract all possible filter values from user input
async function extractFilterValues(input: string) {
  const FilterValuesSchema = z.object({
    // Investment-focused filters
    funding_stage: z
      .array(z.string())
      .default([])
      .describe("Funding stage values mentioned in query"),
    funding_amount_gte: z
      .number()
      .default(0)
      .describe("Minimum funding amount in USD"),
    funding_amount_lte: z
      .number()
      .default(100000000)
      .describe("Maximum funding amount in USD"),
    lead_investor: z
      .array(z.string())
      .default([])
      .describe("Lead investor values mentioned in query"),
    monthly_revenue_gte: z
      .number()
      .default(0)
      .describe("Minimum monthly revenue in USD"),
    monthly_revenue_lte: z
      .number()
      .default(10000000)
      .describe("Maximum monthly revenue in USD"),
    industry: z
      .array(z.string())
      .default([])
      .describe("Industry values mentioned in query"),
    location: z
      .array(z.string())
      .default([])
      .describe("Location values mentioned in query"),
    business_model: z
      .array(z.string())
      .default([])
      .describe("Business model values mentioned in query"),
  });

  const extractorLLM = llm.withStructuredOutput(FilterValuesSchema);
  const availableFilters = await getAvailableFilters();

  const extractPrompt = `Extract ALL relevant filter values from: "${input}"
    Available options: ${JSON.stringify(availableFilters, null, 2)}
    Extract only values explicitly mentioned in the query. Leave fields empty if not mentioned.`;

  return await extractorLLM.invoke(extractPrompt);
}<p>Dependendo da intenção detectada, o fluxo de trabalho seleciona um de dois caminhos:</p><p><strong>prepareInvestmentSearch:</strong> desenvolve parâmetros de busca orientados financeiramente, incluindo estágio de financiamento, valor do investimento, investidor e informações de renovação. Você pode encontrar o modelo completo de consulta no arquivo <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a>:</p>// Node 2A: Prepare Investment-Focused Search Parameters 
async function prepareInvestmentSearch(state: typeof VCState.State) {
  console.log(
    "💰 Preparing INVESTMENT-FOCUSED search parameters with financial emphasis..."
  );

  try {
    // Extract all filter values from input
    const values = await extractFilterValues(state.input);

    let searchParams: any = {
      template_id: INVESTMENT_FOCUSED_TEMPLATE,
      query_text: state.input,
      ...values,
    };

    return { searchParams };
  } catch (error) {
    console.error("❌ Error preparing investment-focused params:", error);
    return {
      searchParams: {},
    };
  }
}<p><strong>prepareMarketSearch:</strong> cria parâmetros orientados pelo mercado, focados em setores, geografias e modelos de negócios. Veja a consulta completa no arquivo <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a> :</p>// Node 2B: Prepare Market-Focused Search Parameters
async function prepareMarketSearch(state: typeof VCState.State) {
  console.log(
    "🔍 Preparing MARKET-FOCUSED search parameters with market emphasis..."
  );

  try {
    // Extract all filter values from input
    const values = await extractFilterValues(state.input);

    let searchParams: any = {
      template_id: MARKET_FOCUSED_TEMPLATE,
      query_text: state.input,
      ...values,
    };

    return { searchParams };
  } catch (error) {
    console.error("❌ Error preparing market-focused params:", error);
    return {};
  }
}<h3>nó executeSearch</h3><p>Este nó pega os parâmetros de busca gerados do estado e os envia primeiro para o Elasticsearch, usando a <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-render-search-template">API _render</a> para visualizar a consulta para fins de depuração, e então envia uma solicitação para buscar os resultados.</p>// Node 3: Execute Search
async function executeSearch(state: typeof VCState.State) {
  const { searchParams } = state;

  try {
    // getting formed query from template for debugging
    const renderedTemplate = await esClient.renderSearchTemplate({
      id: searchParams.template_id,
      params: searchParams,
    });

    console.log(
      "📋 Complete query:",
      JSON.stringify(renderedTemplate.template_output, null, 2)
    );

    const results = await esClient.searchTemplate({
      index: INDEX_NAME,
      id: searchParams.template_id,
      params: searchParams,
    });

    return {
      results: results.hits.hits.map((hit: any) =&gt; hit._source),
    };
  } catch (error: any) {
    console.error(`❌ ${state.searchParams.search_type} search error:`, error);
    return { results: [] };
  }
}<h3>nó visualizeResults</h3><p>Por fim, este nó exibe os resultados do Elasticsearch.</p>// Node 4: Visualize results
async function visualizeResults(state: typeof VCState.State) {
  const results = state.results || [];

  let formattedResults = `🎯 Found ${results.length} startups matching your criteria:\n\n`;

  results.forEach((startup: any, index: number) =&gt; {
    formattedResults += `${index + 1}. **${startup.company_name}**\n`;
    formattedResults += `   📍 ${startup.location} | 🏢 ${startup.industry} | 💼 ${startup.business_model}\n`;
    formattedResults += `   💰 ${startup.funding_stage} - $${(
      startup.funding_amount / 1000000
    ).toFixed(1)}M\n`;
    formattedResults += `   👥 ${startup.employee_count} employees | 📈 $${(
      startup.monthly_revenue / 1000
    ).toFixed(0)}K MRR\n`;
    formattedResults += `   🏦 Lead: ${startup.lead_investor}\n`;
    formattedResults += `   📝 ${startup.description}\n\n`;
  });

  return {
    final: formattedResults,
  };
}<p>Programaticamente, o gráfico completo tem a seguinte aparência:</p>  const workflow = new StateGraph(VCState)
    // Register nodes - these are the processing functions
    .addNode("decideStrategy", decideSearchStrategy)
    .addNode("prepareInvestment", prepareInvestmentSearch)
    .addNode("prepareMarket", prepareMarketSearch)
    .addNode("executeSearch", executeSearch)
    .addNode("visualizeResults", visualizeResults)
    // Define execution flow with conditional branching
    .addEdge(START, "decideStrategy") // Start with strategy decision
    .addConditionalEdges(
      "decideStrategy",
      (state: typeof VCState.State) =&gt; state.searchStrategy, // Conditional function
      {
        investment_focused: "prepareInvestment", // If investment focused -&gt; RRF template preparation
        market_focused: "prepareMarket", // If market focused -&gt; dynamic query preparation
      }
    )
    .addEdge("prepareInvestment", "executeSearch") // Investment prep -&gt; execute
    .addEdge("prepareMarket", "executeSearch") // Market prep -&gt; execute
    .addEdge("executeSearch", "visualizeResults") // Execute -&gt; visualize
    .addEdge("visualizeResults", END); // End workflow<p>Como você pode ver, temos uma aresta condicional onde o app decide qual "caminho" ou nó será executado em seguida. Esse recurso é útil quando fluxos de trabalho precisam de lógica de ramificação, como escolher entre várias ferramentas ou incluir uma etapa com uma pessoa no ciclo.</p><p>Com os recursos do núcleo do LangGraph entendidos, podemos configurar o aplicativo onde o código será executado:</p><p>Junte tudo em um método <code>main</code>; aqui declaramos o gráfico com todos os elementos sob a variável fluxo de trabalho:</p>async function main() {
  await createIndex();
  await createSearchTemplates();
  await ingestDocuments();

  // Create the workflow graph with shared state
  const workflow = new StateGraph(VCState)
    // Register nodes - these are the processing functions
    .addNode("decideStrategy", decideSearchStrategy)
    .addNode("prepareInvestment", prepareInvestmentSearch)
    .addNode("prepareMarket", prepareMarketSearch)
    .addNode("executeSearch", executeSearch)
    .addNode("visualizeResults", visualizeResults)
    // Define execution flow with conditional branching
    .addEdge(START, "decideStrategy") // Start with strategy decision
    .addConditionalEdges(
      "decideStrategy",
      (state: typeof VCState.State) =&gt; state.searchStrategy, // Conditional function
      {
        investment_focused: "prepareInvestment", // If investment focused -&gt; RRF template preparation
        market_focused: "prepareMarket", // If market focused -&gt; dynamic query preparation
      }
    )
    .addEdge("prepareInvestment", "executeSearch") // Investment prep -&gt; execute
    .addEdge("prepareMarket", "executeSearch") // Market prep -&gt; execute
    .addEdge("executeSearch", "visualizeResults") // Execute -&gt; visualize
    .addEdge("visualizeResults", END); // End workflow


  const app = workflow.compile();

  await saveGraphImage(app);

  const query =
    "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K";

  const marketResult = await app.invoke({ input: query });
  console.log(marketResult.final);
}<p>A variável de consulta simula a entrada do usuário inserida em uma barra de busca hipotética:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba7189d5f4e63403/6a1709880e2e49cc3041a076/e8d76909eb2bc1bb62f3ca9a8b3e4b85fcec2893-1600x164.png" alt="" /><p>A partir da frase em linguagem natural "Encontre startups com financiamento Série A ou Série B entre US$ 8M–US$ 25M e receita mensal acima de US$ 500K", todos os filtros serão extraídos.</p><p>Finalmente, invoque o método principal:</p>main().catch(console.error);<h3>Resultados</h3>🔍 Checking if index exists...
🏗️ Creating index...
✅ Index created successfully!
Ingesting documents...
✅ Documents ingested successfully!
✅ Investment-focused template created successfully!
✅ Market-focused template created successfully!

📊 Workflow graph saved as: ./workflow_graph.png

🔍 Query: "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K"

🤔 Search strategy: investment_focused - The query specifically seeks profitable fintech startups with defined funding amounts and high monthly revenue, which aligns closely with financial performance metrics and investment-related criteria.

💰 Preparing INVESTMENT-FOCUSED search parameters with financial emphasis...

📋 Complete query: {
  "size": 5,
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_field",
                "query": "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "bool": {
                "filter": [
                  {
                    "terms": {
                      "funding_stage": [
                        "Series A",
                        "Series B"
                      ]
                    }
                  },
                  {
                    "range": {
                      "funding_amount": {
                        "gte": 8000000,
                        "lte": 25000000
                      }
                    }
                  },
                  {
                    "terms": {
                      "lead_investor": []
                    }
                  },
                  {
                    "range": {
                      "monthly_revenue": {
                        "gte": 500000,
                        "lte": 0
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "rank_window_size": 100,
      "rank_constant": 20
    }
  }
}
🎯 Found 5 startups matching your criteria:

1. **TechFlow**
   📍 San Francisco, CA | 🏢 logistics | 💼 B2B
   💰 Series A - $8.0M
   👥 45 employees | 📈 $500K MRR
   🏦 Lead: Sequoia Capital
   📝 TechFlow optimizes supply chain operations using AI-powered route optimization and real-time tracking. Founded in 2023, shows remarkable growth with $500K monthly revenue.

2. **DataViz**
   📍 New York, NY | 🏢 enterprise software | 💼 B2B
   💰 Series A - $10.0M
   👥 42 employees | 📈 $450K MRR
   🏦 Lead: Battery Ventures
   📝 DataViz creates intuitive data visualization tools for enterprise customers. No-code platform allows business users to create dashboards without technical expertise.

3. **FinanceAI**
   📍 San Francisco, CA | 🏢 fintech | 💼 B2C
   💰 Series C - $25.0M
   👥 120 employees | 📈 $1200K MRR
   🏦 Lead: Tiger Global Management
   📝 FinanceAI provides AI-powered investment advisory services to retail investors. Uses machine learning to analyze market trends with over 100,000 active users.

4. **UrbanMobility**
   📍 New York, NY | 🏢 logistics | 💼 B2B2C
   💰 Series B - $15.0M
   👥 78 employees | 📈 $750K MRR
   🏦 Lead: Kleiner Perkins
   📝 UrbanMobility revolutionizes urban transportation through autonomous delivery drones and smart logistics hubs. Partners with major retailers for same-day delivery across Manhattan and Brooklyn.

5. **HealthTech Solutions**
   📍 Boston, MA | 🏢 healthcare | 💼 B2B
   💰 Series B - $18.0M
   👥 95 employees | 📈 $900K MRR
   🏦 Lead: General Catalyst
   📝 HealthTech Solutions develops medical devices and software for remote patient monitoring. Comprehensive telehealth platform reducing hospital readmissions by 30%.

✨  Done in 18.80s.<p>Para a entrada enviada, a aplicação escolhe o caminho <strong>focado no investimento</strong> e, como resultado, podemos ver a consulta Elasticsearch gerada pelo fluxo de trabalho LangGraph, que extrai os valores e intervalos a partir da entrada do usuário. Também podemos ver a consulta enviada para o Elasticsearch com os valores extraídos aplicados e, finalmente, os resultados formatados pelo node <code>visualizeResults</code> com os resultados.</p><p>Agora vamos testar o nó <strong>focado no mercado</strong> usando a consulta "Encontre startups de fintech e saúde em São Francisco, Nova York ou Boston":</p>...

🔍 Query: Find fintech and healthcare startups in San Francisco, New York, or Boston

🤔 Search strategy: market_focused - The query is focused on finding fintech startups in San Francisco that are disrupting traditional banking and payment systems, which pertains to specific industries (fintech) and locations (San Francisco). Thus, a market-focused strategy is more appropriate.

🔍 Preparing MARKET-FOCUSED search parameters with market emphasis...

📋 Complete query: {
  "size": 5,
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_field",
                "query": "Find fintech and healthcare startups in San Francisco, New York, or Boston"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "bool": {
                "filter": [
                  {
                    "terms": {
                      "industry": [
                        "fintech",
                        "healthcare"
                      ]
                    }
                  },
                  {
                    "terms": {
                      "location": [
                        "San Francisco, CA",
                        "New York, NY",
                        "Boston, MA"
                      ]
                    }
                  },
                  {
                    "terms": {
                      "business_model": []
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "rank_window_size": 50,
      "rank_constant": 10
    }
  }
}
🎯 Found 5 startups matching your criteria:

1. **FinanceAI**
   📍 San Francisco, CA | 🏢 fintech | 💼 B2C
   💰 Series C - $25.0M
   👥 120 employees | 📈 $1200K MRR
   🏦 Lead: Tiger Global Management
   📝 FinanceAI provides AI-powered investment advisory services to retail investors. Uses machine learning to analyze market trends with over 100,000 active users.

2. **CryptoWallet**
   📍 Miami, FL | 🏢 fintech | 💼 B2C
   💰 Series B - $16.0M
   👥 73 employees | 📈 $820K MRR
   🏦 Lead: Coinbase Ventures
   📝 CryptoWallet provides secure digital wallet solutions for cryptocurrency trading and storage. Multi-chain support with enterprise-grade security features.

...

✨  Done in 7.41s.<h2>Aprendizados</h2><p>Durante o processo de escrita, aprendi:</p><ul><li><p>Devemos mostrar ao LLM os valores exatos dos filtros; caso contrário, dependemos de o usuário digitar os valores exatos das coisas. Para baixa cardinalidade, essa abordagem é válida; mas, quando a cardinalidade é alta, precisamos de algum mecanismo para filtrar os resultados.</p></li><li><p>Usar templates para busca torna os resultados muito mais consistentes do que deixar o LLM escrever a consulta Elasticsearch, e também é mais rápido</p></li><li><p>Arestas condicionais são um mecanismo poderoso para construir aplicações com múltiplas variantes e caminhos ramificados.</p></li><li><p>A saída estruturada é extremamente útil ao gerar informações com LLMs porque impõe respostas previsíveis e seguras para tipos. Isso melhora a confiabilidade e reduz as interpretações errôneas imediatas.</p></li></ul><p>Combinar busca semântica e estruturada por meio da recuperação híbrida produz resultados melhores e mais relevantes, equilibrando precisão e compreensão do contexto.</p><h2>Conclusão</h2><p>Neste exemplo, combinamos LangGraph.js com o Elasticsearch para criar um fluxo de trabalho dinâmico capaz de interpretar consultas em linguagem natural e decidir entre estratégias de busca voltadas para finanças ou para o mercado. Essa abordagem reduz a complexidade de elaborar consultas manuais, ao mesmo tempo em que melhora a flexibilidade e a precisão para analistas de capital de risco.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-workflow-finance-langgraph-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-workflow-finance-langgraph-elasticsearch</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt013eba5d152f11f3/6a1709892b835f6784f4b1a6/12b6057d84c6356267cd178a3c6c1a5c61123ece-2000x1256.png" length="0" type="image/png"/>
    <pubDate>Fri, 05 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criar um conector do ChatGPT com o Elasticsearch para consultar problemas no GitHub]]></title>
    <description><![CDATA[Saiba como criar um conector ChatGPT personalizado e implantar um servidor Elasticsearch MCP que usa a pesquisa híbrida para buscar problemas internos do GitHub.]]></description>
    <content:encoded><![CDATA[<p>Recentemente, a OpenAI anunciou o recurso de <a href="https://help.openai.com/en/articles/11487775-connectors-in-chatgpt">conectores personalizados</a> para o ChatGPT nos planos Pro/Business/Empresarial e Edu. Além dos conectores prontos para uso para acessar dados no Gmail, GitHub, Dropbox etc. É possível criar conectores personalizados usando servidores MCP.</p><p>Os conectores personalizados permitem que você combine seus conectores ChatGPT existentes com fontes adicionais de dados, como o Elasticsearch, para obter respostas abrangentes.</p><p>Neste artigo, criaremos um servidor <a href="https://modelcontextprotocol.io/docs/getting-started/intro">MCP</a> que conecta o ChatGPT a um índice Elasticsearch contendo informações sobre problemas internos e solicitações de pull do GitHub. Isso permite que consultas em linguagem natural sejam respondidas usando os dados do seu Elasticsearch.</p><p>Implantaremos o servidor MCP usando o <a href="https://gofastmcp.com/getting-started/welcome">FastMCP</a> no Google Colab com ngrok para obter um URL público ao qual o ChatGPT possa se conectar, eliminando a necessidade de uma configuração de infraestrutura complexa.</p><p>Para uma visão geral do MCP e seu ecossistema, consulte <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">O Estado Atual do MCP</a>.</p><h2>Pré-requisitos</h2><p>Antes de começar, você precisará de:</p><ul><li><p>Cluster do Elasticsearch (8.X ou superior)</p></li><li><p>Chave de API do Elasticsearch com acesso de leitura ao seu índice</p></li><li><p>Conta do Google (para o Google Colab)</p></li><li><p>Conta Ngrok (versão gratuita funciona)</p></li><li><p>Conta do ChatGPT com plano Pro/Empresarial/Business ou Edu</p></li></ul><h2>Entendendo os requisitos do conector MCP do ChatGPT</h2><p>Os conectores MCP do ChatGPT exigem a implementação de duas ferramentas: <code>search</code> e <code>fetch</code>. Para mais detalhes, consulte <a href="https://platform.openai.com/docs/mcp#create-an-mcp-server">OpenAI Docs</a>.</p><h3><a href="https://platform.openai.com/docs/mcp#search-tool">Ferramenta de busca</a></h3><p>Retorna uma lista de resultados relevantes do seu índice Elasticsearch com base em uma consulta do usuário.</p><h4>O que ele recebe:</h4><ul><li><p>Uma única string com a consulta de linguagem natural do usuário.</p></li><li><p>Exemplo: "Encontre problemas relacionados à migração do Elasticsearch."</p></li></ul><h4>O que ele retorna: </h4><ul><li><p>Um objeto com uma chave <code>result</code> contendo um array de objetos de resultado. Cada resultado inclui:</p><ul><li><p><code>id</code> - Identificador único do documento</p></li><li><p><code>title</code> - Título da issue ou do PR</p></li><li><p><code>url</code> - Link para o problema/PR</p></li></ul></li></ul><h4>Na nossa implementação:</h4>return {
    "results": [
        {
            "id": "PR-612",
            "title": "Fix memory leak in WebSocket notification service",
            "url": "https://internal-git.techcorp.com/pulls/612"
        },
        # ... more results
    ]
}<h3><a href="https://platform.openai.com/docs/mcp#fetch-tool">Ferramenta de recuperação</a></h3><p>Recupera o conteúdo completo de um documento específico.</p><h4>O que ele recebe:</h4><ul><li><p>Uma única string com o ID do documento Elasticsearch do resultado de busca</p></li><li><p>Exemplo: "Me dê os detalhes do PR-578."</p></li></ul><h4>O que ele retorna:</h4><ul><li><p>Um objeto de documento completo com:</p><ul><li><p><code>id</code> - Identificador único do documento</p></li><li><p><code>title</code> - Título da issue ou do PR</p></li><li><p><code>text</code> - Complete a descrição e os detalhes do problema/PR</p></li><li><p><code>url</code> - Link para o problema/PR</p></li><li><p><code>type</code> - Tipo de documento (issue, pull_request)</p></li><li><p><code>status</code> - Status atual (aberto, em_andamento, resolvido)</p></li><li><p><code>priority</code> - Nível de prioridade (baixo, médio, alto, crítico)</p></li><li><p><code>assignee</code> - Pessoa designada para o problema/PR</p></li><li><p><code>created_date</code> - Quando foi criado</p></li><li><p><code>resolved_date</code> - Quando foi resolvido (se aplicável)</p></li><li><p><code>labels</code> - Tags associadas ao documento</p></li><li><p><code>related_pr</code> - ID de pull request relacionado</p></li></ul></li></ul>return {
    "id": "PR-578",
    "title": "Security hotfix: Patch SQL injection vulnerabilities",
    "text": "Description: CRITICAL SECURITY FIX for ISSUE-1889. Patches SQL...",
    "url": "https://internal-git.techcorp.com/pulls/578",
    "type": "pull_request",
    "status": "closed",
    "priority": "critical",
    "assignee": "sarah_dev",
    "created_date": "2025-09-19",
    "resolved_date": "2025-09-19",
    "labels": "security, hotfix, sql",
    "related_pr": null
}<p><strong>Observação</strong>: este exemplo usa uma estrutura plana onde todos os campos estão no nível raiz. Os requisitos do OpenAI são flexíveis e também permitem objetos de metadados aninhados.</p><h2>Questões do GitHub e conjunto de dados PRs</h2><p>Para este tutorial, vamos usar um conjunto de dados interno do GitHub contendo problemas e solicitações de pull. Isso representa um cenário em que você deseja consultar dados privados e internos por meio do ChatGPT.</p><p>O conjunto de dados pode ser encontrado <a href="https://gist.github.com/TomasMurua/4e7bbdf7a7ebbdffaa663c43578d934a">aqui</a>. E atualizaremos o índice dos dados usando a <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-bulk">bulk API</a>.</p><p>Esse conjunto de dados inclui:</p><ul><li><p>Problemas com descrições, status, prioridade e responsáveis</p></li><li><p>Solicitações de pull com alterações de código, revisões e informações de implantação</p></li><li><p>Relações entre problemas e PRs (por exemplo, PR-578 corrige o ISSUE-1889)</p></li><li><p>Rótulos, datas e outros metadados</p></li></ul><h3>Mapeamentos de índice</h3><p>O índice usa os seguintes <a href="https://www.elastic.co/docs/manage-data/data-store/mapping">mapeamentos</a> para permitir a pesquisa híbrida com o <a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-elser">ELSER</a>. A <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text">text_semantic</a> é usada para busca semântica, enquanto outros campos permitem a busca por palavras-chave.</p>{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "title": {
        "type": "text"
      },
      "text": {
        "type": "text"
      },
      "text_semantic": {
        "type": "semantic_text",
        "inference_id": ".elser-2-elasticsearch"
      },
      "url": {
        "type": "keyword"
      },
      "type": {
        "type": "keyword"
      },
      "status": {
        "type": "keyword"
      },
      "priority": {
        "type": "keyword"
      },
      "assignee": {
        "type": "keyword"
      },
      "created_date": {
        "type": "date",
        "format": "iso8601"
      },
      "resolved_date": {
        "type": "date",
        "format": "iso8601"
      },
      "labels": {
        "type": "keyword"
      },
      "related_pr": {
        "type": "keyword"
      }
    }
  }
}<h2>Construa o servidor MCP</h2><p>Nosso servidor MCP implementa duas ferramentas seguindo as especificações da OpenAI, usando busca híbrida para combinar correspondência semântica e de texto para obter melhores resultados.</p><h3>Ferramenta de busca</h3><p>Utiliza busca híbrida com <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">RRF</a> (Reciprocal Rank Fusion), combinando buscar semântica com correspondência de texto:</p>@mcp.tool()
    async def search(query: str) -&gt; Dict[str, List[Dict[str, Any]]]:
        """
        Search for internal issues and PRs using hybrid search (semantic + text with RRF).
        Returns list with id, title, and url per OpenAI spec.
        """
        if not query or not query.strip():
            return {"results": []}

        logger.info(f"Searching for: '{query}'")

        try:
            # Hybrid search with RRF (Reciprocal Rank Fusion)
            response = es_client.search(
                index=ELASTICSEARCH_INDEX,
                size=10,
                source=["id", "title", "url", "type", "priority"],
                retriever={
                    "rrf": {
                        "retrievers": [
                            {
                                # Semantic search with ELSER
                                "standard": {
                                    "query": {
                                        "semantic": {
                                            "field": "text_semantic",
                                            "query": query
                                        }
                                    }
                                }
                            },
                            {
                                # Text search (BM25) for keyword matching
                                "standard": {
                                    "query": {
                                        "multi_match": {
                                            "query": query,
                                            "fields": [
                                                "title^3",
                                                "text^2",
                                                "assignee^2",
                                                "type",
                                                "labels",
                                                "priority"
                                            ],
                                            "type": "best_fields",
                                            "fuzziness": "AUTO"
                                        }
                                    }
                                }
                            }
                        ],
                        "rank_window_size": 50,
                        "rank_constant": 60
                    }
                }
            )

            results = []
            if response and 'hits' in response:
                for hit in response['hits']['hits']:
                    source = hit['_source']
                    results.append({
                        "id": source.get('id', hit['_id']),
                        "title": source.get('title', 'Unknown'),
                        "url": source.get('url', '')
                    })

            logger.info(f"Found {len(results)} results")
            return {"results": results}

        except Exception as e:
            logger.error(f"Search error: {e}")
            raise ValueError(f"Search failed: {str(e)}")<h3>Pontos principais:</h3><ul><li><p><strong>Busca híbrida com RRF:</strong> combina busca semântica (ELSER) e busca por texto (BM25) para melhores resultados.</p></li><li><p><strong>Consulta multi-correspondência:</strong> <a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-multi-match-query">busca em múltiplos campos</a> com aumento de relevância (title^3, text^2, assignee^2). O símbolo de caret (^) multiplica as pontuações de relevância, priorizando as correspondências nos títulos em detrimento do conteúdo.</p></li><li><p><strong>Correspondência inexata:</strong> <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/common-options#fuzziness"><code>fuzziness: AUTO</code></a> lida com erros de digitação e ortografia, permitindo correspondências aproximadas.</p></li><li><p><strong>Ajuste dos parâmetros do RRF:</strong></p><ul><li><p><code>rank_window_size: 50</code> - Especifica quantos resultados principais de cada recuperador (semântico e textual) são considerados antes da mesclagem.</p></li><li><p><code>rank_constant: 60</code> - Esse valor determina quanta influência os documentos em conjuntos de resultados individuais têm sobre o resultado final classificado.</p></li></ul></li><li><p><strong>Retorna somente os campos obrigatórios:</strong> <code>id</code>, <code>title</code>, <code>url</code> de acordo com a especificação da OpenAI e evita a exposição desnecessária de campos adicionais.</p></li></ul><h3>Ferramenta de recuperação</h3><p>Recupera detalhes do documento pelo ID do documento, quando existe:</p>@mcp.tool()
    async def fetch(id: str) -&gt; Dict[str, Any]:
        """
        Retrieve complete issue/PR details by ID.
        Returns id, title, text, url.
        """
        if not id:
            raise ValueError("ID is required")

        logger.info(f"Fetching: {id}")

        try:
            # Search by the 'id' field (not _id) since IDs are stored as a field
            response = es_client.search(
                index=ELASTICSEARCH_INDEX,
                body={
                    "query": {
                        "term": {
                            "id": id  # Search by your custom 'id' field
                        }
                    },
                    "size": 1
                }
            )

            if not response or not response['hits']['hits']:
                raise ValueError(f"Document with id '{id}' not found")

            hit = response['hits']['hits'][0]
            source = hit['_source']

            result = {
                "id": source.get('id', id),
                "title": source.get('title', 'Unknown'),
                "text": source.get('text', ''),
                "url": source.get('url', ''),
                "type": source.get('type', ''),
                "status": source.get('status', ''),
                "priority": source.get('priority', ''),
                "assignee": source.get('assignee', ''),
                "created_date": source.get('created_date', ''),
                "resolved_date": source.get('resolved_date', ''),
                "labels": source.get('labels', ''),
                "related_pr": source.get('related_pr', '')
            }

            logger.info(f"Fetched: {result['title']}")
            return result

        except Exception as e:
            logger.error(f"Fetch error: {e}")
            raise ValueError(f"Failed to fetch '{id}': {str(e)}")<h3>Pontos principais:</h3><ul><li><p><strong>Buscar por campo de ID do documento:</strong> Utiliza consulta de termo no campo personalizado <code>id</code></p></li><li><p><strong>Retorna o documento completo:</strong> inclui o campo <code>text</code> completo com todo o conteúdo</p></li><li><p><strong>Estrutura plana:</strong> Todos os campos no nível da raiz, correspondendo à estrutura de documentos do Elasticsearch.</p></li></ul><h2>Implantar no Google Colab</h2><p>Usaremos o Google Colab para executar nosso servidor MCP e o ngrok para expô-lo publicamente, permitindo que o ChatGPT se conecte a ele.</p><h3>Etapa 1: Abra o notebook do Google Colab</h3><p>Acesse nosso notebook pré-configurado <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/elasticsearch-chatgpt-connector">Elasticsearch MCP para ChatGPT</a>.</p><h3>Etapa 2: Configure suas credenciais</h3><p>Você precisará de três informações:</p><ul><li><p><strong>URL do Elasticsearch:</strong> seu <a href="https://www.elastic.co/docs/deploy-manage/deploy/cloud-enterprise/connect-elasticsearch">URL do cluster do Elasticsearch</a>.</p></li><li><p><strong>Chave da API do Elasticsearch:</strong> <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys">Chave da API</a> com permissão de leitura do seu índice.</p></li><li><p><strong>Token de autenticação Ngrok:</strong> token grátis do <a href="https://ngrok.com/">ngrok</a>. Vamos usar o ngrok para expor a URL do MCP à internet para que o ChatGPT possa se conectar a ela.</p></li></ul><h4>Obter seu token ngrok</h4><ol><li><p>Cadastre-se para uma conta gratuita em <a href="https://ngrok.com/">ngrok</a></p></li><li><p>Acesse seu <a href="https://dashboard.ngrok.com/">painel do ngrok</a></p></li><li><p>Copie seu token de autenticação.</p></li></ol><h4>Adicionando segredos ao Google Colab</h4><p>No notebook do Google Colab:</p><ol><li><p>Clique no <strong>ícone de chave </strong>na barra lateral esquerda para abrir <strong>Secrets</strong>.</p></li><li><p>Adicione estes três segredos:</p></li></ol>ELASTICSEARCH_URL=https://your-cluster.elastic.com:443
ELASTICSEARCH_API_KEY=your-api-key
NGROK_TOKEN=your-ngrok-token<p>3. Habilitar o acesso ao notebook para cada segredo</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5acae97b386277f8/6a17f08f5ea30f74c964b6c2/d5dd6ac19fe816a562c6351fdb0f11369da0e877-609x321.jpg" alt="Adicionar segredos ao Google Collab" /><h3>Passo 3: Execute o notebook</h3><ol><li><p>Clique em <strong>Runtime</strong> e depois em <strong>Executar tudo</strong> para executar todas as células</p></li><li><p>Aguarde o servidor iniciar (cerca de 30 segundos)</p></li><li><p>Procure a saída mostrando seu URL público do ngrok</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdd11aacf2deab67c/6a17f091e8fbce81f13a1a41/f185100e8869624bc9e1c7b2b4eb32785e2d89e7-1189x283.png" alt="" /><p>4. A saída exibirá algo como:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8891d917fdbaaf48/6a17f092abe0f208c7dfeaf6/e02e625e91ed9136454e4401b184575fb03a336e-1052x465.jpg" alt="A saída da execução de um notebook no Google Collab" /><h2>Conectar-se ao ChatGPT</h2><p>Agora vamos conectar o servidor MCP à sua conta do ChatGPT.</p><ol><li><p>Abra o ChatGPT e vá para <strong>Configurações</strong>.</p></li><li><p>Navegue até <strong>Conectores. </strong>Se você estiver usando uma conta Pro, precisará ativar <a href="https://platform.openai.com/docs/guides/developer-mode">o modo de desenvolvedor</a> nos conectores.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt95efdcb2c39307e7/6a17f094abe0f24d8edfeafa/32c02192912fc0e7e5a52e9399077ba7ae3b4901-739x715.png" alt="Conectando o servidor MPC a uma conta do ChatGPT" /><p><em>Se você está usando o ChatGPT em empresas ou negócios, precisa disponibilizar o conector para seu local de trabalho.</em></p><p>3. Clique em <strong>Criar</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4c8fc8dd6033918/6a17f095631730de19585b7b/15c53e5ccc381108a9dc0052cca05bf0fc97679a-755x683.png" alt="Adicionando um conector ao ChatGPT" /><p><em><strong>Observação</strong></em><em>: nos espaços de trabalho Business, Empresarial e Edu, somente os proprietários, administradores e usuários com a respectiva configuração ativada (para Empresarial/Edu) podem adicionar conectores personalizados. Usuários com a função de membro padrão não têm permissão para adicionar conectores personalizados.</em></p><p><em>Após um conector ser adicionado e habilitado por um proprietário ou usuário administrador, ele fica disponível para todos os membros do espaço de trabalho.</em></p><p>4. Insira as informações necessárias e sua URL ngrok que termina em <code>/sse/</code>. Repare no "/" após "sse". Não vai funcionar sem ele:</p><ul><li><p><strong>Nome:</strong> Elasticsearch MCP</p></li><li><p><strong>Descrição: </strong>MCP personalizado para pesquisar e recuperar informações internas do GitHub.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd716ad0beeeb1d35/6a17f09714d90c11cc79b6d7/162a85705cc8ac48a3f2f665551d513e0719f93d-479x684.png" alt="Criar um Conector MCP Elastic " /><p>5. Pressione <strong>Criar</strong> para salvar o MCP personalizado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt857794237d7d3b5a/6a17f0983e03d729b74f2d54/97eb5fb0a32b86bfadfb35561f698616f217c049-913x629.png" alt="Salvar o conector MCP personalizado clicando em criar" /><p>A conexão será instantânea se seu servidor estiver em execução. Não é necessária autenticação adicional, pois a chave da API do Elasticsearch está configurada no seu servidor.</p><h2>Teste o servidor MCP</h2><p>Antes de fazer perguntas, você precisa selecionar qual conector o ChatGPT deve usar.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd1602c48878dc7a9/6a17f09a6df731cca90a0fff/77a6fc1eb263a0eb16aac64f2ecaca5f4ac12ec2-966x568.gif" alt="Selecionar qual conector o ChatGPT deve usar" /><h3>Prompt 1: Buscar por problemas</h3><p>Pergunte: "<strong>Encontre problemas relacionados à migração do Elasticsearch" </strong>e confirme a chamada da ferramenta de ações.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6c204ceacf897f61/6a17f09c9da390fb1de4657d/cfd781acbff8cd7c8095bbe29224f8b26d581f77-650x375.png" alt="Peça ao ChatGPT &quot;Encontre problemas relacionados à migração do Elasticsearch&quot; e confirme a chamada da ferramenta de ações." /><p>O ChatGPT chamará a ferramenta <code>search</code> com sua consulta. Você pode ver que ele está procurando as ferramentas disponíveis, se preparando para chamar a ferramenta Elasticsearch e confirma com o usuário antes de tomar qualquer medida em relação à ferramenta.</p><h4>Solicitação de chamada de ferramenta:</h4>{
  "query": "Elasticsearch migration issues"
}<h4>Resposta da ferramenta:</h4>{
  "results": [
    {
      "id": "PR-598",
      "title": "Elasticsearch 8.x migration - Application code changes",
      "url": "https://internal-git.techcorp.com/pulls/598"
    },
    {
      "id": "ISSUE-1712",
      "title": "Migrate from Elasticsearch 7.x to 8.x",
      "url": "https://internal-git.techcorp.com/issues/1712"
    },
    {
      "id": "RFC-045",
      "title": "Design Proposal: Microservices Migration Architecture",
      "url": "https://internal-git.techcorp.com/rfcs/045"
    }
    // ... 7 more results
  ]
}<p>O ChatGPT processa os resultados e os apresenta em um formato natural e conversacional.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1b4378e7d26b4ad0/6a17f09ddbb4ff4de1fb57bf/9d5b6cff85c7e54ccc2584b8ae96d45495fae8c1-923x1352.png" alt="Como o ChatGPT processa os resultados da solicitação de chamada da ferramenta e da resposta à chamada da ferramenta" /><h3>Nos bastidores</h3><h4>Prompt: "Encontrar problemas relacionados à migração do Elasticsearch"</h4><p>1. Chamadas do ChatGPT <code>search(“Elasticsearch migration”)</code></p><p>2. O Elasticsearch realiza uma busca híbrida</p><ul><li><p><strong>A busca semântica</strong> compreende conceitos como "atualização" e "<em>compatibilidade de versões"</em>.</p></li><li><p>A <strong>busca de texto</strong> encontra correspondências exatas para "<em>Elasticsearch</em>" e "migração".</p></li><li><p>O <strong>RRF</strong> combina e classifica os resultados de ambas as abordagens</p></li></ul><p>3. Retorna os 10 melhores eventos de correspondência com <code>id</code>, <code>title</code>, <code>url</code></p><p>4. O ChatGPT identifica "<em>ISSUE-1712: migrar do Elasticsearch 7.x para o 8.x</em>" como o resultado mais relevante</p><h3>Prompt 2: Obter todos os detalhes</h3><p>Perguntar: <em><strong>"Informe detalhes sobre o ISSUE-1889"</strong></em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8d1a53db8bfe8326/6a17f09f445de966104d021a/5c0db5245535ce67a36056e61e135bddc97ce496-934x629.png" alt="O ChatGPT reconhece que você quer informações detalhadas sobre um problema específico, aciona a ferramenta fetch e confirma com o usuário antes de tomar qualquer medida em relação à ferramenta." /><p>O ChatGPT reconhece que você quer informações detalhadas sobre um problema específico e aciona a ferramenta <code>fetch</code>, confirmando com o usuário antes de tomar qualquer medida em relação à ferramenta.</p><h4>Solicitação de chamada de ferramenta:</h4>{
  "id": "ISSUE-1889"
}<h4>Resposta da ferramenta:</h4>{
  "id": "ISSUE-1889",
  "title": "SQL injection vulnerability in search endpoint",
  "text": "Description: Security audit identified SQL injection vulnerability in /api/v1/search endpoint. User input from query parameter is not properly sanitized before being used in raw SQL query. Severity: HIGH - Immediate action required Affected Code: - File: services/search/query_builder.py - Line: 145-152 - Issue: String concatenation used instead of parameterized queries Investigation: - @security_team_alice: Confirmed exploitable with UNION-based injection - @sarah_dev: Checking all other endpoints for similar patterns - @john_backend: Found 3 more instances in legacy codebase Remediation: - Rewrite using SQLAlchemy ORM or parameterized queries - Add input validation and sanitization - Implement WAF rules as additional layer - Security regression tests Comments: - @tech_lead_mike: Stop all other work, this is P0 - @sarah_dev: PR-578 ready with fixes for all 4 vulnerable endpoints - @alex_devops: Deployed hotfix to production 2025-09-19 at 14:30 UTC - @security_team_alice: Verified fix, conducting full pentest next week Resolution: All vulnerable endpoints patched. Added pre-commit hooks to catch raw SQL queries. Security training scheduled for team.",
  "url": "https://internal-git.techcorp.com/issues/1889",
  "type": "issue",
  "status": "closed",
  "priority": "critical",
  "assignee": "sarah_dev",
  "created_date": "2025-09-18",
  "resolved_date": "2025-09-19",
  "labels": "security, vulnerability, bug, sql",
  "related_pr": "PR-578"
}<p>O ChatGPT sintetiza as informações e as apresenta claramente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt560958fa3bd212d0/6a17f0a0faa91355ba93c974/410f19f213e94fc4e3c47eeef6e04b69e0c86159-602x462.png" alt="Como o ChatGPT sintetiza as informações e as apresenta " /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcccf35a584e8373b/6a17f0a2505ac3471cad8c2e/54d8ffa117628a1e3afc317c3ab75d4f7731d7ab-767x1600.png" alt="Como o ChatGPT apresenta as informações" /><h3>Nos bastidores</h3><h4>Prompt: “Informe mais detalhes sobre ISSUE-1889”</h4><ol><li><p>Chamadas do ChatGPT <code>fetch(“ISSUE-1889”)</code></p></li><li><p>O Elasticsearch recupera o documento completo</p></li><li><p>Retorna um documento completo com todos os campos no nível raiz</p></li><li><p>O ChatGPT sintetiza as informações e responde com citações adequadas.</p></li></ol><h2>Conclusão</h2><p>Neste artigo, criamos um servidor MCP personalizado que conecta o ChatGPT ao Elasticsearch usando ferramentas MCP dedicadas de <strong>busca</strong> e <strong>recuperação</strong>, permitindo consultas em linguagem natural sobre dados privados.</p><p>Este padrão MCP funciona para qualquer índice Elasticsearch, documentação, produtos, log ou quaisquer outros dados que você queira consultar por meio de linguagem natural.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/chatgpt-connector-mcp-server-github-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/chatgpt-connector-mcp-server-github-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Busca híbrida]]></category>
    <dc:creator><![CDATA[Tomás Murúa]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd1602c48878dc7a9/6a17f09a6df731cca90a0fff/77a6fc1eb263a0eb16aac64f2ecaca5f4ac12ec2-966x568.gif" length="0" type="image/gif"/>
    <pubDate>Mon, 01 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Desenvolvimento de um assistente RAG agente usando LangChain e Elasticsearch]]></title>
    <description><![CDATA[Aprenda como construir um assistente de notícias interativo usando LangChain e Elasticsearch que responde a consultas sobre artigos com roteamento adaptativo.]]></description>
    <content:encoded><![CDATA[<p>Este artigo do blog explora os fluxos de trabalho RAG com agentes, explicando suas principais características e padrões de design comuns. Além disso, demonstra como implementar esses fluxos de trabalho por meio de um exemplo prático que utiliza o Elasticsearch como repositório de vetores e o LangChain para construir a estrutura RAG agentiva. Por fim, o artigo discute brevemente as melhores práticas e os desafios associados ao projeto e à implementação de tais arquiteturas. Você pode acompanhar o passo a passo para criar um pipeline RAG simples e agético com este <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/agentic-rag/agent_rag_news_assistant.ipynb">notebook Jupyter</a>.</p><h2>Introdução ao RAG agentivo</h2><p>A Geração Aumentada por Recuperação (<a href="https://www.elastic.co/docs/solutions/search/rag">RAG</a>, na sigla em inglês) tornou-se um pilar fundamental em aplicações baseadas em Modelos de Aprendizagem Baseados em Aprendizagem (LLM, na sigla em inglês), permitindo que os modelos forneçam respostas otimizadas ao recuperar o contexto relevante com base nas consultas do usuário. Os sistemas RAG aprimoram a precisão e o contexto das respostas do LLM (Modelo de Aprendizagem Baseado em Aprendizagem) ao utilizar informações externas provenientes de APIs ou bancos de dados, em vez de se limitarem ao conhecimento pré-treinado do LLM. Por outro lado, os agentes de IA operam de forma autônoma, tomando decisões e executando ações para atingir seus objetivos designados.</p><p>O RAG Agentic é uma estrutura que unifica os pontos fortes da geração aumentada por recuperação e do raciocínio agentivo. Ele integra o RAG ao processo de tomada de decisão do agente, permitindo que o sistema escolha dinamicamente fontes de dados, refine consultas para melhor recuperação de contexto, gere respostas mais precisas e aplique um ciclo de feedback para melhorar continuamente a qualidade da saída.</p><h2>Principais características do RAG agentivo</h2><p>A estrutura RAG agentiva representa um grande avanço em relação aos sistemas RAG tradicionais. Em vez de seguir um processo de recuperação fixo, utiliza agentes dinâmicos capazes de planejar, executar e otimizar resultados em tempo real.</p><p>Vamos analisar algumas das principais características que distinguem os pipelines RAG agentivos:</p><ul><li><p><strong>Tomada de decisão dinâmica</strong>: o Agentic RAG utiliza um mecanismo de raciocínio para compreender a intenção do usuário e direcionar cada consulta para a fonte de dados mais relevante, produzindo respostas precisas e contextualizadas.</p></li><li><p><strong>Análise abrangente de consultas:</strong> o Agentic RAG analisa profundamente as consultas dos usuários, incluindo subperguntas e sua intenção geral. Ele avalia a complexidade da consulta e seleciona dinamicamente as fontes de dados mais relevantes para recuperar informações, garantindo respostas precisas e completas.</p></li><li><p><strong>Colaboração em múltiplas etapas</strong>: Esta estrutura permite a colaboração em múltiplas etapas através de uma rede de agentes especializados. Cada agente lida com uma parte específica de um objetivo maior, trabalhando sequencialmente ou simultaneamente para alcançar um resultado coeso.</p></li><li><p><strong>Mecanismos de autoavaliação</strong>: O pipeline RAG agentivo utiliza a autorreflexão para avaliar os documentos recuperados e as respostas geradas. Ele pode verificar se as informações recuperadas respondem completamente à consulta e, em seguida, revisar a saída quanto à precisão, integridade e consistência factual.</p></li><li><p><strong>Integração com ferramentas externas</strong>: Este fluxo de trabalho pode interagir com APIs externas, bancos de dados e fontes de informação em tempo real, incorporando informações atualizadas e adaptando-se dinamicamente à evolução dos dados.</p></li></ul><h2>Padrões de fluxo de trabalho do RAG agente</h2><p>Os padrões de fluxo de trabalho definem como a IA agente estrutura, gerencia e orquestra aplicações baseadas em LLM de maneira confiável e eficiente. Diversas estruturas e plataformas, como <a href="https://www.langchain.com/">LangChain</a>, <a href="https://www.langchain.com/langgraph">LangGraph</a>, <a href="https://www.crewai.com/">CrewAI</a> e <a href="https://www.llamaindex.ai/">LlamaIndex</a>, podem ser usadas para implementar esses fluxos de trabalho com agentes.</p><ol><li><p><strong>Cadeia de recuperação sequencial</strong>: Os fluxos de trabalho sequenciais dividem tarefas complexas em etapas simples e ordenadas. Cada etapa melhora a entrada para a próxima, levando a melhores resultados. Por exemplo, ao criar um perfil de cliente, um agente pode extrair detalhes básicos de um CRM, outro recupera o histórico de compras de um banco de dados de transações e um agente final combina essas informações para gerar um perfil completo para recomendações ou relatórios.</p></li><li><p><strong>Cadeia de roteamento e recuperação</strong>: Neste padrão de fluxo de trabalho, um agente de roteamento analisa a entrada e a direciona para o processo ou fonte de dados mais apropriada. Essa abordagem é particularmente eficaz quando existem múltiplas fontes de dados distintas com sobreposição mínima. Por exemplo, em um sistema de atendimento ao cliente, o agente de roteamento categoriza as solicitações recebidas, como problemas técnicos, reembolsos ou reclamações, e as encaminha para o departamento apropriado para um tratamento eficiente.</p></li><li><p><strong>Cadeia de recuperação paralela</strong>: Neste padrão de fluxo de trabalho, várias subtarefas independentes são executadas simultaneamente e suas saídas são posteriormente agregadas para gerar uma resposta final. Essa abordagem reduz significativamente o tempo de processamento e aumenta a eficiência do fluxo de trabalho. Por exemplo, em um fluxo de trabalho paralelo de atendimento ao cliente, um agente recupera solicitações anteriores semelhantes, enquanto outro consulta artigos relevantes da base de conhecimento. Um agregador combina então esses resultados para gerar uma resolução abrangente.</p></li><li><p><strong>Cadeia de trabalho do Orchestrator</strong>: Este fluxo de trabalho compartilha semelhanças com a paralelização devido à sua utilização de subtarefas independentes. No entanto, uma distinção fundamental reside na integração de um agente orquestrador. Este agente é responsável por analisar as consultas do usuário, segmentá-las dinamicamente em subtarefas durante a execução e identificar os processos ou ferramentas apropriados necessários para formular uma resposta precisa.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1e2e634cf9c94e25/6a17ff81b1e113c9fc79f4e0/ece6fc2403f211556c93e99d5227bfb7053b0c31-1600x1047.png" alt="Padrão de fluxo de trabalho em RAG agético" /><h2>Construindo um pipeline RAG agético do zero.</h2><p>Para ilustrar os princípios do RAG agentivo, vamos projetar um fluxo de trabalho usando LangChain e Elasticsearch. Este fluxo de trabalho adota uma arquitetura baseada em roteamento, onde múltiplos agentes colaboram para analisar consultas, recuperar informações relevantes, avaliar resultados e gerar respostas coerentes. Você pode consultar este <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/agentic-rag/agent_rag_news_assistant.ipynb">notebook Jupyter</a> para acompanhar este exemplo.</p><p>O fluxo de trabalho começa com o agente de roteamento, que analisa a consulta do usuário para selecionar o método de recuperação ideal, ou seja, uma abordagem <code>vectorstore</code>, <code>websearch</code> ou <code>composite</code> . O vectorstore lida com a recuperação tradicional de documentos baseada em RAG, a pesquisa na web busca as informações mais recentes que não estão armazenadas no vectorstore, e a abordagem composta combina ambas quando são necessárias informações de múltiplas fontes.</p><p>Se os documentos forem considerados adequados, o agente de sumarização gera uma resposta clara e contextualizada. No entanto, se os documentos forem insuficientes ou irrelevantes, o agente de reescrita de consultas reformula a consulta para melhorar a pesquisa. Essa consulta revisada reinicia o processo de roteamento, permitindo que o sistema refine sua busca e aprimore o resultado final.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16020333cf6dda91/6a17ff82e8fbceb4d83a1c00/ed8701a7f15558fbf2e967a884b3e770eccb826b-1256x1092.png" alt="Como um sistema agente refina sua saída com diferentes consultas" /><h3>Pré-requisitos</h3><p>Este fluxo de trabalho depende dos seguintes componentes principais para executar o exemplo de forma eficaz:</p><ul><li><p>Python 3.10</p></li><li><p><a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/agentic-rag/agent_rag_news_assistant.ipynb">Notebook Jupyter</a></p></li><li><p>Azure OpenAI</p></li><li><p>Elasticsearch</p></li><li><p>LangChain</p></li></ul><p>Antes de prosseguir, você será solicitado a configurar o seguinte conjunto de variáveis de ambiente obrigatórias para este exemplo.</p>AZURE_OPENAI_ENDPOINT="Add your azure openai endpoint"
AZURE_OPENAI_KEY="Add your azure openai key"
AZURE_OPENAI_DEPLOYMENT="gpt-4.1"
AZURE_OPENAI_API_VERSION="Add your azure openai api version"

ES_ENDPOINT = "Add your Elasticsearch ENDPOINT"
ES_API_KEY = "Add your Elasticsearch API KEY"<h3>Fontes de dados</h3><p>Este fluxo de trabalho é ilustrado usando um subconjunto do conjunto de dados da AG News. O conjunto de dados inclui artigos de notícias de diversas categorias, como Internacional, Esportes, Negócios e Ciência/Tecnologia.</p>dataset = load_dataset("ag_news", split="train[:1000]")
docs = [
    Document(
        page_content=sample["text"],
        metadata={"category": sample["label"]}
    )
    for sample in dataset
]<p>O <a href="https://python.langchain.com/docs/integrations/vectorstores/elasticsearch/">módulo ElasticsearchStore</a> é utilizado a partir do <code>langchain_elasticsearch</code> como nosso armazenamento de vetores. Para a recuperação de dados, implementamos a SparseVectorStrategy, utilizando <a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-elser">o ELSER</a>, o modelo de incorporação proprietário da Elastic. É essencial confirmar se o modelo ELSER está instalado e implantado corretamente em seu ambiente Elasticsearch antes de iniciar o armazenamento de vetores.</p>elastic_vectorstore = ElasticsearchStore.from_documents(
    docs,
    es_url=ES_ENDPOINT,
    es_api_key=ES_API_KEY,
    index_name=index_name,
    strategy=SparseVectorStrategy(model_id=".elser_model_2"),
)

elastic_vectorstore.client.indices.refresh(index=index_name)<p>A funcionalidade de busca na web é implementada usando <a href="https://python.langchain.com/api_reference/community/tools/langchain_community.tools.ddg_search.tool.DuckDuckGoSearchRun.html">o DuckDuckGoSearchRun</a> das ferramentas da comunidade LangChain, o que permite que o sistema recupere informações em tempo real da web de forma eficiente. Você também pode considerar o uso de outras APIs de busca que podem fornecer resultados mais relevantes. Essa ferramenta foi escolhida por permitir buscas sem a necessidade de uma chave de API.</p>duckduckgo = DuckDuckGoSearchRun(description= "A custom DuckDuckGo search tool for finding latest news stories.", verbose=True)
def websearch_retriever(query):
    results = duckduckgo.run(f"{query}")
    return results<p>O recuperador composto foi projetado para consultas que exigem uma combinação de fontes. É utilizado para fornecer uma resposta abrangente e contextualizada, recuperando simultaneamente dados em tempo real da web e consultando notícias históricas do banco de dados vetorial.</p>def composite_retriever(query):
    related_docs = vectorstore_retriever(query)
    related_docs += websearch_retriever(query)
    return related_docs<h3>Configurar os agentes</h3><p>Na etapa seguinte, os agentes LLM são definidos para fornecer capacidades de raciocínio e tomada de decisão dentro desse fluxo de trabalho. As cadeias LLM que criaremos incluem: <code>router_chain</code>, <code>grade_docs_chain</code>, <code>rewrite_query_chain</code> e <code>summary_chain</code>.</p><p>O agente de roteamento utiliza um assistente LLM para determinar a fonte de dados mais apropriada para uma determinada consulta em tempo de execução. O agente de classificação avalia os documentos recuperados quanto à sua relevância. Se os documentos forem considerados relevantes, eles são encaminhados ao agente de resumo para gerar um resumo. Caso contrário, o agente de reescrita de consultas reformula a consulta e a envia de volta ao processo de roteamento para uma nova tentativa de recuperação. Você pode encontrar as instruções para todos os agentes na seção Cadeias LLM do <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/agentic-rag/agent_rag_news_assistant.ipynb">caderno</a>.</p>class RouteQuery(BaseModel):
    datasource: Literal["vectorstore", "websearch", "composite"] = Field(
        ...,
        description="Choose to route the query to web search, vectorstore or composite."
    )

router_prompt = ChatPromptTemplate.from_template("""You are an assistant that decides the best data source for questions based on news articles.
Choose one of the following options:
- 'vectorstore': for general, background, or historical news articles.
- 'websearch': for recent discoveries, 'latest', 'current', or '2025' type queries.
- 'composite': when the question needs both historical and current knowledge on news articles.

Question: {query}

Return one word: 'vectorstore', 'websearch', or 'composite'.
""")
router_structured = llm.with_structured_output(RouteQuery)
router_chain: RunnableSequence = router_prompt | router_structured<p>O <code>llm.with_structured_output</code> restringe a saída do modelo a seguir um esquema predefinido definido pelo BaseModel sob a classe <code>RouteQuery</code> , garantindo a consistência dos resultados. A segunda linha compõe um <code>RunnableSequence</code> conectando <code>router_prompt</code> com <code>router_structured</code>, formando um pipeline no qual o prompt de entrada é processado pelo modelo de linguagem para produzir resultados estruturados e compatíveis com o esquema.</p><h3>Defina os nós do grafo.</h3><p>Esta parte envolve a definição dos estados do grafo, que representam os dados que fluem entre os diferentes componentes do sistema. Uma especificação clara desses estados garante que cada nó no fluxo de trabalho saiba quais informações ele pode acessar e atualizar.</p>class RAGState(TypedDict):
    query: str
    docs: List[Document]
    router: str
    summary: str
    self_reflection: bool
    retry_count: int = 0<p>Uma vez definidos os estados, o próximo passo é definir os nós do grafo. Os nós são como as unidades funcionais do grafo que executam operações específicas sobre os dados. Nosso pipeline possui 7 nós diferentes.</p>def router(state: RAGState):
   router = router_chain.invoke({'query': state["query"]})
   logger.info(f"Router selected the datasource: {router.datasource}")
   logger.info(f"User query: {state['query']}")
   return {"router": router.datasource}

def vectorstore(state: RAGState):
   return {"docs": vectorstore_retriever(state["query"])}

def websearch(state: RAGState):
   return {"docs": websearch_retriever(state["query"])}

def composite(state: RAGState):
   return {"docs": composite_retriever(state["query"])}

def self_reflection(state: RAGState):
   evaluation = grade_docs_chain.invoke(
       {"query": state["query"], "docs": state["docs"]}
   )
   if evaluation.binary_score:
       logger.info(f"Self-reflection passed -- binary_score={evaluation.binary_score}")
   else:
       logger.info(f"Self-reflection failed -- binary_score={evaluation.binary_score}")

   return {
       "self_reflection": evaluation.binary_score,
   }

def query_rewriter(state: RAGState):
   retry_count = state.get("retry_count", 0) + 1
   new_query = rewrite_query_chain.invoke({"query": state["query"]})
   logger.info(f"Query rewritten: {new_query}, retry_count: {retry_count}")
   return {
       "query": new_query,
       "retry_count": retry_count,
   }

def summarize(state: RAGState):
   summary = summarize_chain.run(
       query=state["query"],
       docs=state["docs"],
   )
   return {"summary": summary}<p>O nó <code>query_rewriter</code> serve a dois propósitos no fluxo de trabalho. Primeiro, ele reescreve a consulta do usuário usando o <code>rewrite_query_chain</code> para melhorar a recuperação quando os documentos avaliados pelo agente de autorreflexão são considerados insuficientes ou irrelevantes. Em segundo lugar, funciona como um contador que registra quantas vezes a consulta foi reescrita.</p><p>Cada vez que o nó é invocado, ele incrementa o <code>retry_count</code> armazenado no estado do fluxo de trabalho. Esse mecanismo impede que o fluxo de trabalho entre em um loop infinito. Se o <code>retry_count</code> exceder um limite predefinido, o sistema pode recorrer a um estado de erro, uma resposta padrão ou qualquer outra condição predefinida que você escolher.</p><h3>Compilando o gráfico</h3><p>O último passo é definir as arestas do grafo e adicionar quaisquer condições necessárias antes de compilá-lo. Cada grafo deve começar a partir de um nó inicial designado, que serve como ponto de entrada para o fluxo de trabalho. As arestas no grafo representam o fluxo de dados entre os nós e podem ser de dois tipos:</p><ul><li><p>Arestas retas: Estas definem um fluxo direto e incondicional de um nó para outro. Sempre que o primeiro nó conclui sua tarefa, o fluxo de trabalho avança automaticamente para o próximo nó ao longo da aresta reta.</p></li><li><p>Arestas condicionais: Permitem que o fluxo de trabalho se ramifique com base no estado atual ou nos resultados da computação de um nó. O próximo nó é selecionado dinamicamente, dependendo de condições como resultados de avaliação, decisões de roteamento ou número de tentativas.</p></li></ul>graph.add_edge(START, "router")

def after_router(state: RAGState):
   route = state.get("router", None)
   if route == "vectorstore":
       return "vectorstore"
   elif route == "websearch":
       return "websearch"
   else:
       return "composite"

def after_self_reflection(state: RAGState):
   if state["self_reflection"]:
           return "summarize"
   return "query_rewriter"

def after_query_rewriter(state: RAGState):
   while state['retry_count'] &lt;= 3:
           return "router"
   raise RuntimeError("Maximum retries (3) reached -- evaluation failed.")

graph.add_conditional_edges(
   "router",
   after_router,
   {
       "vectorstore": "vectorstore",
       "websearch": "websearch",
       "composite": "composite"
   }
)

graph.add_edge("vectorstore", "self_reflection")
graph.add_edge("websearch", "self_reflection")
graph.add_edge("composite", "self_reflection")
graph.add_conditional_edges(
   "self_reflection",
   after_self_reflection,
   {
       "summarize": "summarize",
       "query_rewriter": "query_rewriter"
   }
)
graph.add_conditional_edges("query_rewriter", after_query_rewriter, {"router": "router"})
graph.add_edge("summarize", END)
agent=graph.compile()<p>Com isso, seu primeiro pipeline RAG agentivo está pronto e pode ser testado usando o agente compilado.</p>result = agent.invoke({"query": query1})
logger.info(f"\nFinal Summary:\n: {result['summary']}")<h3>Testando o pipeline RAG agentivo</h3><p>Agora vamos testar esse pipeline usando três tipos distintos de consultas, conforme descrito abaixo. Note que os resultados podem variar, e os exemplos mostrados abaixo ilustram apenas um resultado possível.</p>query1="What are the latest AI models released this month?"
query2="What technological innovations are discussed in Sci/Tech news?"
query3="Compare a Sci/Tech article from the dataset with a current web article about AI trends."<p>Para a primeira consulta, o roteador seleciona <code>websearch</code> como fonte de dados. A consulta falha na avaliação de autorreflexão e, consequentemente, é redirecionada para a etapa de reescrita da consulta, conforme mostrado na saída.</p>INFO     | __main__:router:11 - Router selected the datasource: websearch
INFO     | __main__:router:12 - User query: What are the latest AI models released this month?
Latest Singapore news, including the city state's relationships with Malaysia and Mahathir, China and Xi Jinping, and the rest of Southeast Asia. 3 days ago · The latest military news, insights and analysis from China. All the latest news, opinions and analysis on Hong Kong, China, Asia and around the world Latest news, in-depth features and opinion on Malaysia, covering politics, economy, society and the Asean member-nation's relationships with China, Singapore, and other Southeast Asian ... Oct 12, 2025 · Brics (an acronym for Brazil, Russia, India, China and South Africa) refers to an association of 10 leading emerging markets. The other member states are Egypt, Ethiopia, ...
INFO     | __main__:self_reflection:31 - Self-reflection failed -- binary_score=False
INFO     | __main__:query_rewriter:40 - Query rewritten: query='Which AI models have been officially released in June 2024?', retry_count: 1
INFO     | __main__:router:11 - Router selected the datasource: websearch
INFO     | __main__:router:12 - User query: query='Which AI models have been officially released in June 2024?'
Dream Machine is a text-to-video model created by Luma Labs and launched in June 2024 . It generates video output based on user prompts or still images. Dream Machine has been noted for its ability to realistically capture motion... Released in June 2023. In June 2024 , Baidu announced Ernie 4.0 Turbo. In April 2025, Ernie 4.5 Turbo and X1 Turbo were released . These models are optimized for faster response times and lower operational costs.[28][29]. The meaning of QUERY is question, inquiry. How to use query in a sentence. Synonym Discussion of Query. QUERY definition: 1. a question, often expressing doubt about something or looking for an answer from an authority.... Learn more. Query definition: a question; an inquiry.. See examples of QUERY used in a sentence.
INFO     | __main__:self_reflection:29 - Self-reflection passed -- binary_score=True
INFO     | __main__:&lt;module&gt;:2 - 
Final Summary:
: In June 2024, two AI models were officially released: Dream Machine, a text-to-video model launched by Luma Labs, and Ernie 4.0 Turbo, announced by Baidu, which is optimized for faster response times and lower operational costs.<p>Em seguida, examinamos um exemplo onde a recuperação <code>vectorstore</code> é usada, demonstrado com a segunda consulta.</p>INFO     | __main__:router:11 - Router selected the datasource: vectorstore
INFO     | __main__:router:12 - User query: What technological innovations are discussed in Sci/Tech news?
INFO     | __main__:self_reflection:29 - Self-reflection passed -- binary_score=True
INFO     | __main__:&lt;module&gt;:2 - 
Final Summary:
: Recent Sci/Tech news highlights several technological innovations: NASA is collaborating with Silicon Valley firms to build a powerful Linux-based supercomputer to support theoretical research and shuttle engineering; new chromatin transfer techniques have enabled the cloning of cats; cybersecurity advancements are being discussed in relation to protecting personal technology; Princeton University scientists assert that existing technologies can be used immediately to stabilize global warming; and a set of GameBoy micro-games has been recognized for innovation in game design.<p>A consulta final é direcionada à recuperação composta, que utiliza tanto o armazenamento vetorial quanto a pesquisa na web.</p>INFO     | __main__:router:11 - Router selected the datasource: composite
INFO     | __main__:router:12 - User query: Compare a Sci/Tech article from the dataset with a current web article about AI trends.
Atlas currently only available on macOS, built on Chromium with planned features like ad-blocking still in development. OpenAI's Atlas browser launched with bold promises of AI -powered web browsing, but early real-world testing reveals a different story. Career-long data are updated to end-of-2024 and single recent year data pertain to citations received during calendar year 2024. The selection is based on the top 100,000 scientists by c-score (with and without self-citations) or a percentile rank of 2% or above in the sub-field. In this article I list 45 AI tools across 21 different categories. After exploring all the available options in each category, I've carefully selected the best tools based on my personal experience. Reading a complex technical article ? Simply highlight confusing terminology and ask "what's this?" to receive instant explanations. compare browsers. Comparison showing traditional browser navigation versus OpenAI Atlas AI -powered workflows. After putting Gemini, ChatGPT, Grok, and DeepSeek through rigorous testing in October 2025, it's clear that there isn't one AI that reigns supreme across all categories.
INFO     | __main__:self_reflection:29 - Self-reflection passed -- binary_score=True
INFO     | __main__:&lt;module&gt;:2 - 
Final Summary:
: A Sci/Tech article from the dataset highlights NASA's development of robust artificial intelligence software for planetary rovers, aiming to make them more self-reliant and capable of decision-making during missions. In contrast, a current web article about AI trends focuses on the proliferation of AI-powered tools across various categories, including browsers like OpenAI Atlas, and compares leading models such as Gemini, ChatGPT, Grok, and DeepSeek, noting that no single AI currently excels in all areas. While the NASA article emphasizes specialized AI applications for autonomous robotics in space exploration, the current trends article showcases the broadening impact of AI across consumer and professional technologies, with ongoing competition and rapid innovation among major AI platforms.<p>No fluxo de trabalho acima, o RAG agente determina de forma inteligente qual fonte de dados usar ao recuperar informações para uma consulta do usuário, melhorando assim a precisão e a relevância da resposta. Você pode criar exemplos adicionais para testar o agente e analisar os resultados para verificar se eles produzem algum resultado interessante.</p><h2>Melhores práticas para a construção de fluxos de trabalho RAG com agentes</h2><p>Agora que entendemos como o RAG agético funciona, vamos analisar algumas práticas recomendadas para a construção desses fluxos de trabalho. Seguir estas diretrizes ajudará a manter o sistema eficiente e de fácil manutenção.</p><ul><li><p><strong>Prepare-se para planos de contingência</strong>: Planeje estratégias alternativas com antecedência para cenários em que qualquer etapa do fluxo de trabalho falhe. Isso pode incluir retornar respostas padrão, acionar estados de erro ou usar ferramentas alternativas. Isso garante que o sistema lide com as falhas de forma adequada, sem interromper o fluxo de trabalho geral.</p></li><li><p><strong>Implemente um registro abrangente</strong>: tente implementar o registro em cada etapa do fluxo de trabalho, como novas tentativas, saídas geradas, opções de roteamento e reescritas de consultas. Esses registros ajudam a melhorar a transparência, facilitam a depuração e auxiliam no aprimoramento de prompts, comportamento do agente e estratégias de recuperação ao longo do tempo.</p></li><li><p><strong>Selecione o padrão de fluxo de trabalho apropriado</strong>: Analise seu caso de uso e selecione o padrão de fluxo de trabalho que melhor atenda às suas necessidades. Utilize fluxos de trabalho sequenciais para raciocínio passo a passo, fluxos de trabalho paralelos para fontes de dados independentes e padrões de orquestrador-trabalhador para consultas complexas ou que envolvam múltiplas ferramentas.</p></li><li><p><strong>Incorporar estratégias de avaliação</strong>: Integrar mecanismos de avaliação em diferentes etapas do fluxo de trabalho. Isso pode incluir agentes de autorreflexão, classificação de documentos recuperados ou verificações de qualidade automatizadas. A avaliação ajuda a verificar se os documentos recuperados são relevantes, se as respostas são precisas e se todas as partes de uma consulta complexa foram abordadas.</p></li></ul><h2>Desafios</h2><p>Embora os sistemas RAG agentivos ofereçam vantagens significativas em termos de adaptabilidade, precisão e raciocínio dinâmico, eles também apresentam certos desafios que devem ser abordados durante as fases de projeto e implementação. Alguns dos principais desafios incluem:</p><ul><li><p><strong>Fluxos de trabalho complexos</strong>: À medida que mais agentes e pontos de decisão são adicionados, o fluxo de trabalho geral torna-se cada vez mais complexo. Isso pode levar a uma maior probabilidade de erros ou falhas em tempo de execução. Sempre que possível, priorize fluxos de trabalho simplificados, eliminando agentes redundantes e pontos de decisão desnecessários.</p></li><li><p><strong>Escalabilidade</strong>: Pode ser desafiador dimensionar sistemas RAG com agentes para lidar com grandes conjuntos de dados e altos volumes de consultas. Incorpore estratégias eficientes de indexação, armazenamento em cache e processamento distribuído para manter o desempenho em grande escala.</p></li><li><p><strong>Orquestração e sobrecarga computacional</strong>: A execução de fluxos de trabalho com múltiplos agentes requer orquestração avançada. Isso inclui um planejamento cuidadoso, gerenciamento de dependências e coordenação de agentes para evitar gargalos e conflitos, fatores que contribuem para a complexidade geral do sistema.</p></li><li><p><strong>Complexidade da avaliação</strong>: A avaliação desses fluxos de trabalho apresenta desafios inerentes, uma vez que cada etapa requer uma estratégia de avaliação distinta. Por exemplo, a etapa RAG deve ser avaliada quanto à relevância e completude dos documentos recuperados, enquanto os resumos gerados precisam ser verificados quanto à qualidade e precisão. Da mesma forma, a eficácia da reformulação de consultas requer uma lógica de avaliação separada para determinar se a consulta reescrita melhora os resultados da recuperação.</p></li></ul><h2>Conclusão</h2><p>Neste post do blog, apresentamos o conceito de RAG agente e destacamos como ele aprimora a estrutura tradicional de RAG, incorporando capacidades autônomas da IA agente. Exploramos as principais funcionalidades do RAG agentivo e demonstramos essas funcionalidades por meio de um exemplo prático, construindo um assistente de notícias usando o Elasticsearch como repositório de vetores e o LangChain para criar a estrutura agentiva.</p><p>Além disso, discutimos as melhores práticas e os principais desafios a serem considerados ao projetar e implementar um pipeline RAG com agentes. Essas informações têm como objetivo orientar os desenvolvedores na criação de sistemas de agentes robustos, escaláveis e eficientes que combinem efetivamente recuperação de dados, raciocínio e tomada de decisões.</p><h2>O que vem a seguir</h2><p>O fluxo de trabalho que desenvolvemos é simples, deixando bastante espaço para melhorias e experimentação. Podemos melhorar isso experimentando com vários modelos de incorporação e refinando as estratégias de recuperação. Além disso, a integração de um agente de reclassificação para priorizar os documentos recuperados pode ser benéfica. Outra área a ser explorada envolve o desenvolvimento de estratégias de avaliação para estruturas de agentes, especificamente a identificação de abordagens comuns e reutilizáveis aplicáveis a diferentes tipos de estruturas. Por fim, experimentar essas estruturas em conjuntos de dados grandes e mais complexos.</p><p>Entretanto, se você tiver experiências semelhantes para compartilhar, adoraríamos saber mais sobre elas! Fique à vontade para enviar seus comentários ou entrar em contato conosco por meio do nosso <a href="https://ela.st/slack">canal da comunidade no Slack</a> ou <a href="https://discuss.elastic.co/c/security">dos fóruns de discussão</a>.</p><h2>Recursos</h2><ul><li><p><a href="https://arxiv.org/abs/2310.11511">Auto-RAG: Aprendendo a Recuperar, Gerar e Criticar por meio da Autorreflexão</a></p></li><li><p><a href="https://arxiv.org/abs/2501.09136">Geração Aumentada por Recuperação Agencial: Uma Análise sobre RAG Agencial</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agentic-rag-news-assistant-langchain-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agentic-rag-news-assistant-langchain-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Kirti Sodhi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8c7a9f3b0d141d5d/6a17ff83fbc5f86686491d15/59dc0077f5dab00561d9f1b1e7dbf8ec3456259e-1600x1047.heif" length="0" type="image/*"/>
    <pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando um agente de IA para RH com Elastic Agent Builder e GPT-OSS]]></title>
    <description><![CDATA[Descubra como criar um agente de IA capaz de responder a consultas em linguagem natural sobre os dados de RH dos seus funcionários usando o Elastic Agent Builder e o GPT-OSS.]]></description>
    <content:encoded><![CDATA[<h2>Introdução</h2><p>Este artigo mostrará como criar um agente de IA para RH usando <a href="https://openai.com/index/introducing-gpt-oss/">GPT-OSS</a> e Elastic Agent Builder. O agente pode responder às suas perguntas sem enviar dados para a OpenAI, Anthropic ou qualquer serviço externo.</p><p>Usaremos o LM Studio para disponibilizar o GPT-OSS localmente e conectá-lo ao Elastic Agent Builder.</p><p>Ao final deste artigo, você terá um agente de IA personalizado capaz de responder a perguntas em linguagem natural sobre os dados de seus funcionários, mantendo o controle total sobre suas informações e modelo.</p><h2>Pré-requisitos</h2><p>Para ler este artigo, você precisa de:</p><ul><li><p><a href="https://www.elastic.co/cloud">Elastic Cloud</a> hospedado na versão 9.2, implantação <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart">local</a> ou sem servidor.</p></li><li><p>Recomenda-se máquina com 32 GB de RAM (mínimo de 16 GB para GPT-OSS 20B).</p></li><li><p><a href="https://lmstudio.ai/">LM Studio</a> instalado</p></li><li><p><a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a> instalado</p></li></ul><h2>Por que usar GPT-OSS?</h2><p>Com um LLM local, você tem o controle para implantá-lo em sua própria infraestrutura e ajustá-lo para atender às suas necessidades específicas. Tudo isso mantendo o controle sobre os dados que você compartilha com o modelo e, claro, sem precisar pagar nenhuma taxa de licença a um fornecedor externo.</p><p>A OpenAI <a href="https://openai.com/index/introducing-gpt-oss/">lançou o GPT-OSS</a> em 5 de agosto de 2025, como parte de seu compromisso com o ecossistema de modelos abertos.</p><p>O modelo de parâmetros 20B oferece:</p><ul><li><p><strong>capacidades de utilização da ferramenta</strong></p></li><li><p><strong>Inferência eficiente</strong></p></li><li><p><strong>Compatível com o SDK OpenAI</strong></p></li><li><p><strong>Compatível com fluxos de trabalho agentes</strong></p></li></ul><p>Comparação de referência:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt58fab956edb40412/6a170cfcb0367da43a72bd80/29160e3345352088e8213297630882f252b00c47-1600x680.png" alt="" /><h2>Arquitetura da solução</h2><p>A arquitetura é executada inteiramente em sua máquina local. O Elastic (executado em um contêiner Docker) se comunica diretamente com seu LLM local por meio do LM Studio, e o Elastic Agent Builder usa essa conexão para criar agentes de IA personalizados que podem consultar os dados de seus funcionários.</p><p>Para obter mais detalhes, consulte esta <a href="https://www.elastic.co/docs/solutions/observability/connect-to-own-local-llm">documentação</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80db5bb0a797f51b/6a170cfd0e2e492f2c41a16f/a4a886750ff25fa8bb7aefc7448161e52cf73ed3-1600x896.png" alt="" /><h2>Construindo um agente de IA para RH: Etapas</h2><p>Dividiremos a implementação em 5 etapas:</p><ol><li><p>Configure o LM Studio com um modelo local.</p></li><li><p>Implante o Elastic local com o Docker.</p></li><li><p>Crie o conector OpenAI no Elastic</p></li><li><p>Carregar dados de funcionários no Elasticsearch</p></li><li><p>Crie e teste seu agente de IA.</p></li></ol><h2>Etapa 1: Configurar o LM Studio com GPT-OSS 20B</h2><p>O LM Studio é um aplicativo fácil de usar que permite executar grandes modelos de linguagem localmente em seu computador. Ele fornece um servidor de API compatível com OpenAI, facilitando a integração com ferramentas como o Elastic, sem um processo de configuração complexo. Para obter mais detalhes, consulte a <a href="https://lmstudio.ai/docs/app">documentação do LM Studio</a>.</p><p>Primeiro, baixe e instale o LM Studio a partir do site oficial. Após a instalação, abra o aplicativo.</p><h3>Na interface do LM Studio:</h3><ol><li><p>Acesse a aba de pesquisa e procure por “GPT-OSS”.</p></li><li><p>Selecione o <code>openai/gpt-oss-20b</code> da OpenAI</p></li><li><p>Clique em baixar</p></li></ol><p>O tamanho deste modelo deverá ser de aproximadamente <strong>12,10 GB</strong>. O download pode demorar alguns minutos, dependendo da sua conexão com a internet.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2dc341a6625e34b7/6a170cff839dfa2eb4dcff44/5d01bc4dcb377b5259fc6b521fe2425a31b90ca4-1312x872.png" alt="" /><h4>Após o download do modelo:</h4><ol><li><p>Acesse a aba do servidor local.</p></li><li><p>Selecione o openai/gpt-oss-20b</p></li><li><p>Use a porta padrão 1234</p></li><li><p>No painel direito, acesse <strong>Carregar </strong>e defina o Comprimento do Contexto para <strong>40K</strong> ou mais.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3704ca1b28465cc4/6a170d00d7c022ed8fde64ef/e546033f916381647b876815b2c1f1ae2a08365f-326x337.png" alt="" /><p>5. Clique em Iniciar servidor</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7b9170a4945ff857/6a170d0266c4f9ffadf8c0a6/28ee78a3caa84d14e04db3d42f30acbe4d4d005a-1312x872.png" alt="" /><p>Você deverá ver isso se o servidor estiver em execução.</p>[LM STUDIO SERVER] Success! HTTP server listening on port 1234
[LM STUDIO SERVER] Supported endpoints:
[LM STUDIO SERVER] -&gt;	GET  http://localhost:1234/v1/models
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/responses
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/chat/completions
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/completions
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/embeddings
Server started.<h2>Etapa 2: Implante o Elastic local com o Docker</h2><p>Agora vamos configurar o Elasticsearch e o Kibana localmente usando o Docker. A Elastic fornece um script prático que lida com todo o processo de configuração. Para obter mais detalhes, consulte a <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart">documentação oficial</a>.</p><h3>Execute o script start-local</h3><p>Execute o seguinte comando no seu terminal:</p>curl -fsSL https://elastic.co/start-local | sh<p>Este script irá:</p><ul><li><p>Baixe e configure o Elasticsearch e o Kibana.</p></li><li><p>Inicie ambos os serviços usando o Docker Compose.</p></li><li><p>Ative automaticamente uma licença de avaliação Platinum de 30 dias.</p></li></ul><h3>Resultado esperado</h3><p>Aguarde a seguinte mensagem e salve a senha e a chave da API exibidas; você precisará delas para acessar o Kibana:</p>🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!
🌐 Open your browser at http://localhost:5601
   Username: elastic
   Password: KSUlOMNr
🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: cnJGX0pwb0JhOG00cmNJVklUNXg6cnNJdXZWMnM4bncwMllpQlFlUTlWdw==
Learn more at https://github.com/elastic/start-local<h3>Acesse o Kibana</h3><p>Abra seu navegador e acesse:</p>http://localhost:5601<p>Faça login utilizando as credenciais obtidas na saída do terminal.</p><h3>Habilitar o Construtor de Agentes</h3><p>Após fazer login no Kibana, navegue até <strong>Gerenciamento </strong>&gt;<strong> IA </strong>&gt;<strong> Construtor de Agentes </strong>e ative o Construtor de Agentes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a934bd99fa6a0ce/6a170d046234e019c3db1a5a/92e104cb846c20d875865ded8a3d37f5c7daae9b-1491x1528.png" alt="" /><h2>Etapa 3: Crie o conector OpenAI no Elastic</h2><p>Agora vamos configurar o Elastic para usar seu LLM local.</p><h3>Conectores de acesso</h3><ol><li><p>Em Kibana</p></li><li><p>Acesse <strong>Configurações do projeto</strong> &gt; <strong>Gerenciamento</strong></p></li><li><p>Em <strong>Alertas e insights</strong>, selecione <strong>Conectores.</strong></p></li><li><p>Clique em Criar conector</p></li></ol><h3>Configure o conector</h3><p>Selecione <strong>OpenAI</strong> na lista de conectores. O LM Studio utiliza o SDK da OpenAI, o que o torna compatível.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt762023c39781eb78/6a170d06a29299a59ed01087/5ac87042e086c7a2bd47a8039e646ec831f0dcc6-923x974.png" alt="" /><p>Preencha os campos com estes valores:</p><ul><li><p><strong>Nome do conector: </strong>LM Studio - GPT-OSS 20B</p></li><li><p><strong>Selecione um provedor OpenAI: </strong>Outro (Serviço compatível com OpenAI)</p></li><li><p><strong>URL: </strong><code>http://host.docker.internal:1234/v1/chat/completions</code></p></li><li><p><strong>Modelo padrão: </strong>openai/gpt-oss-20b</p></li><li><p><strong>Chave da API:</strong> testkey-123 (qualquer texto funciona, pois o LM Studio Server não requer autenticação).</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt980e595f80e2be2e/6a170d086f7f0468a19148cc/2084ac32fcf1fb810c8b54ecab1c85a1e3e8905b-672x1302.png" alt="" /><p>Para finalizar a configuração, clique em <strong>Salvar e testar</strong>.</p><p><strong>Importante:</strong> Ative a opção “<strong>Habilitar chamada de função nativa</strong>”; isso é necessário para que o Construtor de Agentes funcione corretamente. Se você não habilitar isso, você receberá um erro <strong><code>No tool calls found in the response</code></strong> .</p><h3>Teste a conexão</h3><p>O Elastic deve testar a conexão automaticamente. Se tudo estiver configurado corretamente, você verá uma mensagem de sucesso como esta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4d2e815dd558f881/6a170d090e2e49076541a177/f567d767f1969c4730c1daa92f651789dc3742ac-1042x812.png" alt="" /><p>Resposta.</p>{
  "status": "ok",
  "data": {
    "id": "chatcmpl-flj9h0hy4wcx4bfson00an",
    "object": "chat.completion",
    "created": 1761189456,
    "model": "openai/gpt-oss-20b",
    "choices": [
      {
        "index": 0,
        "message": {
          "role": "assistant",
          "content": "Hello! 👋 How can I assist you today?",
          "reasoning": "Just greet.",
          "tool_calls": []
        },
        "logprobs": null,
        "finish_reason": "stop"
      }
    ],
    "usage": {
      "prompt_tokens": 69,
      "completion_tokens": 23,
      "total_tokens": 92
    },
    "stats": {},
    "system_fingerprint": "openai/gpt-oss-20b"
  },
  "actionId": "ee1c3aaf-bad0-4ada-8149-118f52dad757"
}<h2>Etapa 4: Carregar os dados dos funcionários no Elasticsearch</h2><p>Agora vamos carregar o <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/gpt-oss-with-elasticsearch/hr-employees-bulk.json">conjunto de dados de funcionários de RH</a> para demonstrar como o agente trabalha com dados confidenciais. Eu gerei um conjunto de dados fictício com essa estrutura.</p><h3>Estrutura do conjunto de dados</h3>{
  "employee_id": "0f4dce68-2a09-4cb1-b2af-6bcb4821539b",
  "full_name": "Daffi Stiebler",
  "email": "lscutchings0@huffingtonpost.com",
  "date_of_birth": "1975-06-20T15:39:36Z",
  "hire_date": "2025-07-28T00:10:45Z",
  "job_title": "Physical Therapy Assistant",
  "department": "HR",
  "salary": "108455",
  "performance_rating": "Needs Improvement",
  "years_of_experience": 2,
  "skills": "Java",
  "education_level": "Master's Degree",
  "manager": "Carl MacGibbon",
  "emergency_contact": "Leigha Scutchings",
  "home_address": "5571 6th Park"
}<h3>Criar o índice com mapeamentos</h3><p>Primeiro, crie o índice com os mapeamentos adequados. Observe que estamos usando campos <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text">semantic_text</a> para alguns campos-chave; isso possibilita recursos de busca semântica em nosso índice.</p>​​PUT hr-employees
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "employee_id": {
        "type": "keyword"
      },
      "full_name": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "email": {
        "type": "keyword"
      },
      "date_of_birth": {
        "type": "date",
        "format": "iso8601"
      },
      "hire_date": {
        "type": "date",
        "format": "iso8601"
      },
      "job_title": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "department": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "salary": {
        "type": "double"
      },
      "performance_rating": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "years_of_experience": {
        "type": "long"
      },
      "skills": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "education_level": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "manager": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "emergency_contact": {
        "type": "keyword"
      },
      "home_address": {
        "type": "keyword"
      },
      "employee_semantic": {
        "type": "semantic_text"
      }
    }
  }
}<h3>Indexar com API em lote</h3><p>Copie e cole o <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/gpt-oss-with-elasticsearch/hr-employees-bulk.json">conjunto de dados</a> nas suas Ferramentas de Desenvolvedor no Kibana e execute-o:</p>POST hr-employees/_bulk
{"index": {}}
{"employee_id": "57728b91-e5d7-4fa8-954a-2384040d3886", "full_name": "Filide Gane", "email": "vhallahan1@booking.com", "job_title": "Business Systems Development Analyst", "department": "Marketing", "salary": "$52330.27", "performance_rating": "Meets Expectations", "years_of_experience": 12, "skills": "Java", "education_level": "Bachelor's Degree", "date_of_birth": "2000-02-07T16:49:32Z", "hire_date": "2023-11-07T13:03:16Z", "manager": "Freedman Kings", "emergency_contact": "Vilhelmina Hallahan", "home_address": "75 Dennis Junction"}
{"index": {}}
{"employee_id": "...", ...}<h3>Verifique os dados</h3><p>Execute uma consulta para verificar:</p>GET hr-employees/_search<h2>Etapa 5: Crie e teste seu agente de IA</h2><p>Com tudo configurado, é hora de criar um agente de IA personalizado usando o Elastic Agent Builder. Para obter mais detalhes, consulte a <a href="https://www.elastic.co/docs/solutions/search/agent-builder/get-started">documentação da Elastic</a>.</p><h3>Adicione o conector</h3><p>Antes de podermos criar nosso novo agente, precisamos configurar nosso construtor de agentes para usar nosso conector personalizado chamado <code>LM Studio - GPT-OSS 20B</code> , porque o padrão é o <a href="https://www.elastic.co/docs/reference/kibana/connectors-kibana/elastic-managed-llm">Elastic Managed LLM</a>. Para isso, precisamos acessar <strong>Configurações do Projeto</strong> &gt; <strong>Gerenciamento</strong> &gt; <strong>Configurações do GenAI</strong>; agora selecionamos a que criamos e clicamos em <strong>Salvar</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc42f079c5e756057/6a170d0acf4f2501d9b2d1c7/11e830c3e2fb4c298b020c928fa5422f3397ba08-1600x1152.png" alt="" /><h3>Construtor de Agentes de Acesso</h3><ol><li><p>Acesse a seção de <strong>Agentes.</strong></p></li><li><p>Clique em <strong>Criar um novo agente</strong></p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb8e734817c5a7c6a/6a170d0ca929cf867cae0a34/c1e60541563650163f972ac9088dc1ed1de759a7-1600x1054.png" alt="" /><h3>Configure o agente</h3><p>Para criar um novo agente, os campos obrigatórios são o <strong>ID do Agente</strong>, <strong>o Nome de Exibição</strong> e <strong>as Instruções de Exibição</strong>.</p><p>Mas existem mais opções de personalização, como as Instruções Personalizadas, que orientam o comportamento do seu agente e a forma como ele interagirá com as suas ferramentas, de forma semelhante a um prompt do sistema, mas para o nosso agente personalizado. As etiquetas ajudam a organizar seus agentes, a cor do avatar e o símbolo do avatar.</p><p>Os agentes que escolhi para o nosso agente, com base no conjunto de dados, são:

<strong>ID do agente:</strong> <code>hr_assistant</code></p><p><strong>Instruções personalizadas:</strong></p>You are an HR Analytics Assistant that helps answer questions about employee data.
When responding to queries:
- Provide clear, concise answers
- Include relevant employee details (name, department, salary, skills)
- Format monetary values with currency symbols
- Be professional and maintain data confidentiality<p>
Rótulos: <code>Human Resources</code> e <code>GPT-OSS</code></p><p>Nome de exibição: <code>HR Analytics Assistant</code></p><p>Descrição da tela:</p>A specialized AI assistant for Human Resources that helps analyze employee data, compensation, performance metrics, and talent management. Ask questions about employees, departments, salaries, or performance analytics.<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt23fb011e5b4f4d49/6a170d0e7d8d67f47a70e77f/f94bb2bf08497e5e756ca76b30a3a51f42927756-1424x1217.png" alt="" /><p>Com todos os dados inseridos, podemos clicar em <strong>Salvar</strong> nosso novo agente.</p><h3>Teste o agente</h3><p>Agora você pode fazer perguntas em linguagem natural sobre os dados de seus funcionários, e o GPT-OSS 20B entenderá a intenção e gerará uma resposta apropriada.</p><h4>Incitar:</h4>Which employee is the one with the highest salary in the hr-employees index?<h4>Responder:</h4><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc0c52faacf63b583/6a170d0f0e2e497bfd41a17b/94ad19f80b96304028a59f60beca51dfc9aecc8a-899x631.png" alt="" /><p>O processo do Agente foi o seguinte:</p><p>1. Compreenda sua pergunta usando o conector GPT-OSS.</p><p>2. Gere a consulta Elasticsearch apropriada (usando as ferramentas integradas ou <a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL</a> personalizado).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte32a8a7e6363c7f2/6a170d115091680077e1bb44/6f2961d0d1b97475f6dda300acee84da540938e6-844x466.png" alt="" /><p>3. Recuperar registros de funcionários correspondentes</p><p>4. Apresentar os resultados em linguagem natural com formatação adequada.</p><p>Diferentemente da busca lexical tradicional, o agente baseado em GPT-OSS entende a intenção e o contexto, facilitando a localização de informações sem a necessidade de conhecer os nomes exatos dos campos ou a sintaxe da consulta. Para obter mais detalhes sobre o processo de pensamento do agente, consulte este <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance">artigo</a>.</p><h2>Conclusão</h2><p>Neste artigo, criamos um agente de IA personalizado usando o Agent Builder da Elastic para conectar-se ao modelo GPT-OSS da OpenAI em execução localmente. Ao implantar o Elastic e o LLM em sua máquina local, essa arquitetura permite que você aproveite os recursos de IA generativa, mantendo o controle total sobre seus dados, tudo isso sem enviar informações para serviços externos.</p><p>Utilizamos o GPT-OSS 20B como experimento, mas os modelos oficialmente recomendados para o Elastic Agent Builder podem ser consultados <a href="https://www.elastic.co/docs/solutions/search/agent-builder/models#recommended-models">aqui</a>. Se você precisar de recursos de raciocínio mais avançados, existe também a <a href="https://huggingface.co/openai/gpt-oss-120b">variante com 120 parâmetros</a> , que apresenta melhor desempenho em cenários complexos, embora exija uma máquina com especificações mais altas para ser executada localmente. Para obter mais detalhes, consulte a <a href="https://openai.com/open-models/">documentação oficial da OpenAI</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-an-ai-agent-hr-elastic-agent-builder-gpt-oss</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-an-ai-agent-hr-elastic-agent-builder-gpt-oss</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Tomás Murúa]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt664f490053e46e6b/6a170d13b0367d2d7e72bd84/05d2d0513fff67d975f9223d75108aa9f50646bc-1600x914.png" length="0" type="image/png"/>
    <pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Principais projetos e aprendizados do Elastic Agent Builder do Cal Hacks 12.0]]></title>
    <description><![CDATA[Explore os principais projetos do Elastic Agent Builder do Cal Hacks 12.0 e mergulhe em nossos insights técnicos sobre arquiteturas Serverless, ES|QL e agentes.]]></description>
    <content:encoded><![CDATA[<p>Há algumas semanas, tivemos a incrível oportunidade de patrocinar <a href="https://cal-hacks-12-0.devpost.com/">o Cal Hacks 12.0</a>, um dos maiores hackathons presenciais, com mais de 2.000 participantes vindos de todo o mundo. Oferecemos uma categoria de prêmios dedicada ao melhor uso do Elastic Agent Builder em Serverless, e a resposta foi fenomenal. Em apenas 36 horas, recebemos 29 projetos que utilizaram o Agent Builder de maneiras criativas, desde a criação de ferramentas de inteligência contra incêndios florestais até validadores do StackOverflow.</p><p>Além dos projetos impressionantes, a experiência no Cal Hacks 12.0 também nos proporcionou algo igualmente valioso: feedback rápido e direto de desenvolvedores que estavam tendo contato com nossa Stack pela primeira vez. Hackathons são testes de pressão únicos, com prazos apertados, zero familiaridade prévia e obstáculos imprevisíveis (como as infames quedas de Wi-Fi). Eles revelam exatamente onde a experiência do desenvolvedor se destaca e onde ainda precisa ser aprimorada. Isso é ainda mais importante agora, à medida que os desenvolvedores interagem com o Elastic Stack de novas maneiras, cada vez mais por meio de fluxos de trabalho orientados por LLM. Neste post do blog, vamos explorar mais a fundo o que os participantes criaram com o Agent Builder e o que aprendemos durante o processo.</p><h2>Os projetos vencedores</h2><h3>Primeiro lugar: AgentOverflow</h3><p>Stack Overflow reconstruído para a era do LLM e dos agentes.</p><p>Leia mais sobre AgentOverflow <a href="https://devpost.com/software/agentoverflow">aqui</a>.</p><p>O AgentOverflow resolve um problema que a maioria dos desenvolvedores de IA enfrenta: os LLMs (Learning Learning Machines) têm alucinações, o histórico de bate-papo desaparece e os desenvolvedores perdem tempo resolvendo os mesmos problemas repetidamente.</p><p>O AgentOverflow captura, valida e reapresenta pares reais de problema-solução, para que os desenvolvedores possam quebrar o ciclo de ilusão e lançar produtos mais rapidamente.</p><h4>Como funciona:</h4><p><strong>1. Compartilhar JSON - o "Esquema da Solução".</strong></p><p>Um clique em um compartilhamento do Claude irá coletar, extrair e montar um JSON de Solução de Compartilhamento, que é um formato estruturado contendo:</p><ul><li><p>Problema</p></li><li><p>Contexto</p></li><li><p>Código</p></li><li><p>Tags</p></li><li><p>Etapas da solução verificadas.</p></li></ul><p>Um validador (LAVA) verifica e impõe a estrutura; o usuário adiciona uma linha de contexto extra, que então é armazenada e indexada no Elasticsearch.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte7bc35b6d54921e8/6a17f0176df73162760a0fe6/45a3e96f4474050a855419628c2a7338bb12c706-1600x877.png" alt="Clicar em “Compartilhar solução” coletará os dados da sessão atual juntamente com os metadados relevantes." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9967f52007fff99e/6a17f019ec0f8987c45a6701/2d65cb154d8ee32fc96ff17dfa5b0bf2636e3777-1600x1002.png" alt="Os usuários fornecem contexto adicional por meio da interface web, e o JSON é então indexado no Elasticsearch." /><p><strong>2. Encontre a solução</strong></p><p>Quando você ficar preso, clique em <code>Find Solution</code> e o AgentOverflow irá extrair informações da sua conversa atual, usá-las para construir uma consulta e executar uma pesquisa híbrida no Elasticsearch para exibir os resultados:</p><ul><li><p>Correções classificadas e validadas pela comunidade</p></li><li><p>As mesmas instruções que originalmente resolveram o problema.</p></li></ul><p>Isso permite que os desenvolvedores copiem, colem e desbloqueiem sua sessão atual rapidamente.</p><p><strong>3. MCP - Injeção de contexto para LLMs</strong></p><p>Ao conectar-se às soluções estruturadas armazenadas no Elasticsearch por meio do MCP (Model Context Protocol), os LLMs recebem um contexto de alta qualidade (código, logs, configurações, correções anteriores) em tempo de execução, sem ruído adicional.</p><p>O AgentOverflow utiliza o Agent Builder com o Elasticsearch como uma camada de memória estruturada que injeta contexto relevante nos LLMs. Isso os transforma de chatbots passivos em solucionadores de problemas sensíveis ao contexto.</p><h3>Segundo lugar: MarketMind</h3><p>Uma visão interpretável e em tempo real da energia de mercado, alimentada por seis Agentes Elásticos.</p><p>Leia mais sobre a MarketMind <a href="https://devpost.com/software/marketmind-b6cy2q">aqui</a>.</p><p>A MarketMind conquistou seu espaço ao oferecer aos traders iniciantes uma plataforma que converte dados de mercado fragmentados em sinais claros e em tempo real. Em vez de lidar com a ação do preço, os fundamentos, o sentimento e a volatilidade em diferentes ferramentas, o MarketMind consolida todas essas informações em uma única plataforma, ajudando os traders a obter insights acionáveis. Este projeto também utilizou algumas consultas ES|QL complexas na construção de seus agentes.</p><h4>Como funciona:</h4><p><strong>1. Coletar dados de mercado em tempo real</strong></p><p>O MarketMind extrai métricas de ação de preço, fundamentos, sentimento, volatilidade e risco do Yahoo Finance. Esses dados são ingeridos e organizados em múltiplos índices do Elasticsearch.</p><p><strong>2. Seis agentes especializados analisam o mercado.</strong></p><p>Cada agente, criado com o Agent Builder, concentra-se em uma camada diferente do mercado. Eles leem dados de um índice do Elasticsearch, calculam suas próprias métricas específicas do domínio e geram uma saída JSON padronizada com pontuações e justificativas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4ba582f9872b65b/6a17f01b7f6f15c2d8c09c1c/7d9716cca06a047a2b3584378b5c7e592a785ba1-1284x878.png" alt="6 agentes de IA especializados do GOOGL que analisam o mercado" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd86ed3bfe4b8bd2b/6a17f01c5ea30f868164b6ba/5aac6a833347c0d2e596c02049ec4b4d3aae5cd7-794x764.png" alt="Capacidades de análise de anomalias de volume e detecção de catástrofes dos agentes especializados do GOOGL." /><p><strong>3. Agregar sinais em um modelo unificado de “energia de mercado”</strong></p><p>Os resultados combinados aparecem como pulsos brilhantes ao redor de cada ação, ilustrando se o ímpeto está aumentando, o risco está crescendo ou o sentimento está mudando.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5af7c7c838308275/6a17f01e42022917b629f6ca/46b3da8e3d528c5dd4e2829416c5446098acb3aa-744x718.png" alt="Modelo unificado de “energia de mercado” de agentes especializados do GOOGL" /><p><strong>4. Visualize insights</strong></p><p>A interface foi desenvolvida com React e <a href="https://github.com/vercel/next.js">Next.js</a>, utilizando TypeScript, recursos visuais baseados em física SVG e <a href="https://github.com/chartjs">Chart.js</a> para gráficos de velas em tempo real. Isso transforma análises brutas em feedback acionável em tempo real.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt775e1880aa7afacc/6a17f01f1d1b83ce1f93e528/3f000c043117b77ed4127202be5a49c12e3682ba-1600x930.png" alt="Como visualizar insights da análise de agentes especializados do GOOGL" /><h2>Outros projetos interessantes:</h2><p>Aqui estão alguns outros fortes concorrentes que usaram o Elastic em diferentes partes de sua infraestrutura:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltffe292009e446a70/6a17f0216df731068c0a0fea/76c49a853426844f475cd6b2a74999e60af20e8c-926x1080.png" alt="" /><p>Encontre <a href="https://cal-hacks-12-0.devpost.com/submissions/search?utf8=%E2%9C%93&amp;prize_filter%5Bprizes%5D%5B%5D=91882">aqui</a> a lista completa dos projetos submetidos à nossa trilha.</p><h2>O que aprendemos com os desenvolvedores</h2><ul><li><p><strong>O Construtor de Agentes é fácil de usar:</strong></p></li></ul><p>A maioria das equipes nunca havia usado o Elastic antes e, mesmo assim, conseguiu criar agentes rapidamente com pouco suporte. Realizamos um workshop para aqueles que precisavam de mais orientação, mas a maioria conseguiu importar seus dados e construir um agente para executar ações com base nesses dados.</p><ul><li><p><strong>Os LLMs se destacam em </strong>consultas<strong><code>kNN</code></strong><strong>, mas ainda precisam de orientação na geração de ES|QL:</strong></p></li></ul><p>Ao solicitar que o ChatGPT-5 gerasse consultas ES|QL, foram retornadas informações incorretas, frequentemente misturando ES|QL e SQL. Fornecer os documentos ao LLM em um arquivo Markdown pareceu ser uma solução viável.</p><ul><li><p><strong>Funções ES|QL exclusivas de snapshots vazaram para a documentação:</strong></p></li></ul><p>As próximas funções de agregação <code>FIRST</code> e <code>LAST</code> foram acidentalmente incluídas em nossa documentação ES|QL. Como fornecemos esses documentos ao ChatGPT, o modelo usou essas funções corretamente, mesmo que elas ainda não estejam disponíveis no Serverless. Graças ao feedback do grupo, a equipe de engenharia rapidamente abriu e incorporou uma correção para remover as funções da documentação publicada (<a href="https://github.com/elastic/elasticsearch/pull/137341">PR #137341</a>).</p><ul><li><p><strong>Ausência de orientações específicas para Serverless:</strong></p></li></ul><p>Uma equipe tentou habilitar <code>LOOKUP JOIN</code> em um índice que não foi criado no modo de pesquisa. A mensagem de erro os levou a seguir comandos que não existem no Serverless. Repassamos isso para a equipe de produto, que imediatamente abriu uma solicitação de correção para uma mensagem acionável específica para Serverless. A longo prazo, a visão é ocultar completamente a complexidade da reindexação (<a href="https://github.com/elastic/elasticsearch-serverless/issues/4838">Problema nº 4838</a>).</p><ul><li><p><strong>Valor dos eventos presenciais:</strong></p></li></ul><p>Hackathons online são ótimos, mas nada se compara ao feedback rápido que você obtém ao depurar código lado a lado com os desenvolvedores. Acompanhamos as equipes integrando o Agent Builder em diferentes casos de uso, identificamos pontos em que a experiência do desenvolvedor com ES|QL poderia ser aprimorada e corrigimos problemas muito mais rapidamente do que se tivéssemos tentado fazê-lo por meio de canais assíncronos.</p><h2>Conclusão</h2><p>O Cal Hacks 12.0 nos proporcionou mais do que um fim de semana repleto de demonstrações incríveis; também nos deu uma visão de como os novos desenvolvedores estão interagindo com o Elastic Stack. Em apenas 36 horas, vimos equipes começarem a usar o Agent Builder, ingerir dados no Elasticsearch, projetar sistemas multiagentes e testar nossos recursos de diversas maneiras. O evento também nos lembrou por que os eventos presenciais são importantes. Os ciclos de feedback rápidos, as conversas reais e a depuração prática nos ajudaram a entender as necessidades atuais dos desenvolvedores. Estamos entusiasmados em trazer de volta para a equipe de engenharia o que aprendemos. Nos vemos no próximo hackathon.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-projects-learnings-cal-hacks-12-0</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-projects-learnings-cal-hacks-12-0</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0f079179be9832d4/6a17f023631730a69c585b6d/8ba034a6f19b50521f541b8131756a8acdb52975-1280x960.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando uma sala de imprensa para agentes LLM com protocolo A2A e MCP no Elasticsearch: Parte II]]></title>
    <description><![CDATA[Descubra como construir uma redação especializada para agentes LLM em um ambiente híbrido, utilizando o protocolo A2A para colaboração entre agentes e o MCP para acesso a ferramentas no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<h2>A2A e MCP: o código em ação</h2><p>Este artigo é um complemento ao artigo "Criando uma sala de imprensa com o agente LLM usando os protocolos A2A e MCP no Elasticsearch!", que explicou os benefícios de implementar as arquiteturas A2A e MCP no mesmo agente para aproveitar ao máximo as vantagens exclusivas de ambas as estruturas. Um <a href="https://github.com/justincastilla/elastic-newsroom">repositório</a> está disponível caso você queira executar a demonstração por conta própria.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt232e466d2153c764/6a17f15f631730042d585b8d/7196f004089127f83547b2e5dc3f663205cfcdce-1162x1600.png" alt="Fluxo de trabalho do agente de protocolo A2A e MCP" /><p>Vamos analisar como nossos agentes de redação colaboram usando tanto o A2A quanto o MCP para produzir um artigo jornalístico. O repositório que acompanha o projeto, onde é possível ver os agentes em ação, pode ser encontrado <a href="https://github.com/justincastilla/elastic-newsroom">aqui</a>.</p><h3>Etapa 1: Atribuição da história</h3><p>O <strong>chefe de jornalismo</strong> (atuando como cliente) designa uma pauta:</p>{
  "message_type": "task_request",
  "sender": "news_chief",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "assignment": {
      "topic": "Renewable Energy Adoption in Europe",
      "angle": "Policy changes driving solar and wind expansion",
      "target_length": 1200,
      "deadline": "2025-09-30T18:00:00Z"
    }
  }
}<h3>Etapa 2: O repórter solicita pesquisa.</h3><p>O <strong>Agente Repórter</strong> reconhece que precisa de informações básicas e delega essa tarefa ao <strong>Agente Pesquisador</strong> por meio do método A2A:</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "fact_gathering",
    "parameters": {
      "queries": [
        "EU renewable energy capacity 2024",
        "Solar installations growth Europe",
        "Wind energy policy changes 2024"
      ],
      "depth": "comprehensive"
    }
  }
}<h3>Etapa 3: O repórter solicita contexto histórico ao Agente de Arquivo.</h3><p>O <strong>agente repórter</strong> reconhece que o contexto histórico fortaleceria a matéria. Ele delega ao <strong>Agente de Arquivo</strong> (com <a href="https://www.elastic.co/docs/solutions/search/elastic-agent-builder">tecnologia A2A do Elastic</a>) via A2A a busca no arquivo de artigos da sala de notícias, que utiliza o Elasticsearch:</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "archive_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "search_archive",
    "parameters": {
      "query": "European renewable energy policy changes and adoption trends over past 5 years",
      "focus_areas": ["solar", "wind", "policy", "Germany", "France"],
      "time_range": "2019-2024",
      "result_count": 10
    }
  }
}<h3>Etapa 4: O Agente de Arquivamento usa o Agente A2A Elástico com MCP</h3><p>O <strong>Agente de Arquivamento</strong> utiliza o Agente A2A da Elastic, que por sua vez usa o MCP para acessar as ferramentas do Elasticsearch. Isso demonstra a arquitetura híbrida onde o A2A permite a colaboração entre agentes enquanto o MCP fornece acesso às ferramentas:</p># Archive Agent using Elastic A2A Agent
async def search_historical_articles(self, query_params):
    # The Archive Agent sends a request to Elastic's A2A Agent
    elastic_response = await self.a2a_client.send_request(
        agent="elastic_agent",
        capability="search_and_analyze",
        parameters={
            "natural_language_query": query_params["query"],
            "index_pattern": "newsroom-articles-*",
            "filters": {
                "topics": query_params["focus_areas"],
                "date_range": query_params["time_range"]
            },
            "analysis_type": "trend_analysis"
        }
    )
    
    # Elastic's A2A Agent internally uses MCP tools:
    # - platform.core.search (to find relevant articles)
    # - platform.core.generate_esql (to analyze trends)
    # - platform.core.index_explorer (to identify relevant indices)
    
    return elastic_response<p>O <strong>Agente de Arquivamento</strong> recebe dados históricos abrangentes do Agente A2A da Elastic e os retorna ao Reporter:</p>{
  "message_type": "task_response",
  "sender": "archive_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "status": "completed",
    "archive_data": {
      "historical_articles": [
        {
          "title": "Germany's Energiewende: Five Years of Solar Growth",
          "published": "2022-06-15",
          "key_points": [
            "Germany added 7 GW annually 2020-2022",
            "Policy subsidies drove 60% of growth"
          ],
          "relevance_score": 0.94
        },
        {
          "title": "France Balances Nuclear and Renewables",
          "published": "2023-03-20",
          "key_points": [
            "France increased renewable target to 40% by 2030",
            "Solar capacity doubled 2021-2023"
          ],
          "relevance_score": 0.89
        }
      ],
      "trend_analysis": {
        "coverage_frequency": "EU renewable stories increased 150% since 2019",
        "emerging_themes": ["policy incentives", "grid modernization", "battery storage"],
        "coverage_gaps": ["Small member states", "offshore wind permitting"]
      },
      "total_articles_found": 47,
      "search_confidence": 0.91
    }
  }
}<p>Esta etapa demonstra como o agente A2A da Elastic se integra ao fluxo de trabalho da redação. O Agente de Arquivo (um agente específico para redações) trabalha em conjunto com o Agente A2A da Elastic (um especialista terceirizado) para aproveitar os poderosos recursos de busca e análise do Elasticsearch. O agente da Elastic usa o MCP internamente para acessar as ferramentas do Elasticsearch, demonstrando a clara separação entre a coordenação do agente (A2A) e o acesso às ferramentas (MCP).</p><h3>Etapa 5: O pesquisador utiliza servidores MCP</h3><p>O <strong>Agente Pesquisador</strong> acessa vários servidores MCP para coletar informações:</p># Researcher Agent using MCP to access tools
async def gather_facts(self, queries):
    results = []
    
    # Use News API MCP Server
    news_data = await self.mcp_client.invoke_tool(
        server="news_api_mcp",
        tool="search_articles",
        parameters={
            "query": queries[0],
            "date_range": "2024-01-01 to 2024-09-30",
            "sources": ["reuters", "bloomberg", "euractiv"]
        }
    )
    
    # Use Statistics MCP Server
    stats_data = await self.mcp_client.invoke_tool(
        server="eurostat_mcp",
        tool="get_energy_statistics",
        parameters={
            "metrics": ["solar_capacity_mw", "wind_capacity_mw"],
            "countries": ["EU27"],
            "year": 2024
        }
    )
    
    # Use Fact-Checking MCP Server
    verified_facts = await self.mcp_client.invoke_tool(
        server="factcheck_mcp",
        tool="verify_claims",
        parameters={
            "claims": [
                "EU solar capacity increased 40% in 2024",
                "Germany leads in wind installations"
            ]
        }
    )
    
    return self._synthesize_research(news_data, stats_data, verified_facts)<h3>Etapa 6: O pesquisador devolve os dados ao repórter.</h3><p>O <strong>Agente de Pesquisa</strong> envia uma pesquisa completa de volta via A2A:</p>{
  "message_type": "task_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "status": "completed",
    "research_data": {
      "key_facts": [
        {
          "claim": "EU solar capacity reached 260 GW in 2024",
          "source": "Eurostat Q3 2024 Report",
          "confidence": 0.95,
          "verified": true
        },
        {
          "claim": "Germany installed 12 GW of wind capacity in 2024",
          "source": "German Federal Network Agency",
          "confidence": 0.92,
          "verified": true
        }
      ],
      "statistics": {
        "solar_growth_rate": "35%",
        "wind_growth_rate": "28%"
      },
      "sources_count": 15
    }
  }
}<h3>Etapa 7: O repórter escreve o artigo</h3><p>O <strong>Repórter Agente</strong> utiliza os dados da pesquisa e suas próprias capacidades de mestrado em Direito (LLM) para redigir o artigo. Durante a escrita, o Repórter utiliza os servidores MCP para estilo e modelos:</p># Reporter Agent writing with MCP assistance
async def write_article(self, research_data, assignment):
    # Get style guidelines via MCP
    style_guide = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="style://editorial/ap_style_guide"
    )
    
    # Get article template via MCP
    template = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="template://articles/news_story"
    )
    
    # Generate article using LLM + research + style
    draft = await self.llm.generate(
        prompt=f"""
        Write a news article following these guidelines:
        {style_guide}
        
        Using this template:
        {template}
        
        Based on this research:
        {research_data}
        
        Assignment: {assignment}
        """
    )
    
    # Self-evaluate confidence in claims
    confidence_check = await self._evaluate_confidence(draft)
    
    return draft, confidence_check<h3>Etapa 8: baixa confiança desencadeia nova pesquisa</h3><p>O <strong>agente repórter</strong> avalia sua versão preliminar e constata que uma das afirmações apresenta baixo nível de confiança. Envia outra solicitação ao <strong>Agente Pesquisador</strong>:</p>{
  "message_type": "collaboration_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "request_type": "fact_verification",
    "claims": [
      {
        "text": "France's nuclear phase-down contributed to 15% increase in renewable capacity",
        "context": "Discussing policy drivers for renewable growth",
        "current_confidence": 0.45,
        "required_confidence": 0.80
      }
    ],
    "urgency": "high"
  }
}<p>O <strong>pesquisador</strong> verifica a alegação usando servidores de checagem de fatos do MCP e retorna informações atualizadas:</p>{
  "message_type": "collaboration_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "verified_claims": [
      {
        "original_claim": "France's nuclear phase-down contributed to 15% increase...",
        "verified_claim": "France's renewable capacity increased 18% in 2024, partially offsetting reduced nuclear output",
        "confidence": 0.88,
        "corrections": "Percentage was 18%, not 15%; nuclear phase-down is gradual, not primary driver",
        "sources": ["RTE France", "French Energy Ministry Report 2024"]
      }
    ]
  }
}<h3>Etapa 9: O repórter revisa e envia ao editor.</h3><p>O <strong>repórter</strong> incorpora os fatos verificados e envia a versão finalizada ao <strong>editor</strong> por meio do sistema A2A:</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "editor_agent",
  "payload": {
    "task_id": "edit_renewable_story",
    "parent_task_id": "story_renewable_energy_2024",
    "content": {
      "headline": "Europe's Renewable Revolution: Solar and Wind Surge 30% in 2024",
      "body": "[Full article text...]",
      "word_count": 1185,
      "sources": [/* array of sources */]
    },
    "editing_requirements": {
      "check_style": true,
      "check_facts": true,
      "check_seo": true
    }
  }
}<h3>Etapa 10: Revisão do editor usando as ferramentas MCP</h3><p>O <strong>Agente de Edição</strong> utiliza vários servidores MCP para revisar o artigo:</p># Editor Agent using MCP for quality checks
async def review_article(self, content):
    # Grammar and style check
    grammar_issues = await self.mcp_client.invoke_tool(
        server="grammarly_mcp",
        tool="check_document",
        parameters={"text": content["body"]}
    )
    
    # SEO optimization check
    seo_analysis = await self.mcp_client.invoke_tool(
        server="seo_mcp",
        tool="analyze_content",
        parameters={
            "headline": content["headline"],
            "body": content["body"],
            "target_keywords": ["renewable energy", "Europe", "solar", "wind"]
        }
    )
    
    # Plagiarism check
    originality = await self.mcp_client.invoke_tool(
        server="plagiarism_mcp",
        tool="check_originality",
        parameters={"text": content["body"]}
    )
    
    # Generate editorial feedback
    feedback = await self._generate_feedback(
        grammar_issues, 
        seo_analysis, 
        originality
    )
    
    return feedback<p>O <strong>editor</strong> aprova o artigo e o encaminha:</p>{
  "message_type": "task_response",
  "sender": "editor_agent",
  "receiver": "reporter_agent",
  "payload": {
    "status": "approved",
    "quality_score": 9.2,
    "minor_edits": [
      "Changed 'surge' to 'increased' in paragraph 3 for AP style consistency",
      "Added Oxford comma in list of countries"
    ],
    "approved_content": "[Final edited article]"
  }
}<h3>Etapa 11: A editora publica via CI/CD</h3><p>Por fim, o <strong>Agente de Impressão</strong> publica o artigo aprovado usando os servidores MCP para o pipeline CMS e CI/CD:</p># Publisher Agent publishing via MCP
async def publish_article(self, content, metadata):
    # Upload to CMS via MCP
    cms_result = await self.mcp_client.invoke_tool(
        server="wordpress_mcp",
        tool="create_post",
        parameters={
            "title": content["headline"],
            "body": content["body"],
            "status": "draft",
            "categories": metadata["categories"],
            "tags": metadata["tags"],
            "featured_image_url": metadata["image_url"]
        }
    )
    
    post_id = cms_result["post_id"]
    
    # Trigger CI/CD deployment via MCP
    deploy_result = await self.mcp_client.invoke_tool(
        server="cicd_mcp",
        tool="trigger_deployment",
        parameters={
            "pipeline": "publish_article",
            "environment": "production",
            "post_id": post_id,
            "schedule": "immediate"
        }
    )
    
    # Track analytics
    await self.mcp_client.invoke_tool(
        server="analytics_mcp",
        tool="register_publication",
        parameters={
            "post_id": post_id,
            "publish_time": datetime.now().isoformat(),
            "story_id": metadata["story_id"]
        }
    )
    
    return {
        "status": "published",
        "post_id": post_id,
        "url": f"https://newsroom.example.com/articles/{post_id}",
        "deployment_id": deploy_result["deployment_id"]
    }<p>A <strong>editora</strong> confirma a publicação via A2A:</p>{
  "message_type": "task_complete",
  "sender": "printer_agent",
  "receiver": "news_chief",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "status": "published",
    "publication": {
      "url": "https://newsroom.example.com/articles/renewable-europe-2024",
      "published_at": "2025-09-30T17:45:00Z",
      "post_id": "12345"
    },
    "workflow_metrics": {
      "total_time_minutes": 45,
      "agents_involved": ["reporter", "researcher", "archive", "editor", "printer"],
      "iterations": 2,
      "mcp_calls": 12
    }
  }
}<p>Segue abaixo a sequência completa do fluxo de trabalho A2A no repositório anexo, utilizando os mesmos agentes descritos acima.</p><p>#</p><p>De</p><p>Para</p><p>Ação</p><p>Protocolo</p><p>Descrição</p><p>1</p><p>Usuário</p><p>Chefe de Notícias</p><p>Atribuir história</p><p>HTTP POST</p><p>O usuário envia o tema e o enfoque da matéria.</p><p>2</p><p>Chefe de Notícias</p><p>Interno</p><p>Criar história</p><p>-</p><p>Cria um registro de história com um ID exclusivo.</p><p>3</p><p>Chefe de Notícias</p><p>Repórter</p><p>Atribuição de Delegado</p><p>A2A</p><p>Envia a atribuição da matéria através do protocolo A2A</p><p>4</p><p>Repórter</p><p>Interno</p><p>Aceitar tarefa</p><p>-</p><p>Atribuição de estoques internamente</p><p>5</p><p>Repórter</p><p>Servidor MCP</p><p>Gerar esboço</p><p>MCP/HTTP</p><p>Cria o esboço do artigo e as perguntas de pesquisa.</p><p>6a</p><p>Repórter</p><p>Pesquisador</p><p>Solicitar pesquisa</p><p>A2A</p><p>Envia perguntas (paralelo com 6b)</p><p>6b</p><p>Repórter</p><p>Arquivista</p><p>Pesquisar no arquivo</p><p>A2A JSONRPC</p><p>Pesquisa artigos históricos (paralelo com 6a)</p><p>7</p><p>Pesquisador</p><p>Servidor MCP</p><p>Questões de pesquisa</p><p>MCP/HTTP</p><p>Utiliza a abordagem antropogênica via MCP para responder a perguntas.</p><p>8</p><p>Pesquisador</p><p>Repórter</p><p>Retornar à pesquisa</p><p>A2A</p><p>Devolve respostas de pesquisa</p><p>9</p><p>Arquivista</p><p>Elasticsearch</p><p>Índice de pesquisa</p><p>API REST do ES</p><p>Consultas ao índice news_archive</p><p>10</p><p>Arquivista</p><p>Repórter</p><p>Retornar ao arquivo</p><p>A2A JSONRPC</p><p>Retorna resultados de pesquisa históricos</p><p>11</p><p>Repórter</p><p>Servidor MCP</p><p>Gerar artigo</p><p>MCP/HTTP</p><p>Cria artigo com contexto de pesquisa/arquivo</p><p>12</p><p>Repórter</p><p>Interno</p><p>Rascunho da loja</p><p>-</p><p>Salva o rascunho internamente</p><p>13</p><p>Repórter</p><p>Chefe de Notícias</p><p>Enviar rascunho</p><p>A2A</p><p>Entrega a versão finalizada</p><p>14</p><p>Chefe de Notícias</p><p>Interno</p><p>Atualização da história</p><p>-</p><p>Armazena o rascunho e atualiza o status para "rascunho_enviado".</p><p>15</p><p>Chefe de Notícias</p><p>Editor</p><p>Revisão do rascunho</p><p>A2A</p><p>Encaminha automaticamente para o Editor para revisão.</p><p>16</p><p>Editor</p><p>Servidor MCP</p><p>Artigo de revisão</p><p>MCP/HTTP</p><p>Analisa conteúdo usando Anthropic via MCP.</p><p>17</p><p>Editor</p><p>Chefe de Notícias</p><p>Revisão de retorno</p><p>A2A</p><p>Envia comentários e sugestões editoriais.</p><p>18</p><p>Chefe de Notícias</p><p>Interno</p><p>Avaliação da loja</p><p>-</p><p>Feedback do editor de lojas</p><p>19</p><p>Chefe de Notícias</p><p>Repórter</p><p>Aplicar edições</p><p>A2A</p><p>Feedback da revisão de rotas para o repórter</p><p>20</p><p>Repórter</p><p>Servidor MCP</p><p>Aplicar edições</p><p>MCP/HTTP</p><p>Revisa o artigo com base no feedback.</p><p>21</p><p>Repórter</p><p>Interno</p><p>Rascunho atualizado</p><p>-</p><p>Atualiza a versão preliminar com revisões.</p><p>22</p><p>Repórter</p><p>Chefe de Notícias</p><p>Devolução revisada</p><p>A2A</p><p>Devolve artigo revisado</p><p>23</p><p>Chefe de Notícias</p><p>Interno</p><p>Atualização da história</p><p>-</p><p>Lojas revisaram a versão preliminar, status para "revisado"</p><p>24</p><p>Chefe de Notícias</p><p>Editor</p><p>Publicar artigo</p><p>A2A</p><p>Rotas automáticas para o editor</p><p>25</p><p>Editor</p><p>Servidor MCP</p><p>Gerar etiquetas</p><p>MCP/HTTP</p><p>Cria etiquetas e categorias</p><p>26</p><p>Editor</p><p>Elasticsearch</p><p>Artigo de índice</p><p>API REST do ES</p><p>Indexa o artigo ao índice news_archive</p><p>27</p><p>Editor</p><p>Sistema de arquivos</p><p>Salvar Markdown</p><p>Entrada/Saída de Arquivos</p><p>Salva o artigo como .md arquivo em /artigos</p><p>28</p><p>Editor</p><p>Chefe de Notícias</p><p>Confirmar publicação</p><p>A2A</p><p>Retorna o status de sucesso</p><p>29</p><p>Chefe de Notícias</p><p>Interno</p><p>Atualização da história</p><p>-</p><p>Atualiza o status da matéria para "publicada".</p><h2>Conclusão</h2><p>Tanto o A2A quanto o MCP desempenham papéis importantes no paradigma moderno de infraestrutura de LLM aumentada. A tecnologia A2A oferece flexibilidade para sistemas multiagentes complexos, mas potencialmente menor portabilidade e maior complexidade operacional. O MCP oferece uma abordagem padronizada para integração de ferramentas que é mais simples de implementar e manter, embora não seja projetado para lidar com orquestração multiagente.</p><p>A escolha não é binária. Conforme demonstrado em nosso exemplo de redação, os sistemas mais sofisticados e eficazes baseados em LLM geralmente combinam ambas as abordagens: os agentes se coordenam e se especializam por meio de protocolos A2A, enquanto acessam suas ferramentas e recursos por meio de servidores MCP. Essa arquitetura híbrida proporciona os benefícios organizacionais dos sistemas multiagentes, juntamente com a padronização e as vantagens do ecossistema do MCP. Isso sugere que talvez não seja necessário escolher: basta usar ambos como abordagem padrão.</p><p>Cabe a você, como desenvolvedor ou arquiteto, testar e determinar a melhor combinação de ambas as soluções para obter o resultado adequado ao seu caso de uso específico. Compreender os pontos fortes, as limitações e as aplicações adequadas de cada abordagem permitirá que você construa sistemas de IA mais eficazes, fáceis de manter e escaláveis.</p><p>Seja para criar uma redação digital, uma plataforma de atendimento ao cliente, um assistente de pesquisa ou qualquer outro aplicativo baseado em LLM, considerar cuidadosamente suas necessidades de coordenação (A2A) e requisitos de acesso às ferramentas (MCP) o colocará no caminho do sucesso.</p><h2>Recursos adicionais</h2><ul><li><p><strong>Construtor de Agentes do Elasticsearch: </strong><a href="https://www.elastic.co/docs/solutions/search/elastic-agent-builder">https://www.elastic.co/docs/solutions/search/elastic-agent-builder</a></p></li><li><p><strong>Especificação A2A</strong>: <a href="https://a2a-protocol.org/latest/specification/">https://a2a-protocol.org/latest/specification/</a></p></li><li><p><strong>Integração A2A e MCP</strong>: <a href="https://a2a-protocol.org/latest/topics/a2a-and-mcp/">https://a2a-protocol.org/latest/topics/a2a-and-mcp/</a></p></li><li><p><strong>Protocolo de Contexto do Modelo</strong>: <a href="https://modelcontextprotocol.io/">https://modelcontextprotocol.io</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-workflow-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-workflow-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Justin Castilla]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1b1f22cdc2130333/6a17f161ec0f8917fa5a6712/f87330e5d4ca961593b3cfb861ca850a4cc34186-1519x1173.png" length="0" type="image/png"/>
    <pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Você sabe, para contexto - Parte III: O poder da busca híbrida na engenharia de contexto]]></title>
    <description><![CDATA[Descubra como usar a engenharia de contexto e a busca híbrida para melhorar a precisão dos resultados da IA com agregações, RBAC e sinais não relacionados ao conteúdo.]]></description>
    <content:encoded><![CDATA[<p>Já discutimos a busca híbrida (<a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">Parte I</a>) e a engenharia de contexto (<a href="https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai">Parte II</a>); agora, vamos explorar como elas funcionam juntas para obter o máximo efeito no fornecimento de contexto direcionado para operações de RAG e IA agente.</p><h2>A busca não morreu, apenas mudou de lugar.</h2><p>Assim, tivemos essa mudança de uma abordagem que consistia principalmente em buscar contexto por meio de uma caixa de texto e usar as informações (o contexto) retornadas para construir as respostas nós mesmos, para agora usar a linguagem natural para dizer a um agente o que queremos e deixar que ele pesquise e compile automaticamente a resposta para nós. Muitos no mundo da tecnologia estão apontando para essa mudança e proclamando que "a busca está morta" (bem, o mundo do SEO e do AdWords está <a href="https://www.pewresearch.org/short-reads/2025/07/22/google-users-are-less-likely-to-click-on-links-when-an-ai-summary-appears-in-the-results/">definitivamente mudando</a>: alguém aí se lembra <a href="https://www.wired.com/story/goodbye-seo-hello-geo-brandlight-openai/">do GEO</a> ?), mas a busca ainda é absolutamente crucial para as operações de agentes — ela só é realizada, em grande parte, fora do campo de visão, por meio de ferramentas.</p><p>Anteriormente, os humanos eram os principais árbitros da relevância subjetiva: cada usuário tem seus próprios motivos para realizar a busca, e sua experiência pessoal influencia a precisão relativa dos resultados. Para confiarmos que os agentes podem chegar à mesma conclusão (ou melhor) que nós, precisamos garantir que as informações contextuais a que eles têm acesso sejam as mais próximas possíveis da nossa intenção subjetiva. Temos que estruturar o contexto que oferecemos aos mestrados em Direito (LLM) de forma a atingir esse objetivo!</p><h2>Geração de contexto com recuperação de pesquisa híbrida</h2><p>Só para relembrar, lá da Parte I, que a busca híbrida da Elastic combina os pontos fortes da busca tradicional baseada em palavras-chave (flexibilidade de sintaxe, precisão de palavras-chave e pontuação de relevância) com a compreensão semântica da busca por similaridade vetorial e oferece múltiplas técnicas de reclassificação. Essa sinergia (nunca se encontrou um uso mais preciso dessa palavra!) Permite resultados altamente relevantes, com consultas que podem ser muito mais específicas na forma como direcionam o conteúdo. Não se trata apenas de poder aplicar a relevância subjetiva como <em>uma</em> das etapas de recuperação; trata-se, na verdade, de que a recuperação na primeira etapa pode incluir a pontuação de relevância juntamente com todos os outros métodos simultaneamente.</p><h3>Precisão e eficiência superiores</h3><p>Utilizar uma plataforma de dados que possa fornecer busca, recuperação e reclassificação distribuídas como seu principal mecanismo de recuperação de contexto faz muito sentido. Você pode usar uma sintaxe de consulta avançada para adicionar o componente ausente da intenção subjetiva e filtrar o conteúdo que possa distrair ou obscurecer o valor das informações contextuais retornadas. Você pode selecionar qualquer uma das opções de sintaxe individuais disponíveis ou combinar modalidades em uma única pesquisa que visa cada tipo de dado da maneira que melhor o compreende e, em seguida, combiná-los/reordená-los com a reclassificação. Você pode filtrar a resposta para incluir apenas os campos/valores desejados, mantendo os dados irrelevantes afastados. Em termos de suporte aos agentes, essa flexibilidade de segmentação permite criar ferramentas extremamente precisas na forma como recuperam o contexto.</p><h3>Refinamento de contexto (agregações e sinais não relacionados ao conteúdo)</h3><p>As agregações podem ser especialmente úteis para moldar o conteúdo que uma ferramenta fornece à janela de contexto. As agregações fornecem naturalmente informações numéricas sobre o formato dos dados contextuais retornados, o que facilita e torna mais preciso o raciocínio dos Modelos de Aprendizagem Baseados em Leis (LLMs). Como as agregações podem ser hierarquicamente aninhadas, é uma maneira fácil de adicionar detalhes em vários níveis para o LLM, a fim de gerar uma compreensão mais matizada. As agregações também podem ajudar no gerenciamento do tamanho da janela de contexto — você pode facilmente reduzir o resultado de uma consulta de 100 mil documentos para algumas centenas de tokens de insights agregados.</p><p>Os sinais não relacionados ao conteúdo são os indicadores inerentes aos seus dados que fornecem uma visão mais ampla do que você está analisando; são as características adicionais dos resultados, como popularidade, atualidade, localização geográfica, categorias, diversidade de hospedagem ou faixas de preço. Essas informações podem ser úteis para orientar o agente na avaliação da importância do contexto recebido. Alguns exemplos simples podem ajudar a ilustrar isso melhor:</p><ul><li><p><strong>Impulsionando conteúdo popular e publicado recentemente</strong> - Imagine que você tenha uma base de conhecimento com artigos. Você deseja encontrar artigos relevantes para a consulta de um usuário, mas também quer priorizar artigos que sejam recentes e que tenham sido considerados úteis por outros usuários (por exemplo, que tenham um grande número de "curtidas"). Nesse cenário, podemos usar uma busca híbrida para encontrar artigos relevantes e, em seguida, reclassificá-los com base em uma combinação de sua data de publicação e popularidade.</p></li><li><p><strong>Busca em e-commerce com ajuste de vendas e estoque</strong> - Em um ambiente de e-commerce, você deseja mostrar aos clientes produtos que correspondam ao termo de busca, mas também promover produtos que estejam vendendo bem e disponíveis em estoque. Você também pode querer diminuir a classificação de produtos com baixo estoque para evitar a frustração do cliente.</p></li><li><p><strong>Priorizando problemas de alta gravidade em um sistema de rastreamento de bugs</strong> - Para uma equipe de desenvolvimento de software, ao procurar problemas, é crucial que os problemas de alta gravidade, alta prioridade e atualizados recentemente sejam exibidos primeiro. Você pode usar indicadores não-sinais, como "criticidade" e "mais discutido", para ponderar diferentes fatores de forma independente, garantindo que as questões mais críticas e ativamente discutidas cheguem ao topo.</p></li></ul><p>Essas consultas de exemplo e outras podem ser encontradas na <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/you-know-for-context/">página de conteúdo</a> do Elasticsearch Labs que acompanha este artigo.</p><h3>aplicação das leis de segurança</h3><p>Uma vantagem crucial de utilizar uma camada de velocidade baseada em pesquisa, como o Elastic, para engenharia de contexto é sua estrutura de segurança integrada. A plataforma da Elastic garante que o contexto fornecido às operações de IA generativa e agente respeite e proteja informações confidenciais mantidas em sigilo por meio de controle de acesso baseado em funções (RBAC) e controle de acesso baseado em atributos (ABAC) granulares. Isso significa que não apenas as consultas são processadas com eficiência, mas também que os resultados são filtrados de acordo com as permissões específicas do agente ou do usuário que iniciou a solicitação.</p><p>Os agentes são executados como o usuário autenticado, portanto a segurança é aplicada implicitamente por meio dos recursos de segurança integrados à plataforma:</p><ul><li><p><strong>Permissões refinadas:</strong> Defina o acesso no nível do documento, do campo ou até mesmo do termo, garantindo que os agentes de IA recebam apenas os dados que estão autorizados a visualizar.</p></li><li><p><strong>Controle de acesso baseado em funções (RBAC):</strong> Atribua funções a agentes ou usuários, concedendo acesso a conjuntos de dados ou funcionalidades específicas com base em suas responsabilidades definidas.</p></li><li><p><strong>Controle de acesso baseado em atributos (ABAC):</strong> Implemente políticas de acesso dinâmicas com base em atributos dos dados, do usuário ou do ambiente, permitindo uma segurança altamente adaptável e contextualizada.</p></li><li><p><strong>Segurança em nível de documento (DLS) e segurança em nível de campo (FLS):</strong> Esses recursos garantem que, mesmo dentro de um documento recuperado, apenas as partes autorizadas sejam visíveis, impedindo que informações confidenciais sejam expostas.</p></li><li><p><strong>Integração com segurança corporativa:</strong> Integre-se perfeitamente com sistemas de gerenciamento de identidade existentes (como LDAP, SAML, OIDC) para aplicar políticas de segurança consistentes em toda a organização.</p></li></ul><p>Ao integrar essas medidas de segurança diretamente no mecanismo de recuperação de contexto, a Elastic atua como um guardião seguro, garantindo que os agentes de IA operem dentro de limites de dados definidos, evitando a exposição não autorizada de dados e mantendo a conformidade com as regulamentações de privacidade de dados. Isso é fundamental para construir confiança em sistemas de IA que lidam com informações confidenciais ou proprietárias.</p><p>Como benefício adicional, ao usar uma camada unificada de velocidade de dados sobre suas fontes de dados corporativas, você alivia as cargas inesperadas de consultas ad hoc nesses repositórios que as ferramentas de agentes criariam. Você obtém um local centralizado para pesquisar tudo em tempo quase real e um único lugar para aplicar controles de segurança e governança.</p><h2>Ferramentas híbridas baseadas em pesquisa</h2><p>Existem algumas funcionalidades essenciais (e <a href="https://www.elastic.co/blog/whats-new-elastic-9-2-0">outras estão sendo adicionadas constantemente</a>) da plataforma Elastic que impulsionam a busca pela engenharia de contexto. O principal aqui é que a plataforma oferece uma infinidade de maneiras de atingir objetivos, com a flexibilidade para adaptar, alterar e expandir os métodos à medida que o ecossistema de IA avança.</p><h3>Apresentando o Construtor de Agentes</h3><p>O Elastic <a href="https://www.elastic.co/elasticsearch/agent-builder">Agent Builder</a> é nossa primeira incursão no mundo das ferramentas de IA com agentes, criadas para interagir com os dados que você já armazena no Elastic. O Agent Builder oferece uma interface de chat que permite aos usuários criar e gerenciar seus próprios agentes e ferramentas dentro do Kibana. Ele vem com servidores MCP e A2A integrados, APIs programáticas e um conjunto de ferramentas de sistema pré-construídas para consultar e explorar índices do Elasticsearch, além de gerar consultas ES|QL a partir de linguagem natural. O Agent Builder permite criar ferramentas personalizadas que visam e moldam os dados contextuais retornados ao agente por meio de uma sintaxe de consulta <a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL</a> expressiva.</p><p>Como o ES|QL realiza buscas híbridas, você pergunta? A funcionalidade principal é alcançada através da combinação do tipo de campo <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text">semantic_text</a> e dos comandos <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/fork">FORK</a>/<a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/fuse">FUSE</a> (o FUSE usa <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">RRF</a> por padrão para mesclar os resultados de cada fork). Aqui está um exemplo simples de uma busca fictícia de produto:</p>FROM products
| FORK
  (MATCH description "high performance gaming laptop" | EVAL search_type = "bm25"),
  (MATCH description_semantic "high performance gaming laptop" | EVAL search_type = "semantic")
| FUSE 
| LIMIT 20
| KEEP product_name, description, _score, search_type<p>A cláusula <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/eval">EVAL</a> incluída em cada um dos ramos FORK no exemplo acima não é estritamente necessária; ela está incluída apenas para demonstrar como você pode rastrear de qual modalidade de pesquisa um determinado resultado foi retornado.</p><h3>Modelos de pesquisa</h3><p>Digamos que você queira direcionar suas próprias ferramentas externas de gerenciamento de agentes para sua implantação do Elasticsearch. E em vez de ES|QL, você deseja usar recuperadores de vários estágios ou reutilizar a sintaxe DSL existente que você desenvolveu, e também deseja poder controlar as entradas que a consulta aceita, a sintaxe usada para executar a pesquisa e os campos retornados na saída. <a href="https://www.elastic.co/docs/solutions/search/search-templates">Os modelos de pesquisa</a> permitem que os usuários definam estruturas predefinidas para padrões de pesquisa comuns, melhorando a eficiência e a consistência na recuperação de dados. Isso é particularmente benéfico para ferramentas de agentes que interagem com APIs de busca, pois ajuda a padronizar o código repetitivo e permite uma iteração mais rápida na lógica de busca. E se alguma vez precisar ajustar algum desses fatores, basta atualizar o modelo de pesquisa e pronto, as alterações são implementadas. Se você procura um exemplo de modelos de pesquisa em ação com ferramentas agentivas, confira o blog do Elasticsearch Labs " <a href="https://www.elastic.co/search-labs/blog/mcp-intelligent-search">MCP para pesquisa inteligente</a>", que utiliza um modelo de pesquisa por trás de uma chamada de ferramenta de um servidor MCP externo.</p><h3>Fluxos de trabalho integrados (SIM!)</h3><p>Um dos aspectos mais difíceis de lidar em nosso novo mundo de IA com agentes é a natureza não determinística de agentes "racionais" semiautônomos e autodirigidos. A engenharia de contexto é uma disciplina crítica para a IA ativa: são as técnicas que ajudam a restringir as possíveis conclusões que nosso agente pode gerar ao que sabemos ser verdade fundamental. Mesmo com uma janela de contexto altamente precisa e relevante (quando saímos do âmbito dos fatos numéricos), ainda nos falta aquela garantia de que a resposta do agente seja totalmente repetível e confiável.</p><p>Ao executar a mesma solicitação para um agente várias vezes, as respostas podem ser <em>essencialmente</em> as mesmas, com <em>apenas uma pequena</em> diferença na forma como são enviadas. Isso geralmente funciona bem para consultas simples, talvez seja quase imperceptível, e podemos tentar moldar a saída com técnicas de engenharia de contexto. Mas, à medida que as tarefas que solicitamos aos nossos agentes se tornam mais complexas, aumenta a probabilidade de que uma ou mais subtarefas introduzam uma variação que altere ligeiramente o resultado final. É provável que a situação piore à medida que começarmos a depender mais da comunicação entre agentes, e essas variações se tornarão cumulativas. Isso reforça a ideia de que as ferramentas com as quais nossos agentes interagem precisam ser muito flexíveis e ajustáveis para direcionar com precisão os dados contextuais, e que devem responder em um formato de saída esperado. Isso também indica que, para muitos casos de uso, precisamos direcionar as interações entre agentes e ferramentas — é aí que os fluxos de trabalho entram em cena!</p><p>Em breve, a Elastic terá fluxos de trabalho totalmente personalizáveis integrados ao núcleo da plataforma. Esses fluxos de trabalho poderão operar com agentes e ferramentas de forma bidirecional, ou seja, os fluxos de trabalho poderão chamar agentes e ferramentas, e os agentes e ferramentas poderão chamar fluxos de trabalho. Ter essas funcionalidades totalmente integradas na mesma plataforma de IA de busca onde todos os seus dados residem será transformador; o potencial dos fluxos de trabalho é extremamente empolgante! Em breve, muito em breve!</p><h3>Elástico como banco de memória unificado</h3><p>Por ser uma plataforma de dados distribuída, criada para buscas quase em tempo real, a Elastic executa naturalmente as funções de memória de longo prazo para sistemas de IA com agentes. Com a experiência de chat integrada do Agent Builder, também temos rastreamento e gerenciamento da memória de curto prazo e do histórico de conversas. E como toda a plataforma é orientada a APIs, é extremamente fácil utilizar o Elastic como plataforma para persistir a saída contextual de uma ferramenta (e poder consultá-la posteriormente), o que poderia sobrecarregar a janela de contexto do agente; essa técnica às vezes é chamada de "<a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents#:~:text=Agents%20can%20assemble%20understanding%20layer%20by%20layer%2C%20maintaining%20only%20what%27s%20necessary%20in%20working%20memory%20and%20leveraging%20note%2Dtaking%20strategies%20for%20additional%20persistence">anotações</a> " em círculos de engenharia de contexto.</p><p>Ter memória de curto e longo prazo na mesma plataforma de busca traz muitos benefícios intrínsecos: imagine poder usar históricos de bate-papo e respostas contextuais persistentes como parte dos influenciadores semânticos em interações futuras, ou para realizar análises de ameaças, ou para criar produtos de dados persistentes que são gerados automaticamente a partir de chamadas de ferramentas repetidas com frequência… As possibilidades são infinitas!</p><h2>Conclusão</h2><p>O surgimento de grandes modelos de linguagem mudou a forma como conseguimos relacionar conteúdo e os métodos que usamos para analisar nossos dados. Estamos nos afastando rapidamente do mundo atual, onde os humanos realizam a pesquisa, a análise contextual e o raciocínio lógico para responder às suas próprias perguntas, para um mundo onde essas etapas são amplamente automatizadas por meio de inteligência artificial ativa. Para que possamos confiar nas respostas geradas que recebemos, precisamos ter a garantia de que o agente considerou <em>todas</em> as informações <em>mais relevantes</em> (incluindo o fator de relevância subjetiva) ao gerar sua resposta. Nosso principal método para tornar a IA agente confiável é fundamentar as ferramentas que recuperam contexto adicional por meio de técnicas de RAG (Aleatorização, Atribuição e Geração de Respostas) e engenharia de contexto, mas a forma como essas ferramentas realizam a <em>recuperação inicial</em> pode ser crucial para a precisão da resposta.</p><p>A plataforma Elastic Search AI oferece a flexibilidade e a vantagem da busca híbrida, juntamente com diversos recursos integrados que auxiliam a IA agente em termos de precisão, desempenho e escalabilidade; em outras palavras, o Elastic é uma plataforma fantástica para vários aspectos da engenharia de contexto! Ao padronizar a recuperação de contexto por meio de uma plataforma de busca, simplificamos as operações das ferramentas de inteligência artificial em várias frentes — e, assim como diz o paradoxo "ir mais devagar para ir mais rápido", a simplicidade na camada de geração de contexto significa uma IA mais rápida e confiável.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-agentic-ai-accuracy</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-agentic-ai-accuracy</guid>
    <category><![CDATA[Busca híbrida]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Woody Walton]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt42a203a316f0e22e/6a170932b339d58ebc769f5f/b82ff25242e4229cc20b218d9cc91c60cfd680bc-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Sabe, para contexto - Parte II: IA Agêntica e a necessidade de engenharia de contexto]]></title>
    <description><![CDATA[Aprenda como a evolução dos LLMs em direção à IA agente aumenta a necessidade de engenharia de contexto para resolver os limites de contexto RAG e o gerenciamento de memória.]]></description>
    <content:encoded><![CDATA[<p>Com esse <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">contexto</a> (bastante extenso) sobre como os LLMs (Learning Learning Machines) mudaram os processos subjacentes de recuperação de informações, vejamos como eles também mudaram a forma como consultamos dados.</p><h2>Uma nova forma de interagir com dados</h2><p>A IA generativa (genAI) e a IA agentiva funcionam de maneira diferente da busca tradicional. Enquanto antes começávamos a pesquisar informações por meio de uma busca ("deixe-me pesquisar isso no Google..."), a ação inicial tanto para a IA de geração de robôs quanto para os agentes geralmente se dá por meio da linguagem natural inserida em uma interface de bate-papo. A interface de bate-papo é uma discussão com um LLM (Literatura Liderada pelo Senhor da Moeda) que usa sua compreensão semântica para transformar nossa pergunta em uma resposta concisa, uma resposta resumida que parece vir de um oráculo com amplo conhecimento de todos os tipos de informação. O que realmente convence é a capacidade do LLM de gerar frases coerentes e ponderadas que conectam os fragmentos de conhecimento que ele apresenta — mesmo quando são imprecisos ou totalmente alucinatórios, há uma <a href="https://en.wikipedia.org/wiki/Truthiness">sensação de veracidade</a> neles.</p><p>Aquela velha barra de pesquisa com a qual nos acostumamos tanto a interagir pode ser considerada o mecanismo RAG que usávamos quando <em><strong>nós mesmos</strong></em> éramos o agente de raciocínio. Hoje em dia, até mesmo os mecanismos de busca da internet estão transformando nossa tradicional experiência de busca lexical, baseada em "catar e digitar", em resumos gerados por inteligência artificial que respondem à consulta com um sumário dos resultados, ajudando os usuários a evitar a necessidade de clicar e avaliar cada resultado individualmente.</p><h2>IA Generativa e RAG</h2><p>A IA generativa tenta usar sua compreensão semântica do mundo para analisar a intenção subjetiva expressa em uma solicitação de bate-papo e, em seguida, usa suas habilidades de inferência para criar uma resposta especializada instantaneamente. Uma interação com IA generativa possui várias partes: começa com a entrada/consulta do usuário, conversas anteriores na sessão de bate-papo podem ser usadas como contexto adicional, e a instrução que informa ao LLM como raciocinar e quais procedimentos seguir na construção da resposta. As instruções evoluíram de orientações simples do tipo "explique isso para mim como se eu tivesse cinco anos de idade" para explicações detalhadas de como processar as solicitações. Essas análises geralmente incluem seções distintas que descrevem detalhes da personalidade/função da IA, raciocínio pré-geração/processo de pensamento interno, critérios objetivos, restrições, formato de saída, público-alvo, bem como exemplos para ajudar a demonstrar os resultados esperados.</p><p>Além da consulta do usuário e da mensagem do sistema, a geração aumentada de recuperação (RAG, na sigla em inglês) fornece informações contextuais adicionais no que é chamado de "janela de contexto". O RAG tem sido uma adição crucial à arquitetura; é o que usamos para informar o LLM sobre as peças que faltam em sua compreensão semântica do mundo.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfa000ccfdd9d184/6a17ddb57b54f955f38b37da/5b9671d5d07d4caefde372bb3188000754a91eed-1470x746.png" alt="Como os LLMs processam as consultas dos usuários e criam contexto" /><p>As janelas de contexto podem ser um tanto <a href="https://www.dbreunig.com/2025/06/22/how-contexts-fail-and-how-to-fix-them.html">exigentes</a> em termos do que, onde e quanto você lhes fornece. O contexto selecionado é muito importante, obviamente, mas a relação sinal-ruído do contexto fornecido também importa, assim como o tamanho da janela.</p><h3>Informação insuficiente</h3><p>Fornecer pouca informação em uma consulta, prompt ou janela de contexto pode levar a alucinações, pois o LLM não consegue determinar com precisão o contexto semântico correto para gerar uma resposta. Existem também problemas com a similaridade vetorial dos tamanhos dos fragmentos de documentos — uma pergunta curta e simples pode não se alinhar semanticamente com os documentos ricos e detalhados encontrados em nossas bases de conhecimento vetorizadas. Foram desenvolvidas técnicas de expansão de consultas, como <a href="https://medium.com/data-science/how-to-use-hyde-for-better-llm-rag-retrieval-a0aa5d0e23e8">Hypothetical Document Embeddings (HyDE)</a> , que utilizam LLMs para gerar uma resposta hipotética mais rica e expressiva do que a consulta curta. O perigo aqui, claro, é que o documento hipotético seja em si uma alucinação que afasta ainda mais o LLM do contexto correto.</p><h3>Informação em excesso</h3><p>Assim como acontece conosco, humanos, o excesso de informações em uma janela de contexto pode sobrecarregar e confundir um usuário de linguagem natural sobre quais são as partes importantes. O estouro de contexto (ou "<a href="https://research.trychroma.com/context-rot">deterioração de contexto</a> ") afeta a qualidade e o desempenho das operações de IA generativa; ele impacta significativamente o "orçamento de atenção" do LLM (sua memória de trabalho) e dilui a relevância entre muitos tokens concorrentes. O conceito de "deterioração do contexto" também inclui a observação de que os autores de livros didáticos tendem a ter um <a href="https://alexandrabarr.beehiiv.com/p/context-windows">viés posicional</a> — eles preferem o conteúdo no início ou no final de uma janela de contexto em relação ao conteúdo na seção intermediária.</p><h3>Informações que distraem ou são contraditórias</h3><p>Quanto maior for a janela de contexto, maior será a probabilidade de incluir informações supérfluas ou conflitantes que podem distrair o usuário do LLM (Liderança em Aprendizagem) de selecionar e processar o contexto correto. De certa forma, isso se torna um problema de "lixo entra, lixo sai": simplesmente despejar um conjunto de resultados de documentos em uma janela de contexto fornece ao LLM muita informação para processar (potencialmente em excesso), mas dependendo de como o contexto foi selecionado, há uma possibilidade maior de informações conflitantes ou irrelevantes se infiltrarem.</p><h2>IA Agêntica</h2><p>Eu disse que havia muito o que abordar, mas conseguimos — finalmente estamos falando sobre tópicos de IA agente! A IA Agética é uma nova e empolgante aplicação das interfaces de chat do LLM que expande a capacidade da IA generativa (podemos já chamá-la de "legada"?) de sintetizar respostas com base em seu próprio conhecimento e nas informações contextuais fornecidas pelo usuário. À medida que a IA generativa amadureceu, percebemos que havia um certo nível de tarefas e automação que poderíamos delegar aos LLMs, inicialmente relegadas a atividades tediosas e de baixo risco que podem ser facilmente verificadas/validadas por um humano. Em um curto período de tempo, esse escopo inicial cresceu: uma janela de bate-papo do LLM agora pode ser a faísca que envia um agente de IA para planejar, executar e avaliar e adaptar seu plano de forma autônoma e iterativa para atingir o objetivo especificado. Os agentes têm acesso ao raciocínio dos seus LLMs, ao histórico de conversas e à memória cognitiva (na medida do possível), e também dispõem de ferramentas específicas que podem utilizar para atingir esse objetivo. Também estamos vendo agora arquiteturas que permitem que um agente de nível superior funcione como orquestrador de múltiplos <a href="https://www.philschmid.de/the-rise-of-subagents">subagentes</a>, cada um com suas próprias cadeias lógicas, conjuntos de instruções, contexto e ferramentas.</p><p>Os agentes são o ponto de entrada para um fluxo de trabalho em grande parte automatizado: eles são autônomos, pois conseguem conversar com um usuário e, em seguida, usar a "lógica" para determinar quais ferramentas estão disponíveis para ajudar a responder à pergunta do usuário. As ferramentas são geralmente consideradas passivas em comparação com os agentes e são construídas para realizar um único tipo de tarefa. Os <em>tipos</em> de tarefas que uma ferramenta pode executar são praticamente ilimitados (o que é realmente empolgante!), mas uma das principais tarefas que as ferramentas realizam é coletar informações contextuais para que um agente as considere ao executar seu fluxo de trabalho.</p><p>Como tecnologia, a IA ativa ainda está em sua infância e propensa ao equivalente acadêmico do transtorno de déficit de atenção — ela facilmente esquece o que lhe foi pedido para fazer e, muitas vezes, sai fazendo outras coisas que não faziam parte do escopo da tarefa. Por trás da aparente magia, as habilidades de "raciocínio" dos LLMs ainda se baseiam em prever o próximo token mais provável em uma sequência. Para que o raciocínio (ou, um dia, a inteligência artificial geral (IAG)) se torne confiável e digno de confiança, precisamos ser capazes de verificar se, ao recebermos as informações corretas e mais atualizadas, elas raciocinarão da maneira que esperamos (e talvez nos forneçam aquela informação extra que não havíamos imaginado). Para que isso aconteça, as arquiteturas agentivas precisarão da capacidade de se comunicar claramente (protocolos), de aderir aos fluxos de trabalho e restrições que lhes impomos (diretrizes), de lembrar em que ponto da tarefa estão (estado), de gerenciar seu espaço de memória disponível e de validar se suas respostas são precisas e atendem aos critérios da tarefa.</p><h2>Fale comigo em uma língua que eu possa entender.</h2><p>Como é comum em novas áreas de desenvolvimento (especialmente no mundo dos LLMs), inicialmente existiram várias abordagens para a comunicação entre agentes e ferramentas, mas elas rapidamente convergiram para o <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Protocolo de Contexto do Modelo (MCP)</a> como o padrão de facto. A definição de Protocolo de Contexto de Modelo está literalmente no nome: é o <strong>protocolo</strong> que um <strong>modelo</strong> usa para solicitar e receber informações <strong>contextuais</strong> . O MCP funciona como um adaptador universal para que os agentes LLM se conectem a ferramentas e fontes de dados externas; ele simplifica e padroniza as APIs para que diferentes estruturas e ferramentas LLM possam interoperar facilmente. Isso faz do MCP uma espécie de ponto de articulação entre a lógica de orquestração e os comandos do sistema dados a um agente para que ele execute tarefas de forma autônoma a serviço de seus objetivos, e as operações enviadas às ferramentas para que sejam executadas de maneira mais isolada (isolada, pelo menos, em relação ao agente iniciador).</p><p>Este ecossistema é tão novo que cada direção de expansão parece uma nova fronteira. Temos protocolos semelhantes para interações agente-a-agente (<a href="https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/">Agent2Agent (A2A)</a> , claro!), bem como outros projetos para melhorar a memória de raciocínio do agente (<a href="https://venturebeat.com/ai/new-memory-framework-builds-ai-agents-that-can-handle-the-real-worlds">ReasoningBank</a>), para selecionar o melhor servidor MCP para a tarefa em questão (<a href="https://arxiv.org/abs/2505.03275">RAG-MCP</a>) e usar análise semântica, como classificação zero-shot e detecção de padrões na entrada e saída, como <a href="https://openai.github.io/openai-guardrails-python/">Guardrails</a> para controlar sobre o que um agente pode operar.</p><p>Você deve ter percebido que a intenção subjacente de cada um desses projetos é melhorar a qualidade e o controle das informações retornadas para uma janela de contexto do agente/genAI? Embora o ecossistema de IA agente continue a desenvolver a capacidade de lidar melhor com essas informações contextuais (para controlá-las, gerenciá-las e operá-las), sempre haverá a necessidade de recuperar as informações contextuais <em>mais relevantes</em> como matéria-prima para o agente processar.</p><h2>Bem-vindo à engenharia de contexto!</h2><p>Se você está familiarizado com os termos de IA generativa, provavelmente já ouviu falar de 'engenharia de prompts' - a essa altura, é quase uma pseudociência em si mesma. A engenharia de prompts é usada para encontrar as melhores e mais eficientes maneiras de descrever proativamente os comportamentos que você deseja que o LLM utilize ao gerar sua resposta. A " <a href="https://www.elastic.co/search-labs/blog/context-engineering-overview">engenharia de contexto</a>" estende as técnicas de "engenharia de prompts" além do lado do agente, abrangendo também as fontes e sistemas de contexto disponíveis no lado das ferramentas do protocolo MCP, e inclui os tópicos gerais de gerenciamento, processamento e geração de contexto:</p><ul><li><p><strong>Gerenciamento de contexto </strong>- Relacionado à manutenção da eficiência de estado e contexto em fluxos de trabalho de agentes de longa duração e/ou mais complexos. Planejamento, acompanhamento e orquestração iterativos de tarefas e chamadas de ferramentas para atingir os objetivos do agente. Devido ao limitado "orçamento de atenção" com que os agentes têm que trabalhar, o gerenciamento de contexto se preocupa principalmente com técnicas que ajudam a refinar a janela de contexto para capturar tanto o escopo mais completo quanto os elementos mais importantes do contexto (sua precisão versus abrangência!). As técnicas incluem compressão, sumarização e persistência do contexto de etapas anteriores ou chamadas de ferramentas para liberar espaço na memória de trabalho para contexto adicional em etapas subsequentes.</p></li><li><p><strong>Processamento de contexto </strong>- Os passos lógicos e, idealmente, em sua maioria programáticos para integrar, normalizar ou refinar o contexto adquirido de fontes distintas, de modo que o agente possa raciocinar sobre todo o contexto de maneira relativamente uniforme. O objetivo principal é tornar o contexto de todas as fontes (sugestões, RAG, memória, etc.) o mais acessível possível ao agente. </p></li><li><p><strong>Geração de contexto </strong>- Se o processamento de contexto visa tornar o contexto recuperado utilizável para o agente, então a geração de contexto permite que o agente solicite e receba informações contextuais adicionais conforme desejar, mas também com restrições.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e1e68c08fe050bc/6a17ddb7414c645035945073/4a8240e1eb078b2294b8d981b9caa8593589cac4-1600x900.png" alt="Engenharia de contexto em mestrados em direito" /><p>Os diversos elementos efêmeros dos aplicativos de bate-papo do LLM se relacionam diretamente (e às vezes de maneiras sobrepostas) com essas funções de alto nível da engenharia de contexto:</p><ul><li><p><strong>Instruções / avisos do sistema</strong> - Os avisos servem de base para que a atividade de IA generativa (ou agentiva) direcione seu raciocínio para atingir o objetivo do usuário. Os prompts são um contexto por si só; não são apenas instruções de tom — frequentemente incluem lógica de execução da tarefa e regras para coisas como "pensar passo a passo" ou "respirar fundo" antes de responder, para validar se a resposta atende completamente à solicitação do usuário. Testes recentes demonstraram que as linguagens de marcação são muito eficazes para estruturar as diferentes partes de um enunciado, mas também é preciso ter cuidado para calibrar as instruções, encontrando um equilíbrio ideal entre serem vagas demais e específicas demais; queremos fornecer instruções suficientes para que o LLM encontre o contexto correto, mas não ser tão prescritivos a ponto de perder insights inesperados.</p></li><li><p><strong>Memória de curto prazo</strong> (estado/histórico) - A memória de curto prazo consiste essencialmente nas interações da sessão de bate-papo entre o usuário e o LLM. Essas informações são úteis para refinar o contexto em sessões ao vivo e podem ser salvas para consulta e continuação futuras. </p></li><li><p><strong>Memória de longo prazo</strong> - A memória de longo prazo deve consistir em informações que sejam úteis em múltiplas sessões. E não se trata apenas de bases de conhecimento específicas de domínio acessadas por meio do RAG; pesquisas recentes utilizam os resultados de solicitações anteriores de IA agentiva/generativa para aprender e referenciar em interações agentivas atuais. Algumas das inovações mais interessantes na área da memória de longo prazo estão relacionadas ao ajuste da forma como o estado é <a href="https://steve-yegge.medium.com/introducing-beads-a-coding-agent-memory-system-637d7d92514a">armazenado e vinculado,</a> para que os agentes possam retomar de onde pararam. </p></li><li><p><strong>Saída estruturada</strong> - A cognição exige esforço, então provavelmente não é surpresa que, mesmo com capacidades de raciocínio, os LLMs (assim como os humanos) queiram despender menos esforço ao pensar e, na ausência de uma API ou protocolo definido, ter um mapa (um esquema) de como ler os dados retornados por uma chamada de ferramenta é extremamente útil. A inclusão de <a href="https://platform.openai.com/docs/guides/structured-outputs?lang=javascript">Saídas Estruturadas</a> como parte da estrutura agentiva ajuda a tornar essas interações máquina a máquina mais rápidas e confiáveis, com menos necessidade de análise sintática guiada pelo pensamento.</p></li><li><p><strong>Ferramentas disponíveis</strong> - As ferramentas podem realizar todo tipo de tarefa, desde coletar informações adicionais (por exemplo, enviar consultas RAG para repositórios de dados corporativos ou por meio de APIs online) até executar ações automatizadas em nome do agente (como reservar um quarto de hotel com base nos critérios da solicitação do agente). As ferramentas também podem ser subagentes com suas próprias cadeias de processamento. </p></li><li><p><strong>Geração Aumentada por Recuperação (RAG)</strong> - Eu realmente gosto da descrição de RAG como "integração dinâmica de conhecimento". Conforme descrito anteriormente, RAG é a técnica para fornecer as informações adicionais às quais o LLM não teve acesso durante seu treinamento, ou seja, é uma reiteração das ideias que consideramos mais importantes para obter a resposta correta — aquela que é mais relevante para nossa pergunta subjetiva.</p></li></ul><h2>Poder cósmico fenomenal, espaço vital minúsculo!</h2><p>A IA agente tem muitos novos domínios fascinantes e empolgantes para explorar! Ainda existem muitos dos antigos problemas tradicionais de recuperação e processamento de dados a serem resolvidos, mas também novas classes de desafios que só agora estão vindo à tona na nova era dos LLMs. Muitos dos problemas imediatos que estamos enfrentando hoje estão relacionados à engenharia de contexto, ou seja, a como fornecer aos LLMs (Learning Learning Machines - Máquinas de Memória de Longo Prazo) as informações contextuais adicionais de que precisam sem sobrecarregar seu espaço limitado de memória de trabalho.</p><p>A flexibilidade de agentes semiautônomos que têm acesso a uma variedade de ferramentas (e outros agentes) dá origem a tantas novas ideias para implementar IA que é difícil imaginar as diferentes maneiras pelas quais poderíamos juntar as peças. A maior parte da pesquisa atual se enquadra no campo da engenharia de contexto e está focada na construção de estruturas de gerenciamento de memória que possam lidar e rastrear quantidades maiores de contexto — isso porque os problemas de raciocínio profundo que realmente queremos que os LLMs resolvam apresentam maior complexidade e etapas de pensamento mais longas e multifásicas, onde a memorização é extremamente importante.</p><p>Grande parte da experimentação em curso na área visa encontrar a gestão de tarefas e as configurações de ferramentas ideais para alimentar a "boca" dos agentes. Cada chamada de ferramenta na cadeia de raciocínio de um agente acarreta um custo cumulativo, tanto em termos de computação necessária para executar a função dessa ferramenta quanto em termos do impacto na janela de contexto limitada. Algumas das técnicas mais recentes para gerenciar o contexto de agentes LLM causaram efeitos em cadeia indesejados, como o "<a href="https://venturebeat.com/ai/ace-prevents-context-collapse-with-evolving-playbooks-for-self-improving-ai">colapso de contexto</a> ", em que a compressão/resumo do contexto acumulado para tarefas de longa duração resulta em perda <em>excessiva</em> de dados. O objetivo é obter ferramentas que retornem um contexto conciso e preciso, sem que informações irrelevantes ocupem o valioso espaço de memória da janela de contexto.</p><h3>Tantas possibilidades</h3><p>Desejamos separação de funções com flexibilidade para reutilizar ferramentas/componentes, portanto, faz todo o sentido criar ferramentas dedicadas e automatizadas para conectar-se a fontes de dados específicas — cada ferramenta pode se especializar em consultar um tipo de repositório, um tipo de fluxo de dados ou até mesmo um caso de uso. Mas atenção: na ânsia de economizar tempo/dinheiro/provar que algo é possível, haverá uma forte tentação de usar os LLMs como ferramenta de federação… Tente não fazer isso, já passamos <a href="https://www.elastic.co/pdf/elastic-distributed-not-federated-search.pdf">por essa situação</a> antes! A consulta federada funciona como um "tradutor universal" que converte uma consulta recebida na sintaxe que o repositório remoto entende e, em seguida, precisa racionalizar os resultados de múltiplas fontes em uma resposta coerente. A federação como técnica <em>funciona</em> <em>bem</em> em pequenas escalas, mas em grandes escalas, e especialmente quando os dados são multimodais, a federação tenta preencher lacunas que são simplesmente muito grandes.</p><p>No mundo agentivo, o agente seria o federador e as ferramentas (através do MCP) seriam as conexões definidas manualmente com recursos distintos. Utilizar ferramentas específicas para acessar fontes de dados desconectadas pode parecer uma nova e poderosa maneira de unir dinamicamente diferentes fluxos de dados para cada consulta, mas usar essas ferramentas para fazer a mesma pergunta a várias fontes provavelmente acabará causando mais problemas do que soluções. Cada uma dessas fontes de dados provavelmente consiste em diferentes tipos de repositórios subjacentes, cada um com suas próprias capacidades de recuperar, classificar e proteger os dados neles contidos. Essas variações ou "incompatibilidades de impedância" entre os repositórios aumentam a carga de processamento, obviamente. Eles também podem introduzir informações ou sinais conflitantes, onde algo aparentemente inócuo como um desalinhamento na pontuação pode alterar drasticamente a importância atribuída a um trecho do contexto retornado e afetar a relevância da resposta gerada no final.</p><h3>A troca de contexto também é difícil para os computadores.</h3><p>Quando você envia um agente em uma missão, muitas vezes a primeira tarefa dele é encontrar todos os dados relevantes aos quais ele tem acesso. Assim como acontece com os humanos, se cada fonte de dados à qual o agente se conecta responde com informações diferentes e desagregadas, haverá uma carga cognitiva (embora não exatamente do mesmo tipo) associada à extração dos elementos contextuais relevantes do conteúdo recuperado. Isso requer tempo/computação, e cada pequeno detalhe se soma na cadeia lógica agentiva. Isso nos leva à conclusão de que, assim como está sendo discutido para <a href="https://blog.cloudflare.com/code-mode/">o MCP</a>, a maioria das ferramentas de agentes deveria se comportar mais como APIs — funções isoladas com entradas e saídas conhecidas, ajustadas para atender às necessidades de diferentes tipos de agentes. Aliás, estamos até percebendo que <a href="https://arxiv.org/html/2501.12372v5">os LLMs precisam de contexto para contexto</a> — eles se saem muito melhor em conectar os pontos semânticos, especialmente quando se trata de uma tarefa como traduzir linguagem natural para sintaxe estruturada, quando têm um esquema ao qual se referir (leia o manual, de fato!).</p><h2>Intervalo da sétima entrada!</h2><p>Já abordamos o <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">impacto que os LLMs tiveram na recuperação e consulta de dados</a>, bem como a forma como a janela de bate-papo está evoluindo para uma experiência de IA ativa. Vamos juntar os dois tópicos e ver como podemos usar nossos recursos modernos de busca e recuperação para melhorar nossos resultados em engenharia de contexto. Vamos para a <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-agentic-ai-accuracy">Parte III: O poder da busca híbrida na engenharia de contexto</a>!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Woody Walton]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5f98889141fba45b/6a17ddb80b0bed0822dd34a2/79c0378b68d74d9e018c35ee2c1fd17daeee9f2c-1080x608.webp" length="0" type="image/webp"/>
    <pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando uma sala de imprensa do LLM Agent com protocolo A2A e MCP no Elasticsearch: Parte I]]></title>
    <description><![CDATA[Explore os conceitos do protocolo A2A e do MCP em um exemplo prático de redação, onde agentes especializados em LLM colaboram para pesquisar, escrever, editar e publicar artigos de notícias.]]></description>
    <content:encoded><![CDATA[<h2>Introdução</h2><p>Os sistemas atuais baseados em LLM estão evoluindo rapidamente, deixando de ser aplicações de modelo único e se tornando redes complexas onde agentes especializados trabalham juntos para realizar tarefas antes consideradas impossíveis pela computação moderna. À medida que esses sistemas se tornam mais complexos, a infraestrutura que permite a comunicação entre agentes e o acesso a ferramentas passa a ser o foco principal do desenvolvimento. Surgiram duas abordagens complementares para atender a essas necessidades: os protocolos <strong>Agent2Agent (A2A)</strong> para coordenação multiagente e o <strong>Model Context Protocol (MCP)</strong> para acesso padronizado a ferramentas e recursos.</p><p>Compreender quando usar cada um em harmonia com o outro e quando utilizá-los isoladamente pode impactar significativamente a escalabilidade, a facilidade de manutenção e a eficácia de suas aplicações. Este artigo explora os conceitos e implementações do <strong>modelo A2A (Application</strong> -to-Application) no exemplo prático de uma redação digital, onde agentes especializados em LLM (Legal Learning Management) colaboram para pesquisar, escrever, editar e publicar artigos de notícias.</p><p>Um repositório complementar pode ser encontrado <a href="https://github.com/justincastilla/elastic-newsroom/tree/main">aqui</a>, e examinaremos exemplos concretos do A2A em ação perto do final do artigo, na Seção 5.</p><h3>Pré-requisitos</h3><p>O <a href="https://github.com/justincastilla/elastic-newsroom/tree/main">repositório</a> consiste em implementações em Python dos agentes A2A. O Flask fornece um servidor de API, bem como um serviço de mensagens personalizado em Python chamado Event Hub, que encaminha mensagens para registro e atualizações da interface do usuário. Por fim, uma interface de usuário React é fornecida para uso independente dos recursos da sala de imprensa. Tudo está contido em uma imagem Docker para facilitar a implementação. Se você deseja executar os serviços diretamente em sua máquina, precisará garantir que tenha as seguintes tecnologias instaladas:</p><p>Linguagens e ambientes de execução</p><ul><li><p>Python 13.12 - Linguagem principal de backend</p></li><li><p>Node.js 18+ - Interface de usuário React opcional</p></li></ul><p>Frameworks principais e SDKs:</p><ul><li><p>SDK A2A 0.3.8 - Coordenação e comunicação de agentes</p></li><li><p>SDK Antrópico - Integração com Claude para geração de IA</p></li><li><p>Uvicorn - Servidor ASGI para executar agentes</p></li><li><p>FastMCP 2.12.5+ - Implementação do servidor MCP</p></li><li><p>React 18.2 - Framework de interface de usuário para front-end</p></li></ul><p>Dados e pesquisa</p><ul><li><p>Elasticsearch 9.1.1+ - Indexação e pesquisa de artigos</p></li></ul><p>Implantação do Docker (opcional, mas recomendada)</p><ul><li><p>Docker 28.5.1+</p></li></ul><h2>Seção 1: O que é Agent2Agent (A2A)?</h2><h3>Definição e conceitos fundamentais</h3><p>Agent2Agent (A2A) é um protocolo padronizado para interação entre agentes LLM independentes. Em vez de um único sistema monolítico que lida com todas as tarefas, o A2A permite que vários agentes especializados se comuniquem, coordenem e colaborem para realizar fluxos de trabalho complexos que seriam difíceis, lentos ou simplesmente impossíveis de serem gerenciados com eficiência por um único agente.</p><p><strong>Especificação oficial</strong>: <a href="https://a2a-protocol.org/latest/specification/">https://a2a-protocol.org/latest/specification/</a></p><h3>Origens e evolução</h3><p>O conceito de comunicação Agente para Agente, ou sistemas multiagentes, tem raízes em sistemas distribuídos, microsserviços e pesquisas multiagentes que remontam <a href="https://en.wikipedia.org/wiki/Multi-agent_system">a décadas</a>. Os primeiros trabalhos em inteligência artificial distribuída lançaram as bases para agentes capazes de negociar, coordenar e colaborar. Esses primeiros sistemas eram dedicados a <a href="https://www.jasss.org/5/1/7.html">simulações sociais</a> em larga escala, <a href="https://arxiv.org/html/2410.09403v1">pesquisa acadêmica</a> e <a href="https://www.researchgate.net/publication/334765661_Generation_Expansion_Planning_Considering_Investment_Dynamic_of_Market_Participants_Using_Multi-agent_System">gerenciamento de redes elétricas</a>.</p><p>Com o surgimento da disponibilidade do LLM e a redução do custo de operação, os sistemas multiagentes tornaram-se acessíveis aos mercados "prosumidores", com o apoio do Google e da comunidade de pesquisa em IA em geral. Agora conhecidos como sistemas Agent2Agent, a adição do protocolo A2A evoluiu para um padrão moderno projetado especificamente para a era de múltiplos modelos de linguagem de grande porte coordenando esforços e tarefas.</p><p>O protocolo A2A garante comunicação e coordenação perfeitas entre os agentes, aplicando padrões e princípios consistentes aos pontos de interação onde os LLMs se conectam e se comunicam. Essa padronização permite que agentes de diferentes desenvolvedores — que utilizam diferentes modelos subjacentes — trabalhem juntos de forma eficaz.</p><p>Os protocolos de comunicação não são novidade e estão amplamente estabelecidos em praticamente todas as transações digitais realizadas na internet. Se você digitou <a href="https://www.elastic.co/search-labs">https://www.elastic.co/search-labs</a> Ao acessar este artigo por meio de um navegador, é muito provável que os protocolos TCP/IP, HTTP e de consulta DNS tenham sido executados, garantindo uma experiência de navegação consistente.</p><h3>Características principais</h3><p>Os sistemas A2A são construídos sobre diversos princípios fundamentais para garantir uma comunicação fluida. Com base nesses princípios, garante-se que diferentes agentes, utilizando diferentes LLMs, frameworks e linguagens de programação, interajam perfeitamente.</p><p>Eis os quatro princípios principais:</p><ul><li><p><strong>Troca de mensagens</strong>: Os agentes comunicam-se por meio de mensagens estruturadas com propriedades e formatos bem definidos.</p></li><li><p><strong>Coordenação</strong>: Os agentes orquestram fluxos de trabalho complexos, delegando tarefas uns aos outros e gerenciando dependências sem bloquear outros agentes.</p></li><li><p><strong>Especialização</strong>: Cada agente se concentra em um domínio ou capacidade específica, tornando-se um especialista em sua área e oferecendo a conclusão de tarefas com base nessa habilidade.</p></li><li><p><strong>Estado distribuído</strong>: O estado e o conhecimento são distribuídos entre os agentes em vez de centralizados, sendo que os agentes têm a capacidade de atualizar uns aos outros sobre o progresso da tarefa, o estado e os retornos parciais (artefatos).</p></li></ul><h3>A redação: um exemplo prático</h3><p>Imagine uma redação digital alimentada por agentes de IA, cada um especializado em um aspecto diferente do jornalismo:</p><ul><li><p><strong>Chefe de Notícias</strong> (coordenador/cliente): Atribui pautas e supervisiona o fluxo de trabalho.</p></li><li><p><strong>Agente de reportagem</strong>: Redige artigos com base em pesquisas e entrevistas.</p></li><li><p><strong>Agente de Pesquisa</strong>: Reúne fatos, estatísticas e informações de contexto.</p></li><li><p><strong>Agente de Arquivo</strong>: Pesquisa artigos históricos e identifica tendências usando o Elasticsearch.</p></li><li><p><strong>Agente Editorial</strong>: Analisa artigos quanto à qualidade, estilo e otimização para SEO.</p></li><li><p><strong>Agente de Publicação</strong>: Publica artigos aprovados na plataforma do blog via CI/CD</p></li></ul><p>Esses profissionais não trabalham isoladamente; quando o chefe de jornalismo atribui uma matéria sobre <em>a adoção de energias renováveis</em>, o repórter precisa do pesquisador para coletar as estatísticas, do editor para revisar o rascunho e do editor-chefe para publicar a versão final. Essa coordenação ocorre por meio de protocolos A2A.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb6c7215a96326481/6a17f2dd445de953024d0243/cc0760dbd74c49b92fa00dafbb8c2e8740eb70b6-963x693.png" alt="" /><h2>Seção 2: Compreendendo a arquitetura A2A</h2><h3>Funções de Agente de Atendimento ao Cliente e Agente Remoto</h3><p>Na arquitetura A2A, os agentes assumem dois papéis principais. O <strong>Agente Cliente</strong> é responsável por formular e comunicar tarefas a outros agentes no sistema. Identifica agentes remotos e suas capacidades, usando essas informações para tomar decisões fundamentadas sobre a delegação de tarefas. O agente do cliente coordena o fluxo de trabalho geral, garantindo que as tarefas sejam distribuídas adequadamente e que o sistema progrida em direção aos seus objetivos.</p><p>O <strong>Agente Remoto</strong>, por outro lado, executa tarefas delegadas pelos clientes. Ela fornece informações ou toma medidas específicas em resposta a solicitações, mas não inicia ações de forma independente. Os agentes remotos também podem se comunicar com outros agentes remotos conforme necessário para cumprir suas responsabilidades atribuídas, criando uma rede colaborativa de capacidades especializadas.</p><p>Em nossa redação, o Chefe de Notícias atua como agente do cliente, enquanto o Repórter, o Pesquisador, o Editor e o Diretor de Publicação são agentes remotos que respondem às solicitações e se coordenam entre si.</p><h3>Principais funcionalidades A2A</h3><p>Os protocolos A2A definem diversas capacidades que permitem a colaboração multiagente:</p><h4>1. Descoberta</h4><p>Os servidores A2A devem anunciar suas funcionalidades para que os clientes saibam quando e como utilizá-las para tarefas específicas. Isso é feito por meio de Cartões de Agente — documentos JSON que descrevem as habilidades, entradas e saídas de um agente. Os cartões de agente são disponibilizados em endpoints consistentes e conhecidos (como o endpoint recomendado <code>/.well-known/agent-card.json</code> ), permitindo que os clientes descubram e consultem as capacidades de um agente antes de iniciar a colaboração.</p><p>Abaixo, segue um exemplo de cartão de agente para o agente de arquivamento personalizado da Elastic, "Archie Archivist". Note que fornecedores de software como a Elastic hospedam seus agentes A2A e fornecem um URL para acesso:</p>{
  "name": "Archie Archivist",
  "description": "Helps find historical news documents in the Elasticsearch Index of archived news articles and content.",
  "url": "https://xxxxxxxxxxxxx-abc123.kb.us-central1.gcp.elastic.cloud/api/agent_builder/a2a/archive-agent",
  "provider": {
    "organization": "Elastic",
    "url": "https://elastic.co"
  },
  "version": "0.1.0",
  "protocolVersion": "0.3.0",
  "preferred_transport": "JSONRPC",
  "documentationURL": "https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server"
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "stateTransitionHistory": false
  },
  "skills": [
    {
      "id": "platform.core.search",
      "name": "platform.core.search",
      "description": "A powerful tool for searching and analyzing data within your Elasticsearch cluster.",
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["text/plain", "application/json"]
    },
    {
      "id": "platform.core.index_explorer",
      "name": "platform.core.index_explorer",
      "description": "List relevant indices, aliases and datastreams based on a natural language query.",
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["text/plain", "application/json"]
    }
  ],
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"]
}<p>Este cartão de agente revela vários aspectos importantes do agente de arquivamento da Elastic. O agente se identifica como "Archie Archivist" e declara claramente seu propósito: ajudar a encontrar documentos de notícias históricas em um índice do Elasticsearch. O cartão especifica o provedor (Elastic) e a versão do protocolo (0.3.0), garantindo a compatibilidade com outros agentes compatíveis com A2A. Mais importante ainda, a matriz <code>skills</code> enumera as capacidades específicas que este agente oferece, incluindo funcionalidades de pesquisa poderosas e exploração inteligente de índices. Cada habilidade define quais modos de entrada e saída ela suporta, permitindo que os clientes entendam exatamente como se comunicar com esse agente. Este agente deriva do serviço Agent Builder da Elastic, que fornece um conjunto de ferramentas nativas com suporte a LLM e endpoints de API para interagir com seu armazenamento de dados, e não apenas para recuperar dados dele. O acesso aos agentes A2A no Elasticsearch pode ser encontrado <a href="https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server">aqui</a>.</p><h4>2. Negociação</h4><p>Clientes e agentes precisam concordar com os métodos de comunicação — sejam as interações realizadas por meio de texto, formulários, iframes ou até mesmo áudio/vídeo — para garantir a interação adequada do usuário e a troca de dados. Essa negociação ocorre no início da colaboração entre os agentes e estabelece os protocolos que irão reger sua interação ao longo do fluxo de trabalho. Por exemplo, um agente de atendimento ao cliente baseado em voz pode negociar para se comunicar por meio de fluxos de áudio, enquanto um agente de análise de dados pode preferir JSON estruturado. O processo de negociação garante que ambas as partes possam trocar informações de forma eficaz, num formato que se adeque às suas capacidades e às exigências da tarefa em questão.</p><p>As funcionalidades listadas no trecho JSON acima possuem esquemas de entrada e saída; estes definem uma expectativa de como outros agentes devem interagir com este agente.</p><h4>3. Gestão de tarefas e estados</h4><p>Clientes e agentes precisam de mecanismos para comunicar o status das tarefas, alterações e dependências ao longo da execução das mesmas. Isso inclui gerenciar todo o ciclo de vida de uma tarefa, desde a criação e atribuição até as atualizações de progresso e alterações de status. Os status típicos incluem pendente, em andamento, concluído ou reprovado. O sistema também deve rastrear as dependências entre as tarefas para garantir que o trabalho prévio seja concluído antes do início das tarefas dependentes. O tratamento de erros e a lógica de repetição também são componentes essenciais, permitindo que o sistema se recupere de forma adequada de falhas e continue progredindo em direção ao objetivo principal.</p><p>Exemplo de mensagem de tarefa:</p>{
  "message_id": "msg_789xyz",
  "message_type": "task_request",
  "sender": "news_chief",
  "receiver": "researcher_agent",
  "timestamp": "2025-09-30T10:15:00Z",
  "payload": {
    "task_id": "task_456abc",
    "capability": "fact_gathering",
    "parameters": {
      "query": "renewable energy adoption rates in Europe 2024",
      "sources": ["eurostat", "iea", "ember"],
      "depth": "comprehensive"
    },
    "context": {
      "story_id": "story_123",
      "deadline": "2025-09-30T18:00:00Z",
      "priority": "high"
    }
  }
}<p>Esta mensagem de tarefa de exemplo demonstra vários aspectos importantes da comunicação A2A.</p><ul><li><p>A estrutura <strong>da mensagem</strong> inclui metadados como um identificador único da mensagem, o tipo de mensagem que está sendo enviada, a identificação do remetente e do destinatário e um registro de data e hora para rastreamento e depuração.</p></li><li><p>A <strong>carga útil</strong> contém as informações reais da tarefa, especificando qual funcionalidade está sendo invocada no agente remoto e fornecendo os parâmetros necessários para executar essa funcionalidade.</p></li><li><p>A seção <strong>de contexto</strong> fornece informações adicionais que ajudam o agente receptor a entender o fluxo de trabalho mais amplo, incluindo prazos e níveis de prioridade que orientam a forma como o agente deve alocar seus recursos e programar seu trabalho.</p></li></ul><h4>4. Colaboração</h4><p>Clientes e agentes <strong>devem</strong> dar suporte a uma interação dinâmica, porém estruturada, permitindo que os agentes solicitem esclarecimentos, informações ou subações do cliente, de outros agentes ou de usuários. Isso cria um ambiente colaborativo onde os agentes podem fazer perguntas de acompanhamento quando as instruções iniciais forem ambíguas, solicitar contexto adicional para tomar melhores decisões, delegar subtarefas a outros agentes com conhecimento mais adequado e fornecer resultados intermediários para feedback antes de prosseguir com a tarefa completa. Essa comunicação multidirecional garante que os agentes não trabalhem isoladamente, mas sim que estejam engajados em um diálogo contínuo que leva a melhores resultados.</p><h3>Comunicação distribuída, ponto a ponto</h3><p>A tecnologia A2A permite a comunicação distribuída, na qual os agentes podem ser hospedados por diferentes organizações, com alguns agentes mantidos internamente, enquanto outros são fornecidos por serviços de terceiros. Esses agentes podem ser executados em diferentes infraestruturas, abrangendo potencialmente vários provedores de nuvem ou centros de dados locais. Eles podem usar diferentes modelos de aprendizado de máquina subjacentes, com alguns agentes baseados em modelos GPT, outros em Claude e outros ainda em alternativas de código aberto. Os agentes podem até operar em diferentes regiões geográficas para cumprir os requisitos de soberania de dados ou reduzir a latência. Apesar dessa diversidade, todos os agentes concordam com um protocolo de comunicação comum para a troca de informações, garantindo a interoperabilidade independentemente dos detalhes de implementação. Essa arquitetura distribuída proporciona flexibilidade na forma como os sistemas são construídos e implantados, permitindo que as organizações combinem os melhores agentes e infraestrutura para suas necessidades específicas.</p><p>Esta é a arquitetura final do aplicativo da redação:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt74d59cd9267f54d8/6a17f2de505ac31129ad8c71/82e01a0d9746038eafd69d11177042b5390507ae-1600x838.png" alt="" /><h2>Seção 3: Protocolo de Contexto do Modelo (MCP)</h2><h3>Definição e propósito</h3><p>O Protocolo de Contexto do Modelo (MCP) é um protocolo padronizado desenvolvido pela Anthropic para aprimorar e capacitar um LLM individual com ferramentas, recursos e instruções definidos pelo usuário, entre outras adições suplementares ao código-fonte. O MCP fornece uma interface universal entre modelos de linguagem e os recursos externos necessários para que eles concluam tarefas com eficácia. Este <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">artigo</a> descreve o estado atual do MCP com exemplos de casos de uso, tendências emergentes e a implementação da própria Elastic.</p><h3>Conceitos básicos do MCP</h3><p>O MCP opera em uma arquitetura cliente-servidor com três componentes principais:</p><ul><li><p><strong>Clientes:</strong> aplicativos (como o Claude Desktop ou aplicativos de IA personalizados) que se conectam aos servidores MCP para acessar suas funcionalidades.</p></li><li><p><strong>Servidores</strong>: aplicações que expõem recursos, ferramentas e instruções para modelos de linguagem. Cada servidor é especializado em fornecer acesso a funcionalidades ou fontes de dados específicas.</p><ul><li><p><strong>Ferramentas</strong>: funções definidas pelo usuário que os modelos podem invocar para executar ações, como pesquisar bancos de dados, chamar APIs externas ou realizar transformações nos dados.</p></li><li><p><strong>Recursos:</strong> fontes de dados que os modelos podem ler, fornecidas com dados dinâmicos ou estáticos e acessadas por meio de padrões de URI (semelhantes a rotas REST).</p></li><li><p><strong>Instruções: </strong>modelos de instruções reutilizáveis com variáveis que orientam o modelo na realização de tarefas específicas.</p></li></ul></li></ul><h3>Padrão de solicitação-resposta</h3><p>O MCP segue um padrão de interação de solicitação-resposta familiar, semelhante às APIs REST. O cliente (LLM) solicita um recurso ou invoca uma ferramenta; em seguida, o servidor MCP processa a solicitação e retorna o resultado, que o LLM utiliza para continuar sua tarefa. Este modelo centralizado com servidores periféricos oferece um padrão de integração mais simples em comparação com a comunicação entre agentes ponto a ponto.</p><h3>MCP na redação</h3><p>Em nosso exemplo de redação, os agentes individuais usam servidores MCP para acessar as ferramentas e os dados de que precisam:</p><ul><li><p><strong>O Agente de Pesquisa</strong> utiliza:</p><ul><li><p>Servidor MCP da API de notícias (acesso a bancos de dados de notícias)</p></li><li><p>Servidor MCP de verificação de fatos (verifica alegações em fontes confiáveis)</p></li><li><p>Servidor MCP de base de dados académica (artigos académicos e investigação)</p></li></ul></li><li><p><strong>O agente repórter</strong> utiliza:</p><ul><li><p>Guia de Estilo do Servidor MCP (padrões de redação para redações)</p></li><li><p>Servidor MCP de modelos (modelos e formatos de artigos)</p></li><li><p>Servidor MCP da Biblioteca de Imagens (fotos e gráficos de banco de imagens)</p></li></ul></li><li><p><strong>O Editor Agent</strong> utiliza:</p><ul><li><p>Servidor MCP do Verificador Gramatical (ferramentas de qualidade linguística)</p></li><li><p>Servidor MCP de Detecção de Plágio (verificação de originalidade)</p></li><li><p>Servidor MCP de Análise de SEO (otimização de títulos e palavras-chave)</p></li></ul></li><li><p><strong>O Publisher Agent</strong> utiliza:</p><ul><li><p>Servidor CMS MCP (API do sistema de gerenciamento de conteúdo)</p></li><li><p>Servidor CI/CD MCP (pipeline de implantação)</p></li><li><p>Servidor MCP de análise (rastreamento e monitoramento)</p></li></ul></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt195fe0bd36d36a48/6a17f2e0b1e113afe479f36c/b67311e3b58b27f9eb1b42a7b1dbad47ef3be4ad-808x535.png" alt="" /><h2>
Seção 4: comparação de arquiteturas</h2><h3>Quando usar o A2A</h3><p>A arquitetura A2A se destaca em <strong>cenários que exigem colaboração multiagente genuína</strong>. Fluxos de trabalho com várias etapas que exigem coordenação se beneficiam muito do A2A, principalmente quando as tarefas envolvem várias etapas sequenciais ou paralelas, fluxos de trabalho que exigem iteração e refinamento, e processos com pontos de verificação e necessidades de validação. Em nosso exemplo de redação, o fluxo de trabalho da matéria exige que o Repórter escreva, mas pode precisar consultar o Pesquisador se a confiança em certos fatos for baixa, depois passar para o Editor e, finalmente, para o Editor-Chefe.</p><p><strong>A especialização em domínios específicos em diversas áreas</strong> é outro caso de uso importante para o A2A. Quando vários especialistas em diversas áreas são necessários para realizar uma tarefa maior, com cada agente trazendo conhecimento profundo do domínio e capacidades de raciocínio especializadas para diferentes aspectos, o A2A fornece a estrutura de coordenação necessária para fazer essas conexões. A redação exemplifica isso perfeitamente: o pesquisador se especializa na coleta de informações, o repórter na redação e o editor no controle de qualidade — cada um com uma especialização distinta.</p><p>A necessidade de comportamento autônomo dos agentes torna o A2A particularmente valioso. Agentes capazes<strong> de tomar decisões independentes, demonstrar comportamento proativo com base em condições variáveis e se adaptar dinamicamente aos requisitos do fluxo de trabalho</strong> prosperam em uma arquitetura A2A. A escalabilidade horizontal de funções especializadas é outra vantagem fundamental: em vez de ter um único agente que domina todas as tarefas, vários agentes especializados trabalham em coordenação, e várias instâncias do mesmo agente podem lidar com subtarefas de forma assíncrona. Durante a cobertura de notícias de última hora em nossa redação, por exemplo, vários repórteres podem trabalhar simultaneamente em diferentes ângulos da mesma história.</p><p>Por fim, tarefas que exigem colaboração genuína entre múltiplos agentes são ideais para o A2A. Isso inclui mecanismos <a href="https://arxiv.org/abs/2404.18796">de avaliação do LLM como júri</a> , sistemas de consenso e votação, e <strong>resolução colaborativa de problemas onde múltiplas perspectivas são necessárias</strong> para alcançar o melhor resultado.</p><h3>Quando usar o MCP</h3><p>O Protocolo de Contexto de Modelo é ideal para ampliar as capacidades de um único modelo de IA. Quando um único modelo de IA precisa acessar várias ferramentas e fontes de dados, o MCP oferece a solução perfeita, combinando raciocínio centralizado com ferramentas distribuídas e integração de ferramentas simplificada. Em nosso exemplo de redação, o Agente Pesquisador (um modelo) precisa de acesso a múltiplas fontes de dados, incluindo a API de Notícias, serviços de verificação de fatos e bases de dados acadêmicas — todas acessadas por meio de servidores MCP padronizados.</p><p>A integração de ferramentas padronizadas torna-se uma prioridade quando o amplo compartilhamento e a reutilização dessas integrações são importantes. O MCP se destaca aqui com seu ecossistema de servidores MCP pré-configurados, que reduzem significativamente o tempo de desenvolvimento para integrações comuns. Quando simplicidade e facilidade de manutenção são necessárias, os padrões de solicitação-resposta do MCP são familiares aos desenvolvedores, mais fáceis de entender e depurar do que sistemas distribuídos e apresentam menor complexidade operacional.</p><p>Por fim, o MCP costuma ser oferecido por fornecedores de software para facilitar a comunicação remota com seus sistemas. Esses servidores MCP oferecidos pelo provedor reduzem significativamente o tempo de integração e desenvolvimento, ao mesmo tempo que oferecem uma interface padronizada para sistemas proprietários, tornando a integração muito mais simples do que o desenvolvimento de APIs personalizadas.</p><h3>Quando usar ambos (MCP da A2A ❤️)</h3><p>Muitos sistemas sofisticados se beneficiam da combinação de A2A e MCP, conforme observado na <a href="https://a2a-protocol.org/latest/topics/a2a-and-mcp/">documentação da A2A sobre integração com MCP</a>. Sistemas que exigem tanto coordenação quanto padronização são candidatos ideais para uma abordagem híbrida. O A2A lida com a coordenação de agentes e a orquestração de fluxos de trabalho, enquanto o MCP fornece acesso a ferramentas para agentes individuais. Em nosso exemplo de redação, os agentes se coordenam por meio do sistema A2A (atendimento ao usuário), com o fluxo de trabalho indo do repórter para o pesquisador, para o editor e, finalmente, para o editor-chefe. No entanto, cada agente utiliza servidores MCP para suas ferramentas especializadas, criando uma clara separação arquitetural.</p><p>A presença de múltiplos agentes especializados, cada um utilizando o MCP para acesso a ferramentas, representa um padrão comum onde existe uma camada de coordenação de agentes gerenciada pelo A2A e uma camada de acesso a ferramentas gerenciada pelo MCP. Essa clara separação de responsabilidades torna os sistemas mais fáceis de entender e manter.</p><p>Os benefícios de combinar ambas as abordagens são substanciais. Você obtém os benefícios organizacionais dos sistemas multiagentes, incluindo especialização, autonomia e processamento paralelo, ao mesmo tempo que desfruta dos benefícios de padronização e ecossistema do MCP, como integração de ferramentas e acesso a recursos. Existe uma clara separação entre a coordenação de agentes (A2A) e o acesso a recursos (MCP) e, o que é importante, a A2A não é necessária para tarefas menores, como o acesso à API isoladamente — a MCP lida com essas tarefas de forma eficiente, sem a sobrecarga da orquestração multiagente.</p><p><strong>FAQ: A2A vs. MCP - Casos de uso</strong></p><p>Recurso</p><p>Agente para Agente (A2A)</p><p>Protocolo de Contexto do Modelo (MCP)</p><p>Híbrido (A2A + MCP)</p><p>Objetivo principal</p><p>Coordenação multiagente: Permite que uma equipe de agentes especializados trabalhe em conjunto em fluxos de trabalho complexos e com várias etapas.</p><p>Aprimoramento para agente único: Amplia a capacidade de um único LLM/Agente com ferramentas, recursos e dados externos.</p><p>Força combinada: A2A gerencia o fluxo de trabalho da equipe, enquanto a MCP fornece ferramentas para cada membro da equipe.</p><p>Exemplo de equipe de redação</p><p>A cadeia de fluxo de trabalho: Chefe de Notícias → Repórter → Pesquisador → Editor → Publicador. Esta é a camada de coordenação.</p><p>Ferramentas do agente individual: O Agente Repórter acessa o servidor de guia de estilo e o servidor de modelos (via MCP). Esta é a camada de acesso à ferramenta.</p><p>O sistema completo: o repórter coordena com o editor (A2A) e utiliza o servidor MCP da biblioteca de imagens para encontrar uma imagem para a matéria.</p><p>Quando usar qual</p><p>Quando você precisa de colaboração genuína, iteração e aprimoramento, ou de conhecimento especializado dividido entre vários agentes.</p><p>Quando um único agente precisa acessar várias ferramentas e fontes de dados ou requer integração padronizada com sistemas proprietários.</p><p>Quando você precisa dos benefícios organizacionais dos sistemas multiagentes e dos benefícios de padronização e ecossistema do MCP.</p><p>Benefício principal</p><p>Autonomia e escalabilidade: Os agentes podem tomar decisões independentes e o sistema permite a escalabilidade horizontal de funções especializadas.</p><p>Simplicidade e padronização: Mais fácil de depurar e manter devido ao raciocínio centralizado, além de fornecer uma interface universal para recursos.</p><p>Separação clara de responsabilidades: torna o sistema mais fácil de entender: A2A = trabalho em equipe, MCP = acesso à ferramenta.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1735ea5de41e10fd/6a17f2e26864a4125cb688c4/ddf6a29b1107ac6a63e94ecef703abc561a29e1e-986x656.png" alt="" /><h2>Conclusão</h2><p>Esta é a primeira parte de um artigo em duas seções que aborda a implementação de agentes baseados em A2A, reforçados com servidores MCP para fornecer suporte e acesso externo a dados e ferramentas. A próxima parte explorará o código real para demonstrar como eles funcionam em conjunto, simulando as atividades de uma redação online. Embora ambas as estruturas sejam extremamente capazes e flexíveis por si só, você verá o quanto elas se complementam quando trabalham em conjunto.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-newsroom-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-newsroom-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Justin Castilla]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2716d804698ec878/6a17f2e41480095fd7b48888/9f938d8e2f0fdf7509edf028816c48bdbc8b3fc7-1600x900.png" length="0" type="image/png"/>
    <pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Construindo um agente de conhecimento com recuperação semântica usando Mastra e Elasticsearch.]]></title>
    <description><![CDATA[Aprenda como construir um agente de conhecimento com recuperação semântica usando Mastra e Elasticsearch como armazenamento vetorial para memória e recuperação de informações.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/context-engineering-overview">A Engenharia de Contexto</a> está se tornando cada vez mais importante na construção de agentes e arquiteturas de IA confiáveis. À medida que os modelos se tornam cada vez melhores, sua eficácia e confiabilidade dependem menos dos dados de treinamento e mais de quão bem eles estão fundamentados no contexto correto. Agentes que conseguem recuperar e aplicar as informações mais relevantes no momento certo têm muito mais probabilidade de produzir resultados precisos e confiáveis.</p><p>Neste blog, usaremos <a href="https://mastra.ai/">o Mastra</a> para construir um agente de conhecimento que memoriza o que os usuários dizem e consegue recuperar informações relevantes posteriormente, utilizando o Elasticsearch como backend de memória e recuperação. Você pode facilmente estender esse mesmo conceito a casos de uso do mundo real, como agentes de suporte que conseguem se lembrar de conversas e soluções anteriores, permitindo que eles personalizem as respostas para usuários específicos ou apresentem soluções mais rapidamente com base no contexto prévio.</p><p>Acompanhe aqui como construir isso passo a passo. Se você se perder ou simplesmente quiser executar um exemplo finalizado, confira o repositório <a href="https://github.com/jdarmada/getting-started-mastra-elastic/tree/main">aqui</a>.</p><h2>O que é Mastra?</h2><p>Mastra é um framework TypeScript de código aberto para a construção de agentes de IA com componentes intercambiáveis para raciocínio, memória e ferramentas. Seu recurso <a href="https://mastra.ai/docs/memory/semantic-recall">de recuperação semântica</a> permite que os agentes se lembrem e recuperem interações passadas, armazenando mensagens como representações vetoriais em um banco de dados vetorial. Isso permite que os agentes mantenham o contexto e a continuidade da conversa a longo prazo. O Elasticsearch é um excelente armazenamento de vetores para habilitar esse recurso, pois oferece suporte a buscas vetoriais densas e eficientes. Quando a recuperação semântica é acionada, o agente extrai mensagens relevantes do passado para a janela de contexto do modelo, permitindo que o modelo use esse contexto recuperado como base para seu raciocínio e respostas.</p><h2>O que você precisa para começar</h2><ul><li><p>Node v18+</p></li><li><p>Elasticsearch (versão 8.15 ou mais recente)</p></li><li><p>Chave da API do Elasticsearch</p></li><li><p><a href="https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key">Chave da API OpenAI</a></p></li></ul><p>Observação: você precisará disso porque a demonstração usa o provedor OpenAI, mas o Mastra é compatível com outros SDKs de IA e provedores de modelos da comunidade, então você pode facilmente trocá-lo dependendo da sua configuração.</p><h2>Construindo um projeto Mastra</h2><p>Usaremos a CLI integrada do Mastra para fornecer a estrutura básica do nosso projeto. Execute o comando:</p>npm create mastra@latest<p>Você receberá uma série de instruções, começando com:</p><p>1. Dê um nome ao seu projeto.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt87f941f654d03827/6a16f7af67045b214d45bfa1/2b9fe559e0276140dd539e24f916a73c60870405-620x84.png" alt="Como nomear um prompt no aplicativo Mastra" /><p>2. Podemos manter esta opção padrão; fique à vontade para deixar este campo em branco.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7dbb3d4f27435cac/6a16f7b0cdacbf29497d27de/e04729eb03bce8499e973e18c28642402340d0e5-852x68.png" alt="Indicar à Mastra onde guardar os arquivos de prompts." /><p>3. Para este projeto, usaremos um modelo fornecido pela OpenAI.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1f654f6cb9397e94/6a16f7b2964cea899a08b942/a86596a469a71bdf8bd99cbaf528d0f0cf7272c0-436x222.png" alt="Selecionando um modelo fornecido pela OpenAI no Mastra" /><p>4. Selecione a opção “Ignorar por enquanto”, pois armazenaremos todas as nossas variáveis de ambiente em um arquivo `.env` que configuraremos em uma etapa posterior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltff106117521a3519/6a16f7b3c1e8a5031af880d8/02b19ccc34af0bdacf52fd94b519d036540ca2e6-426x114.png" alt="Por enquanto, vou optar por ignorar a chave da OpenAI." /><p>5. Também podemos ignorar esta opção.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda7d9c51c3878d7/6a16f7b450916809dbe1b892/b3fe63d19d270bc2e0de1dd92033bf8b26750819-990x208.png" alt="" /><p>Assim que a inicialização estiver concluída, podemos passar para a próxima etapa.</p><h3>Instalando dependências</h3><p>Em seguida, precisamos instalar algumas dependências:</p>npm install ai @ai-sdk/openai @elastic/elasticsearch dotenv<ul><li><p><code>ai</code> - Pacote Core AI SDK que fornece ferramentas para gerenciar modelos de IA, prompts e fluxos de trabalho em JavaScript/TypeScript. O Mastra é construído sobre o <a href="https://ai-sdk.dev/">SDK de IA</a> da Vercel, portanto, precisamos dessa dependência para permitir as interações do modelo com o seu agente.</p></li><li><p><code>@ai-sdk/openai</code> - Plugin que conecta o SDK de IA aos modelos da OpenAI (como GPT-4, GPT-4o, etc.), permitindo chamadas à API usando sua chave de API da OpenAI.</p></li><li><p><code>@elastic/elasticsearch</code> - <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/javascript">Cliente oficial do Elasticsearch para Node.js</a>, Utilizado para conectar-se ao seu Elastic Cloud ou cluster local para indexação, pesquisa e operações vetoriais.</p></li><li><p><code>dotenv</code> - Carrega variáveis de ambiente de um arquivo .env arquivo em process.env, permitindo que você insira credenciais com segurança, como chaves de API e endpoints do Elasticsearch.</p></li></ul><h3>Configurando variáveis de ambiente</h3><p>Crie um arquivo <code>.env</code> no diretório raiz do seu projeto, caso ainda não exista um. Alternativamente, você pode copiar e renomear o exemplo <code>.env</code> que eu forneci no <a href="https://github.com/jdarmada/getting-started-mastra-elastic/blob/main/.env.example">repositório</a>. Neste arquivo, podemos adicionar as seguintes variáveis:</p>ELASTICSEARCH_ENDPOINT="your-endpoint-here"
ELASTICSEARCH_API_KEY="your-key-here"
OPENAI_API_KEY="your-key-here"<p>Isso conclui a configuração básica. A partir daqui, você já pode começar a construir e orquestrar agentes. Vamos dar um passo além e adicionar o Elasticsearch como camada de armazenamento e busca vetorial.</p><h2>Adicionando o Elasticsearch como armazenamento vetorial.</h2><p>Crie uma nova pasta chamada <code>stores</code> e, dentro dela, adicione este <a href="https://github.com/jdarmada/getting-started-mastra-elastic/blob/main/src/mastra/stores/elastic-store.ts">arquivo</a>. Antes que a Mastra e a Elastic lancem uma integração oficial de armazenamento vetorial do Elasticsearch, <a href="https://github.com/abhiaiyer91">Abhi Aiyer</a>(CTO da Mastra) compartilhou esta classe protótipo inicial chamada <code>ElasticVector</code>. Em termos simples, ele conecta a abstração de memória do Mastra aos recursos de vetores densos do Elasticsearch, permitindo que os desenvolvedores utilizem o Elasticsearch como banco de dados de vetores para seus agentes.</p><p>Vamos analisar mais detalhadamente as partes importantes da integração:</p><h3>Ingestão do cliente Elasticsearch</h3><p>Esta seção define a classe <code>ElasticVector</code> e configura a conexão do cliente Elasticsearch com suporte para implantações padrão e sem servidor.</p>export interface ElasticVectorConfig extends ClientOptions {
    /**
     * Explicitly specify if connecting to Elasticsearch Serverless.
     * If not provided, will be auto-detected on first use.
     */
    isServerless?: boolean;
    
    /**
     * Maximum documents to count accurately when describing indices.
     * Higher values provide accurate counts but may impact performance on large indices.
     * 
     * @default 10000
     */
    maxCountAccuracy?: number;
}

export class ElasticVector extends MastraVector {
    private client: Client;
    private isServerless: boolean | undefined;
    private deploymentChecked: boolean = false;
    private readonly maxCountAccuracy: number;

    constructor(config: ElasticVectorConfig) {
        super();
        this.client = new Client(config);
        this.isServerless = config.isServerless;
        this.maxCountAccuracy = config.maxCountAccuracy ?? 10000;
    }
}<ul><li><p><code>ElasticVectorConfig extends ClientOptions</code>Isso cria uma nova interface de configuração que herda todas as opções do cliente Elasticsearch (como <code>node</code>, <code>auth</code>, <code>requestTimeout</code>) e adiciona nossas propriedades personalizadas. Isso significa que os usuários podem passar qualquer configuração válida do Elasticsearch juntamente com nossas opções específicas para ambientes sem servidor.</p></li><li><p><code>extends MastraVector</code>Isso permite que <code>ElasticVector</code> herde da classe base <code>MastraVector</code> do Mastra, que é uma interface comum à qual todas as integrações de armazenamento vetorial estão em conformidade. Isso garante que o Elasticsearch se comporte como qualquer outro backend vetorial do Mastra da perspectiva do agente.</p></li><li><p><code>private client: Client</code>Esta é uma propriedade privada que contém uma instância do cliente JavaScript do Elasticsearch. Isso permite que a classe se comunique diretamente com o seu cluster.</p></li><li><p><code>isServerless</code> e <code>deploymentChecked</code>: Essas propriedades funcionam em conjunto para detectar e armazenar em cache se estamos conectados a uma implantação do Elasticsearch sem servidor ou padrão. Essa detecção ocorre automaticamente no primeiro uso ou pode ser configurada explicitamente.</p></li><li><p><code>constructor(config: ClientOptions)</code>: Este construtor recebe um objeto de configuração (contendo suas credenciais do Elasticsearch e configurações opcionais sem servidor) e o usa para inicializar o cliente na linha <code>this.client = new Client(config)</code>.</p></li><li><p><code>super()</code>Isso chama o construtor base do Mastra, portanto, ele herda o registro de logs, os auxiliares de validação e outros recursos internos.</p></li></ul><p>Neste ponto, Mastra sabe que existe uma nova loja de vetores chamada <code>ElasticVector</code></p><h3>Detecção do tipo de implantação</h3><p>Antes de criar os índices, o adaptador detecta automaticamente se você está usando o Elasticsearch padrão ou o Elasticsearch Serverless. Isso é importante porque as implantações sem servidor não permitem a configuração manual de shards.</p>private async detectServerless(): Promise&lt;boolean&gt; {
    // Return cached result if already detected
    if (this.deploymentChecked) {
        return this.isServerless ?? false;
    }

    // Use explicit configuration if provided
    if (this.isServerless !== undefined) {
        this.deploymentChecked = true;
        this.logger?.info(
            `Using explicit deployment type: ${this.isServerless ? 'Serverless' : 'Standard'}`
        );
        return this.isServerless;
    }

    try {
        const info = await this.client.info();
        
        // Primary detection: build flavor (most reliable)
        const isBuildFlavorServerless = info.version?.build_flavor === 'serverless';
        
        // Secondary detection: tagline (fallback)
        const isTaglineServerless = info.tagline?.toLowerCase().includes('serverless') ?? false;
        
        this.isServerless = isBuildFlavorServerless || isTaglineServerless;
        this.deploymentChecked = true;
        
        this.logger?.info(
            `Auto-detected ${this.isServerless ? 'Serverless' : 'Standard'} Elasticsearch deployment`,
            { 
                buildFlavor: info.version?.build_flavor, 
                version: info.version?.number,
                detectionMethod: isBuildFlavorServerless ? 'build_flavor' : 'tagline'
            }
        );
        
        return this.isServerless;
    } catch (error) {
        this.logger?.warn(
            'Could not auto-detect deployment type, assuming Standard Elasticsearch. ' +
            'Set isServerless: true explicitly in config if using Serverless.',
            { error: error instanceof Error ? error.message : String(error) }
        );
        this.isServerless = false;
        this.deploymentChecked = true;
        return false;
    }
}<p>O que está acontecendo:</p><ul><li><p>Primeiro verifica se você definiu explicitamente <code>isServerless</code> na configuração (ignora a detecção automática).</p></li><li><p>Chama a API <code>info()</code> do Elasticsearch para obter informações do cluster.</p></li><li><p>Verifica o <code>build_flavor field</code> (implantações sem servidor retornam <code>serverless</code>)</p></li><li><p>Se a opção de build não estiver disponível, a solução é verificar a descrição da versão.</p></li><li><p>Armazena o resultado em cache para evitar chamadas repetidas à API.</p></li><li><p>Se a detecção falhar, a implantação padrão será utilizada por padrão.</p></li></ul><p> Exemplo de uso:</p>// Option 1: Auto-detect (recommended)
const vector = new ElasticVector({
    node: 'https://your-cluster.es.cloud',
    auth: { apiKey: 'your-api-key' }
});
// Detection happens automatically on first index operation

// Option 2: Explicit configuration (faster startup)
const vector = new ElasticVector({
    node: 'https://your-serverless.es.cloud',
    auth: { apiKey: 'your-api-key' },
    isServerless: true  // Skips auto-detection
});<h3>Criando o armazenamento de “memória” no Elasticsearch</h3><p>A função abaixo configura um índice Elasticsearch para armazenar embeddings. Verifica se o índice já existe. Caso contrário, cria um com o mapeamento abaixo que contém um campo <code>dense_vector</code> para armazenar embeddings e métricas de similaridade personalizadas.</p><p>Algumas coisas a ter em conta:</p><ul><li><p>O parâmetro <code>dimension</code> representa o comprimento de cada vetor de incorporação, que depende do modelo de incorporação que você está usando. Em nosso caso, geraremos embeddings usando o modelo <code>text-embedding-3-small</code> da OpenAI, que produz vetores de tamanho <code>1536</code>. Usaremos esse valor como padrão.</p></li><li><p>A variável <code>similarity</code> usada no mapeamento abaixo é definida pela função auxiliar c<code>onst similarity = this.mapMetricToSimilarity(metric)</code>, que recebe o valor do parâmetro <code>metric</code> e o converte em uma palavra-chave compatível com o Elasticsearch para a métrica de distância escolhida.</p><ul><li><p>Por exemplo: Mastra usa termos gerais para similaridade de vetores como <code>cosine</code>, <code>euclidean</code> e <code>dotproduct</code>. Se passássemos a métrica <code>euclidean</code> diretamente para o mapeamento do Elasticsearch, ele geraria um erro porque o Elasticsearch espera que a palavra-chave <code>l2_norm</code> represente a distância euclidiana.</p></li></ul></li><li><p>Compatibilidade com ambientes sem servidor: o código omite automaticamente as configurações de shard e réplica para implantações sem servidor, pois estas são gerenciadas automaticamente pelo Elasticsearch Serverless.</p></li></ul>async createIndex(params: CreateIndexParams): Promise&lt;void&gt; {
    const { indexName, dimension = 1536, metric = 'cosine' } = params;

    try {
        const exists = await this.client.indices.exists({ index: indexName });

        if (exists) {
            try {
                await this.validateExistingIndex(indexName, dimension, metric);
                this.logger?.info(`Index "${indexName}" already exists and is valid`);
                return;
            } catch (validationError) {
                throw new Error(
                    `Index "${indexName}" exists but does not match the required configuration: ${
                        validationError instanceof Error ? validationError.message : String(validationError)
                    }`
                );
            }
        }

        const isServerless = await this.detectServerless();
        const similarity = this.mapMetricToSimilarity(metric);

        const indexConfig: any = {
            index: indexName,
            mappings: {
                properties: {
                    vector: {
                        type: 'dense_vector',
                        dims: dimension,
                        index: true,
                        similarity: similarity,
                    },
                    metadata: {
                        type: 'object',
                        enabled: true,
                        dynamic: true, // Allows flexible metadata structures
                    },
                },
            },
        };

        // Only configure shards/replicas for non-serverless deployments
        // Serverless manages infrastructure automatically
        if (!isServerless) {
            indexConfig.settings = {
                number_of_shards: 1,
                number_of_replicas: 0, // Increase for production HA deployments
            };
        }

        await this.client.indices.create(indexConfig);

        this.logger?.info(
            `Created ${isServerless ? 'Serverless' : 'Standard'} Elasticsearch index "${indexName}"`,
            { dimension, metric, similarity }
        );
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to create index "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to create index "${indexName}": ${errorMessage}`);
    }
}<h3>Armazenar uma nova memória ou anotação após uma interação.</h3><p>Esta função recebe novos embeddings gerados após cada interação, juntamente com os metadados, e os insere ou atualiza no índice usando a API <code>bulk</code> do Elastic. A API <code>bulk</code> agrupa várias operações de gravação em uma única solicitação; essa melhoria no desempenho de indexação garante que as atualizações permaneçam eficientes à medida que a memória do nosso agente continua a crescer.</p>async upsert(params: UpsertVectorParams): Promise&lt;string[]&gt; {
    const { indexName, vectors, metadata = [], ids } = params;

    try {
        // Generate unique IDs if not provided
        const vectorIds = ids || vectors.map((_, i) =&gt; 
            `vec_${Date.now()}_${i}_${Math.random().toString(36).substr(2, 9)}`
        );

        const operations = vectors.flatMap((vec, index) =&gt; [
            { index: { _index: indexName, _id: vectorIds[index] } },
            {
                vector: vec,
                metadata: metadata[index] || {},
            },
        ]);

        const response = await this.client.bulk({
            refresh: true,
            operations,
        });

        if (response.errors) {
            const erroredItems = response.items.filter((item: any) =&gt; item.index?.error);
            const erroredIds = erroredItems.map((item: any) =&gt; item.index?._id);
            const errorDetails = erroredItems.slice(0, 3).map((item: any) =&gt; ({
                id: item.index?._id,
                error: item.index?.error?.reason || item.index?.error,
                type: item.index?.error?.type
            }));
            
            const errorMessage = `Failed to upsert ${erroredIds.length}/${vectors.length} vectors`;
            console.error(`${errorMessage}. Sample errors:`, JSON.stringify(errorDetails, null, 2));
            this.logger?.error(errorMessage, { 
                failedCount: erroredIds.length, 
                totalCount: vectors.length,
                sampleErrors: errorDetails 
            });
            
            // Still return successfully inserted IDs
            const successfulIds = vectorIds.filter((id, idx) =&gt; 
                !erroredIds.includes(id)
            );
            
            if (successfulIds.length === 0) {
                throw new Error(`${errorMessage}. All operations failed. See logs for details.`);
            }
            
            return successfulIds;
        }

        this.logger?.info(`Successfully upserted ${vectors.length} vectors to "${indexName}"`);
        return vectorIds;
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
    }
}<h3>Consultar vetores semelhantes para recuperação semântica</h3><p>Essa função é o núcleo do recurso de recuperação semântica. O agente utiliza a busca vetorial para encontrar incorporações armazenadas semelhantes em nosso índice.</p>async query(params: QueryVectorParams&lt;any&gt;): Promise&lt;QueryResult[]&gt; {
    const { indexName, queryVector, topK = 10, filter, includeVector = false } = params;

    try {
        const knnQuery: any = {
            field: 'vector',
            query_vector: queryVector,
            k: topK,
            num_candidates: Math.max(topK * 10, 100), // Search more candidates for better recall
        };

        // Apply metadata filters if provided
        if (filter) {
            knnQuery.filter = this.buildElasticFilter(filter);
        }

        const sourceFields = ['metadata'];
        if (includeVector) {
            sourceFields.push('vector');
        }

        const response = await this.client.search({
            index: indexName,
            knn: knnQuery,
            size: topK,
            _source: sourceFields,
        });

        const results = response.hits.hits.map((hit: any) =&gt; ({
            id: hit._id,
            score: hit._score || 0,
            metadata: hit._source?.metadata || {},
            vector: includeVector ? hit._source?.vector : undefined,
        }));

        this.logger?.debug(`Query returned ${results.length} results from "${indexName}"`);
        return results;
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
    }
}<p>Por dentro do capô:</p><ul><li><p>Executa uma consulta <a href="https://www.elastic.co/docs/solutions/search/vector/knn">kNN</a> (k-vizinhos mais próximos) usando a API <code>knn</code> no Elasticsearch.</p></li><li><p>Recupera os K vetores mais semelhantes ao vetor de consulta de entrada.</p></li><li><p>Opcionalmente, aplica filtros de metadados para refinar os resultados (por exemplo, pesquisar apenas dentro de uma categoria ou intervalo de tempo específico).</p></li><li><p>Retorna resultados estruturados, incluindo o ID do documento, a pontuação de similaridade e os metadados armazenados.</p></li></ul><h2>Criando o agente de conhecimento</h2><p>Agora que vimos a conexão entre Mastra e Elasticsearch por meio da integração <code>ElasticVector</code> , vamos criar o próprio Agente de Conhecimento.</p><p>Dentro da pasta <code>agents</code>, crie um arquivo chamado <code>knowledge-agent.ts</code>. Podemos começar conectando nossas variáveis de ambiente e inicializando o cliente Elasticsearch.</p>import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { openai } from '@ai-sdk/openai';
import { Client } from '@elastic/elasticsearch';
import { ElasticVector } from '../stores/elastic-store';
import dotenv from "dotenv";

dotenv.config();

const ELASTICSEARCH_ENDPOINT = process.env.ELASTICSEARCH_ENDPOINT;
const ELASTICSEARCH_API_KEY = process.env.ELASTICSEARCH_API_KEY;

//Error check for undefined credentials
if (!ELASTICSEARCH_ENDPOINT || !ELASTICSEARCH_API_KEY) {
  throw new Error('Missing Elasticsearch credentials');
}

//Check to see if a connection can be established
const testClient = new Client({
  node: ELASTICSEARCH_ENDPOINT,
  auth: { 
    apiKey: ELASTICSEARCH_API_KEY 
  },
});

try {
  await testClient.ping();
  console.log('Connected to Elasticsearch successfully');
} catch (error: unknown) {
  if (error instanceof Error) {
    console.error('Failed to connect to Elasticsearch:', error.message);
  } else {
    console.error('Failed to connect to Elasticsearch:', error);
  }
  process.exit(1);
}
//Initialize the Elasticsearch vector store
const vectorStore = new ElasticVector({
  node: ELASTICSEARCH_ENDPOINT,
  auth: {
    apiKey: ELASTICSEARCH_API_KEY,
  },
//Optional: Explicitly set to true if using Elasticsearch Serverless to skip auto-detection and improve startup time
//isServerless: true,
});<p>Aqui, nós:</p><ul><li><p>Use <code>dotenv</code> para carregar nossas variáveis do nosso arquivo <code>.env</code> .</p></li><li><p>Verifique se as credenciais do Elasticsearch estão sendo inseridas corretamente e, em seguida, poderemos estabelecer uma conexão bem-sucedida com o cliente.</p></li><li><p>Passe o endpoint do Elasticsearch e a chave da API para o construtor <code>ElasticVector</code> para criar uma instância do nosso armazenamento de vetores que definimos anteriormente.</p></li><li><p>Opcionalmente, especifique <code>isServerless: true</code> se estiver usando o Elasticsearch Serverless. Isso elimina a etapa de detecção automática e melhora o tempo de inicialização. Caso seja omitido, o adaptador detectará automaticamente o seu tipo de implantação na primeira utilização.</p></li></ul><p>Em seguida, podemos definir o agente usando a classe <code>Agent</code> do Mastra.</p>export const knowledgeAgent = new Agent({
    name: 'KnowledgeAgent',
    instructions: 'You are a helpful knowledge assistant.',
    model: openai('gpt-4o'),
    memory: new Memory({

        vector: vectorStore,

        //embedder used to create embeddings for each message
        embedder: 'openai/text-embedding-3-small',

        //set semantic recall options
        options: {
            semanticRecall: {
                topK: 3, // retrieve 3 similar messages
                messageRange: 2, // include 2 messages before/after each match
                scope: 'resource',
            },
        },
    }),
});<p>Os campos que podemos definir são:</p><ul><li><p><code>name</code> e <code>instructions</code>: Dê a ele uma identidade e uma função primária.</p></li><li><p><code>model</code>Estamos usando o <code>gpt-4o</code> da OpenAI por meio do pacote <code>@ai-sdk/openai</code> .</p></li><li><p><code>memory</code>:</p><ul><li><p><code>vector</code>: Aponta para o nosso armazenamento Elasticsearch, de onde os embeddings são armazenados e recuperados.</p></li><li><p><code>embedder</code>Qual modelo usar para gerar embeddings?</p></li><li><p><code>semanticRecall</code> As opções definem como funciona o recall:</p><ul><li><p><code>topK</code>Quantas mensagens semanticamente semelhantes devem ser recuperadas?</p></li><li><p><code>messageRange</code>: Qual a extensão da conversa a ser incluída em cada interação?</p></li><li><p><code>scope</code>Define o limite da memória.</p></li></ul></li></ul></li></ul><p>Quase pronto. Basta adicionarmos esse agente recém-criado à nossa configuração do Mastra. No arquivo chamado <a href="http://index.ts/"><code>index.ts</code></a>, importe o agente de conhecimento e insira-o no campo <code>agents</code> .</p>export const mastra = new Mastra({
  agents: { knowledgeAgent },
  storage: new LibSQLStore({
    // stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
    url: ":memory:",
  }),
  logger: new PinoLogger({
    name: 'Mastra',
    level: 'info',
  }),
  telemetry: {
    // Telemetry is deprecated and will be removed in the Nov 4th release
    enabled: false, 
  },
  observability: {
    // Enables DefaultExporter and CloudExporter for AI tracing
    default: { enabled: true }, 
  },
});<p>Os outros campos incluem:</p><ul><li><p><code>storage</code>Este é o repositório de dados interno do Mastra para histórico de execuções, métricas de observabilidade, pontuações e caches. Para obter mais informações sobre o sistema de armazenamento Mastra, visite <a href="https://mastra.ai/docs/server-db/storage">aqui</a>.</p></li><li><p><code>logger</code>O Mastra utiliza <a href="https://github.com/pinojs/pino">o Pino</a>, que é um registrador JSON estruturado e leve. Ele registra eventos como início e término de agentes, chamadas e resultados de ferramentas, erros e tempos de resposta do LLM.</p></li><li><p><code>observability</code>Controla o rastreamento de IA e a visibilidade da execução de agentes. Ele rastreia:</p><ul><li><p>Início/fim de cada etapa de raciocínio.</p></li><li><p>Qual modelo ou ferramenta foi utilizada?</p></li><li><p>Entradas e saídas.</p></li><li><p>Pontuações e avaliações</p></li></ul></li></ul><h3>Testando o agente com o Mastra Studio</h3><p>Parabéns! Se você chegou até aqui, está pronto para executar este agente e testar suas capacidades de recuperação semântica. Felizmente, o Mastra oferece uma interface de chat integrada, então não precisamos criar a nossa própria.</p><p>Para iniciar o servidor de desenvolvimento do Mastra, abra um terminal e execute o seguinte comando:</p>npm run dev<p>Após a inicialização e o empacotamento iniciais do servidor, você deverá receber um endereço para o Playground.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5f857fddc74ffc9/6a16f7b6a6c2b995d5e794c0/8b045f70008d26aec4d2e6b59d61085555b9c5b2-686x116.png" alt="Endereço do servidor para Playground" /><p>Cole este endereço no seu navegador e você será direcionado para o Mastra Studio.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fdda6ce46ce068/6a16f7b7b0367d4f7672bacf/69bc80fe8486edd9e0cf91d87b39f465aeb23111-1600x438.png" alt="Colar o endereço do Playground para acessar o Mastra Studio" /><p>Selecione a opção <code>knowledgeAgent</code> e comece a conversar.</p><p>Para um teste rápido para verificar se tudo está conectado corretamente, forneça algumas informações como: "A equipe anunciou que o desempenho de vendas em outubro aumentou 12%, impulsionado principalmente por renovações de contratos corporativos." O próximo passo é expandir o alcance aos clientes de médio porte.” Em seguida, inicie um novo bate-papo e faça uma pergunta como: "Em qual segmento de clientes dissemos que precisamos nos concentrar a seguir?" O agente de conhecimento deve ser capaz de recordar as informações que você lhe forneceu na primeira conversa. Você deverá ver uma resposta semelhante a esta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfec3266e81a7213b/6a16f7b92b835f6f70f4afe2/da8ebddad89874023ed440a8f1ad2cb04ed043f4-1070x288.png" alt="Ao conversar com um agente de conhecimento no Mastra Studio, o agente consegue recuperar informações." /><p>Ao recebermos uma resposta como essa, significa que o agente armazenou com sucesso nossa mensagem anterior como embeddings no Elasticsearch e a recuperou posteriormente usando a busca vetorial.</p><h3>Inspecionando o armazenamento de memória de longo prazo do agente.</h3><p>Acesse a aba <code>memory</code> na configuração do seu agente no Mastra Studio. Isso permite que você veja o que seu agente aprendeu ao longo do tempo. Cada mensagem, resposta e interação que é incorporada e armazenada no Elasticsearch passa a fazer parte dessa memória de longo prazo. Você pode realizar buscas semânticas em interações passadas para encontrar rapidamente informações ou contextos que o agente aprendeu anteriormente. Este é essencialmente o mesmo mecanismo que o agente usa durante a recuperação semântica, mas aqui você pode inspecioná-lo diretamente. No exemplo abaixo, estamos pesquisando o termo "vendas" e obtendo como resultado todas as interações que incluíram algo relacionado a vendas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte428134d7bf2a43a/6a16f7bbb0367d185872bad3/3decaa0c332d288c5ae0b11c25f592c7d50c2f0f-1104x1320.png" alt="Como inspecionar o armazenamento de memória de longo prazo dos agentes de conhecimento" /><h2>Conclusão</h2><p>Ao conectar o Mastra e o Elasticsearch, podemos fornecer memória aos nossos agentes, o que é uma camada fundamental na engenharia de contexto. Com a recuperação semântica, os agentes podem construir contexto ao longo do tempo, fundamentando suas respostas no que aprenderam. Isso significa interações mais precisas, confiáveis e naturais.</p><p>Essa integração inicial é apenas o ponto de partida. O mesmo padrão pode permitir que agentes de suporte se lembrem de chamados anteriores, bots internos recuperem documentação relevante ou assistentes de IA consigam recordar detalhes do cliente no meio da conversa. Também estamos trabalhando para uma integração oficial com o Mastra, tornando essa combinação ainda mais perfeita em um futuro próximo.</p><p>Estamos ansiosos para ver o que você vai construir em seguida. Experimente, explore <a href="https://mastra.ai/">o Mastra</a> e seus recursos de memória e sinta-se à vontade para compartilhar suas descobertas com a comunidade.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/knowledge-agent-semantic-recall-mastra-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/knowledge-agent-semantic-recall-mastra-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Experiência do Desenvolvedor]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09afdbff05603865/6a16f7bd839dfabbf2dcfcb5/b8d51c2726d5573385c9246a7821d12ade4f1b0e-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 06 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Servidor Elastic MCP: Exponha as ferramentas do Agent Builder a qualquer agente de IA.]]></title>
    <description><![CDATA[Descubra como usar o servidor Elastic MCP integrado no Agent Builder para estender com segurança qualquer agente de IA com acesso aos seus dados privados e ferramentas personalizadas.]]></description>
    <content:encoded><![CDATA[<p>O Elastic Agent Builder é uma plataforma para criar ferramentas e agentes que se integram profundamente aos seus próprios dados no Elasticsearch. Por exemplo, você pode criar ferramentas que realizam buscas semânticas em documentos internos, analisam logs de observabilidade ou consultam alertas de segurança.</p><p>Mas a verdadeira mágica acontece quando você consegue integrar essas ferramentas personalizadas e orientadas a dados aos ambientes onde você passa a maior parte do tempo. E se o agente do seu editor de código pudesse acessar com segurança a base de conhecimento privada da sua organização?</p><p>É aí que entra <strong>o Protocolo de Contexto do Modelo (MCP)</strong> . O Elastic Agent Builder é fornecido com um servidor MCP integrado que dá acesso às ferramentas da plataforma.</p><h2>Por que usar o servidor Elastic Agent Builder MCP?</h2><p>Os agentes de IA são incrivelmente poderosos, mas seu conhecimento geralmente se limita aos dados com os quais foram treinados e às informações que podem pesquisar ativamente na internet pública. Eles não conhecem os documentos de design internos da sua empresa, os manuais de implantação específicos da sua equipe ou a estrutura exclusiva dos logs de seus aplicativos.</p><p>O desafio é fornecer ao seu assistente de IA o contexto especializado de que ele precisa. Este é precisamente o problema que o MCP foi projetado para resolver. <strong>MCP é um padrão aberto que permite que um modelo ou agente de IA descubra e utilize ferramentas externas.</strong></p><p>Para tornar isso possível, o Elastic Agent Builder expõe nativamente suas ferramentas personalizadas por meio de um servidor MCP integrado. Isso significa que você pode conectar facilmente qualquer cliente compatível com MCP, como <strong>Cursor</strong>, <strong>VS Code</strong> ou <strong>Claude Desktop</strong>, com as ferramentas especializadas e com reconhecimento de dados que você criou com o Elastic Agent Builder.</p><h2>Quando usar MCP (e quando não usar)</h2><p>O Elastic Agent Builder inclui diversos protocolos para suportar diferentes padrões de integração. Escolher a opção certa é fundamental para criar fluxos de trabalho de IA eficazes.</p><ul><li><p><strong>Use </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server"><strong>o MCP</strong></a> para aprimorar seu agente de IA (como no <strong>Cursor</strong> ou <strong>no VS Code</strong>) com ferramentas especializadas. Trata-se da abordagem "traga suas próprias ferramentas", que aprimora o assistente que você já usa com acesso seguro aos seus dados privados. Somente as ferramentas são expostas através do servidor MCP — os agentes da Elastic são independentes disso.</p></li><li><p><strong>Utilize o </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server"><strong>protocolo A2A</strong></a> para permitir que seu Elastic Agent totalmente personalizado colabore com outros agentes autônomos (como no <a href="https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise"><strong>Gemini Enterprise do Google</strong></a>). Isso se aplica à delegação entre agentes, onde cada agente trabalha em conjunto para resolver um problema.</p></li><li><p><strong>Utilize </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/kibana-api"><strong>as APIs do Agent Builder</strong></a> para obter controle programático completo ao criar um aplicativo personalizado do zero.</p></li></ul><p>Para um desenvolvedor que busca respostas em sua documentação interna sem sair do seu IDE, o MCP é a solução ideal.</p><h2>Exemplo: suas ferramentas personalizadas no Cursor com o servidor Agent Builder MCP</h2><p>Vamos analisar um exemplo prático que eu uso diariamente. Primeiro, rastreei e indexei nossa documentação interna de engenharia em um índice Elasticsearch chamado <code>elastic-dev-docs</code>. Embora pudéssemos usar as ferramentas genéricas e integradas disponíveis no Agent Builder, criaremos nossa própria ferramenta personalizada para consultar essa base de conhecimento específica.</p><p>O motivo para construir uma ferramenta personalizada é simples: <strong>controle e precisão</strong>. Essa abordagem nos dá o poder de executar uma consulta semântica rápida diretamente em nosso índice <code>elastic-dev-docs</code> . Temos controle total sobre qual índice é o alvo e como os dados são obtidos.</p><p>Agora, veja como podemos usar essa base de conhecimento personalizada em um editor de código com inteligência artificial, como o Cursor.</p><h3>Etapa 1: Crie uma ferramenta de base de conhecimento personalizada no Agent Builder.</h3><p>Primeiro, crie uma nova ferramenta no Construtor de Agentes. Uma descrição clara e específica da ferramenta é importante porque é assim que qualquer agente de IA, seja o Elastic Agent interno ou uma ferramenta externa como o Cursor, conectado via MCP, descobre e seleciona a ferramenta adequada para a tarefa correta.</p><p>Uma descrição precisa deve ser explícita. Por exemplo: “Realiza uma busca semântica no índice elastic-dev-docs para encontrar documentação interna de engenharia, manuais de operação e procedimentos de lançamento.”</p><p>Com isso configurado, a ferramenta está preparada para realizar uma busca semântica em nosso índice específico. Uma vez salvo, fica imediatamente disponível para ser servido.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt011118f0a9279185/6a17f367dbb4ffc4f3fb581a/1eea079908fdf7cc72dbe81abd07ff51601a43d4-1472x1600.png" alt="Criando uma ferramenta de base de conhecimento personalizada no Agent Builder." /><p>Antes de conectar o dispositivo ao mundo exterior, você pode testá-lo diretamente na interface do usuário. Basta clicar no botão <strong>Testar</strong> para preencher manualmente os parâmetros, simulando o que o LLM fará, e inspecionar os resultados para confirmar se tudo está funcionando corretamente.</p><h3>Etapa 2: Conecte o Cursor ao servidor Elastic MCP</h3><p>O Elastic Agent Builder expõe automaticamente todas as ferramentas disponíveis por meio de um endpoint MCP seguro. Você pode encontrar o URL exclusivo do seu servidor na interface de Ferramentas do Kibana.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdd0e62ae0f394c3d/6a17f368e317916ec32d5933/ba137be30f0eaa7f028b96bd8af4e2779c3f8a33-1600x589.png" alt="Como conectar o cursor da interface de ferramentas do Kibana ao servidor Elastic MCP." /><p>Para conectar ao Cursor, basta adicionar este URL ao seu arquivo de configuração, juntamente com uma chave de API Elastic para autenticação (<a href="https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys">saiba como criar uma chave de API ES</a>). Utilizamos uma chave de API para autorização, pois isso garante que as ferramentas sejam executadas somente com as permissões que você concedeu, respeitando todas as suas regras de controle de acesso.</p><p>A configuração MCP em <code>~/.cursor/mcp.json</code> do Cursor se parece com isto:</p>{
  "mcpServers": {
    "elastic-agent-builder": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://your-kibana.kb.company.io/api/agent_builder/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "ApiKey &lt;ELASTIC_API_KEY&gt;"
      }
    }
  }
}<p>Após salvar a configuração, você deverá ver a ferramenta de servidor Elastic Agent Builder MCP disponível no Cursor.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2837638263e628ed/6a17f36adbb4ffeb9cfb5820/d302c6d3609fbf14fd40e21b9e69e567bf12553f-1600x1002.png" alt="Imagem da ferramenta de servidor Elastic Agent Builder MCP disponível no Cursor." /><h3>Passo 3: pergunte à vontade!</h3><p>Com a conexão estabelecida, os agentes do Cursor agora podem invocar suas ferramentas personalizadas para responder às suas perguntas ou orientar o processo de geração de código.</p><p>Vamos fazer uma pergunta específica:</p><p><em>“Consulte os passos para liberar o serviço de rastreamento na documentação interna de engenharia da organização do Elasticsearch”</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt83fa357261b30e93/6a17f36c4b055d16d1432326/14f572730203c23615bb9dd38234bcb3b0f81155-1600x1468.png" alt="Agentes de cursor invocam ferramentas personalizadas para responder a perguntas e orientar o processo de geração de código." /><p>Nos bastidores, a magia acontece:</p><ol><li><p>O agente Cursor decide a melhor forma de responder à sua pergunta e, em seguida, decide ligar para o <code>engineering_documentation_internal_search</code></p></li><li><p>Ela invoca a ferramenta com uma consulta em linguagem natural.</p></li><li><p>A ferramenta executa uma busca semântica no índice <code>elastic-dev-docs</code> e retorna os procedimentos mais relevantes e atualizados.</p></li></ol><p>Obtemos uma resposta precisa e confiável com base em nossa documentação interna, tudo isso sem precisar sair do editor de código. A experiência é perfeita e impactante.</p><h2>Sua vez de construir</h2><p>Agora você viu como usar o servidor MCP integrado no Elastic Agent Builder para estender seus assistentes de IA com acesso seguro aos seus dados privados. Fundamentar os modelos em suas próprias informações é fundamental para torná-los verdadeiramente úteis.</p><p>Recapitulando, abordamos as etapas principais:</p><ul><li><p>Escolher o protocolo certo para as suas necessidades (MCP).</p></li><li><p>Criação de uma ferramenta de base de conhecimento personalizada.</p></li><li><p>Conectar essa ferramenta a um assistente de IDE como o Cursor.</p></li></ul><p>Seus agentes e ferramentas não precisam mais estar desconectados de seu contexto mais valioso. Esperamos que este guia ajude você a criar fluxos de trabalho mais eficazes e orientados a dados. Boa construção!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elastic-mcp-server-agent-builder-tools</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elastic-mcp-server-agent-builder-tools</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[Ferramentas de IA ]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5b61961b6269ab1/6a17f36ea29299d839d02db2/ef5153551a1d14833c7f512fede554d1dfb31553-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 20 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Avaliação de agentes de IA: como a Elastic testa frameworks de agentes]]></title>
    <description><![CDATA[Saiba como avaliamos e testamos as alterações em um sistema de agentes antes de liberá-las para os usuários da Elastic, garantindo resultados precisos e verificáveis.]]></description>
    <content:encoded><![CDATA[<h2>Introdução</h2><p>No Elastic Stack, existem muitos aplicativos agentivos baseados em LLM, como o futuro Elastic AI Agent no<a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder"> Agent Builder</a> (atualmente em versão de pré-visualização técnica) e <a href="https://www.elastic.co/docs/solutions/security/ai/attack-discovery">o Attack Discovery</a> (<a href="https://www.elastic.co/blog/whats-new-elastic-security-9-0-0">disponível para o público geral</a> nas versões 8.18 e 9.0+), com mais em desenvolvimento. Durante o desenvolvimento, e mesmo após a implementação, é importante responder a estas perguntas:</p><ul><li><p>Como podemos estimar a qualidade das respostas dessas aplicações de IA?</p></li><li><p>Se fizermos uma alteração, como podemos garantir que ela seja realmente uma melhoria e não cause deterioração na experiência do usuário?</p></li><li><p>Como podemos testar esses resultados de forma fácil e repetível?</p></li></ul><p>Diferentemente dos testes de software tradicionais, a avaliação de aplicações de IA generativa envolve métodos estatísticos, análises qualitativas minuciosas e uma compreensão profunda dos objetivos do usuário.</p><p>Este artigo detalha o processo que a equipe de desenvolvimento da Elastic utiliza para realizar avaliações, garantir a qualidade das alterações antes da implantação e monitorar o desempenho do sistema. Nosso objetivo é garantir que cada mudança seja respaldada por evidências, resultando em resultados confiáveis e verificáveis. Parte desse processo está integrada diretamente ao Kibana, refletindo nosso compromisso com a transparência como parte de nossa filosofia de código aberto. Ao compartilhar abertamente partes de nossos dados e métricas de avaliação, buscamos fomentar a confiança da comunidade e fornecer uma estrutura clara para qualquer pessoa que desenvolva agentes de IA ou utilize nossos produtos.</p><h2>Exemplos de produtos</h2><p>Os métodos utilizados neste documento serviram de base para a forma como iteramos e aprimoramos soluções como o Attack Discovery e o Elastic AI Agent. Uma breve introdução aos dois, respectivamente:</p><h3>Descoberta de ataques da Elastic Security</h3><p>A descoberta de ataques utiliza LLMs para identificar e resumir sequências de ataques no Elastic. Com base nos alertas do Elastic Security em um determinado período (padrão de 24 horas), o fluxo de trabalho automatizado do Attack Discovery identificará automaticamente se ocorreram ataques, além de informações importantes, como quais hosts ou usuários foram comprometidos e quais alertas contribuíram para essa conclusão.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb70932abe8d4de75/6a17f04ea292990c52d02d61/20fabb47642dad7b588daaaa8c3a98de860ad01d-1251x758.png" alt="" /><p></p><p>O objetivo é que a solução baseada em LLM produza um resultado pelo menos tão bom quanto o de um ser humano.</p><h3>Agente de IA Elástico</h3><p>O <strong>Elastic Agent Builder</strong> é a nossa nova plataforma para criar agentes de IA sensíveis ao contexto que aproveitam todos os nossos recursos de busca. Ele vem com o <strong>Elastic AI Agent</strong>, um agente pré-construído de uso geral, projetado para ajudar os usuários a entender e obter respostas a partir de seus dados por meio de interação conversacional.</p><p>O agente consegue isso identificando automaticamente informações relevantes no Elasticsearch ou em bases de conhecimento conectadas e utilizando um conjunto de ferramentas pré-construídas para interagir com elas. Isso permite que o Elastic AI Agent responda a uma ampla gama de consultas de usuários, desde perguntas e respostas simples sobre um único documento até solicitações complexas que exigem agregação e buscas de uma ou várias etapas em diversos índices.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3b9dbede85a56bd6/6a17f050e8fbce88943a1a30/d29dee100bb8a17bb623acd745773a5164a1df4f-1600x1014.png" alt="" /><h2>Medindo melhorias por meio de experimentos</h2><p>No contexto de agentes de IA, um experimento é uma mudança estruturada e testável no sistema, projetada para melhorar o desempenho em dimensões bem definidas (por exemplo, utilidade, correção, latência). O objetivo é responder de forma definitiva: "Se incorporarmos essa alteração, podemos garantir que ela representa uma melhoria real e não prejudicará a experiência do usuário?"</p><p>A maioria dos experimentos que realizamos geralmente inclui:</p><ul><li><p><strong>Uma hipótese:</strong> uma afirmação específica e falseável. <em>Exemplo:</em> “Adicionar acesso a uma ferramenta de descoberta de ataques melhora a precisão das consultas relacionadas à segurança.”</p></li><li><p><strong>Critérios de sucesso:</strong> Limiares claros que definem o que significa "sucesso". <em>Exemplo:</em> “Melhoria de 5% na pontuação de correção no conjunto de dados de segurança, sem degradação em outros locais.”</p></li><li><p><strong>Plano de avaliação:</strong> Como medimos o sucesso (métricas, conjuntos de dados, método de comparação)</p></li></ul><p>Um experimento bem-sucedido é um processo sistemático de investigação. Toda alteração, desde um pequeno ajuste de um prompt até uma grande mudança arquitetônica, segue estes sete passos para garantir que os resultados sejam significativos e acionáveis:</p><ul><li><p>Etapa 1: Identificar o problema</p></li><li><p>Etapa 2: Definir métricas</p></li><li><p>Etapa 3: Formule uma hipótese clara</p></li><li><p>Etapa 4: Preparar o conjunto de dados de avaliação</p></li><li><p>Etapa 5: Execute o experimento</p></li><li><p>Etapa 6: Analisar resultados + iterar</p></li><li><p>Etapa 7: Tome uma decisão e documente-a.</p></li></ul><p>Um exemplo dessas etapas é ilustrado na <em>Figura 1</em>. As subseções a seguir explicarão cada etapa, e detalharemos os aspectos técnicos de cada etapa em documentos futuros.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06bfe2f0e4205a18/6a17f052faa91358eb93c968/3a9f5a3e92dd4922a795a19104c6e4ad8c98958d-2400x1352.png" alt="" /><h2>Passo a passo com exemplos reais do Elastic</h2><h3>Etapa 1: Identificar o problema</h3><p><em>Qual é exatamente o problema que essa mudança visa resolver?</em></p><p>Exemplo de detecção de ataques: os resumos são ocasionalmente incompletos ou atividades benignas são erroneamente sinalizadas como ataques (falsos positivos).</p><p>Exemplo de agente de IA elástica: a seleção de ferramentas do agente, especialmente para consultas analíticas, é subótima e inconsistente, muitas vezes levando à escolha da ferramenta errada. Isso, por sua vez, aumenta os custos dos tokens e a latência.</p><h3>Etapa 2: Definir métricas</h3><p><em>Torne o problema mensurável, para que possamos comparar uma mudança com o estado atual.</em></p><p>As métricas comuns incluem <a href="https://developers.google.com/machine-learning/crash-course/classification/accuracy-precision-recall">precisão e revocação</a>, <a href="https://en.wikipedia.org/wiki/Semantic_similarity">similaridade semântica</a>, factualidade, e assim por diante. Dependendo do caso de uso, utilizamos verificações de código para calcular as métricas, como a correspondência de IDs de alerta ou URLs recuperados corretamente, ou técnicas como LLM-as-judge para respostas mais livres.</p><p>Abaixo estão alguns exemplos (<em>lista não exaustiva</em>) de métricas usadas nos experimentos:</p><p><strong>Descoberta de ataques</strong></p><p>Métrica</p><p>Descrição</p><p>Precisão e memorização</p><p>Compare os IDs de alerta entre as saídas reais e esperadas para medir a precisão da detecção.</p><p>Semelhança</p><p>Utilize o BERTScore para comparar a similaridade semântica do texto de resposta.</p><p>Factualidade</p><p>Os principais indicadores de comprometimento (IOCs) estão presentes? As táticas MITRE (taxonomia de ataques do setor) estão corretamente representadas?</p><p>Consistência da cadeia de ataque</p><p>Compare o número de descobertas para verificar se houve superestimação ou subestimação da notificação do ataque.</p><p><strong>Agente de IA Elástico</strong></p><p>Métrica</p><p>Descrição</p><p>Precisão e memorização</p><p>Comparar os documentos/informações recuperados pelo agente para responder a uma consulta do usuário com as informações ou documentos realmente necessários para responder à consulta, a fim de medir a precisão da recuperação de informações.</p><p>Factualidade</p><p>Os principais fatos necessários para responder à consulta do usuário estão presentes? Os fatos estão na ordem correta para questões processuais?</p><p>Relevância da resposta</p><p>A resposta contém informações periféricas ou não relacionadas à consulta do usuário?</p><p>Completude da resposta</p><p>A resposta atende a todas as partes da consulta do usuário? A resposta contém todas as informações presentes na verdade fundamental?</p><p>Validação ES|QL</p><p>O código ES|QL gerado está sintaticamente correto? É funcionalmente idêntico ao ES|QL original?</p><h3>Etapa 3: Formule uma hipótese clara</h3><p><em>Estabeleça critérios de sucesso claros usando o problema e as métricas definidas acima.</em></p><p>Exemplo de agente de IA elástico:</p><ol><li><p>Implementar <strong>alterações nas descrições das ferramentas relevance_search e nl_search para definir claramente suas funções e casos de uso específicos</strong>.</p></li><li><p>Prevemos que <strong>melhoraremos</strong> <strong>a precisão da invocação de nossa ferramenta</strong> em <strong>25%</strong>.</p></li><li><p>Verificaremos se isso representa um saldo positivo, garantindo que não haja impacto negativo em outras métricas, por exemplo... <strong>factualidade e completude</strong>.</p></li><li><p>Acreditamos que isso funcionará porque <strong>descrições precisas das ferramentas ajudarão o agente a selecionar e aplicar com mais exatidão a ferramenta de busca mais adequada para diferentes tipos de consulta, reduzindo o uso incorreto e melhorando a eficácia geral da busca</strong>.</p></li></ol><h3>Etapa 4: Preparar o conjunto de dados de avaliação</h3><p><em>Para medir o desempenho do sistema, utilizamos conjuntos de dados que capturam cenários do mundo real.</em></p><p>Dependendo do tipo de avaliação que estivermos realizando, podemos precisar de diferentes formatos de dados, como dados brutos inseridos em um LLM (por exemplo, cenários de ataque para descoberta de ataques) e resultados esperados. Se o aplicativo for um chatbot, as entradas podem ser consultas do usuário e as saídas podem ser respostas corretas do chatbot, links corretos que ele deveria ter recuperado e assim por diante.</p><p>Exemplo de descoberta de ataques:</p><p>10 novos cenários de ataque</p><p>8 episódios de Oh My Malware (ohmymalware.com)</p><p>4 cenários de múltiplos ataques (criados pela combinação de ataques nas duas primeiras categorias)</p><p>3 cenários benignos</p><p>Exemplo de conjunto de dados para avaliação de agentes de IA elástica (<a href="https://github.com/elastic/kibana/blob/main/x-pack/platform/packages/shared/onechat/kbn-evals-suite-onechat/evals/kb/kb.spec.ts">Link para o conjunto de dados do Kibana</a>):</p><p>14 Índices que utilizam conjuntos de dados de código aberto para simular múltiplas fontes em KB.</p><p>5 tipos de consulta (analítica, recuperação de texto, híbrida…)</p><p>7 tipos de intenção de consulta (procedimental, factual - classificação, investigativa; …)</p><h3>Etapa 5: Execute o experimento</h3><p>Execute o experimento gerando respostas tanto do agente existente quanto da versão modificada em relação ao conjunto de dados de avaliação. Calcule métricas como a veracidade factual (ver passo 2).</p><p>Combinamos diversas avaliações com base nas métricas exigidas na Etapa 2:</p><ul><li><p>Avaliação baseada em regras (por exemplo, (Use Python/TypeScript para verificar se o arquivo .json é válido)</p></li><li><p>LLM como juiz (consultar um LLM separado para verificar se uma resposta é factualmente consistente com um documento original)</p></li><li><p>Revisão com intervenção humana para verificações de qualidade e nuances.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt17ec63af0850d8dd/6a17f054505ac3e508ad8c1e/8648e75818d3291f0ac66f069438a500d42b8225-1600x1099.png" alt="Este é um exemplo de resultado de avaliação gerado por nossa estrutura interna. Apresenta diversas métricas de um experimento realizado em diferentes conjuntos de dados." /><h3>Etapa 6: Analisar resultados + iterar</h3><p>Agora que temos as métricas, vamos analisar os resultados. <u><em>Mesmo que os resultados atendam aos critérios de sucesso definidos na etapa 3, ainda faremos uma revisão humana antes de incorporar a alteração à produção</em></u>; se os resultados não atenderem aos critérios, iteraremos e corrigiremos os problemas e, em seguida, executaremos as avaliações na nova alteração.</p><p>Prevemos que serão necessárias algumas iterações para encontrarmos a melhor alteração antes de a consolidarmos. Assim como é feito executar testes de software locais antes de enviar uma alteração, as avaliações offline podem ser executadas com alterações locais ou com várias alterações propostas. Automatizar o salvamento de resultados experimentais, pontuações compostas e visualizações é útil para agilizar a análise.</p><h3>Etapa 7: Tome uma decisão e documente-a.</h3><p>Com base em uma estrutura de decisão e critérios de aceitação, decida sobre a incorporação da alteração e documente o experimento. A tomada de decisões é multifacetada e pode considerar fatores que vão além do conjunto de dados de avaliação, como verificar cenários de regressão em outros conjuntos de dados ou ponderar o custo-benefício de uma mudança proposta.</p><p>Exemplo: Após testar e comparar algumas iterações, escolha a alteração com a melhor pontuação para enviar aos gerentes de produto e outras partes interessadas relevantes para aprovação. Anexe os resultados das etapas anteriores para auxiliar na tomada de decisão. Para mais exemplos sobre a descoberta de ataques, consulte <a href="https://www.elastic.co/blog/elastic-security-generative-ai-features">Nos bastidores dos recursos de IA generativa do Elastic Security</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt62a466f3a0da114a/6a17f056faa91342c393c96c/74c80b8f34dce8ddd20873ecb2f553873587ed35-1600x618.png" alt="" /><h2>Conclusão</h2><p>Neste blog, descrevemos o processo completo de um fluxo de trabalho de experimento, ilustrando como avaliamos e testamos as alterações em um sistema de agentes antes de disponibilizá-las aos usuários da Elastic. Também fornecemos alguns exemplos de como aprimorar fluxos de trabalho baseados em agentes no Elastic. Em publicações subsequentes no blog, detalharemos diferentes etapas, como criar um bom conjunto de dados, projetar métricas confiáveis e tomar decisões quando várias métricas estão envolvidas.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-evaluation-elastic</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-evaluation-elastic</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Susan Chang,Abhimanyu Anand]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte578b636637be6b1/6a17f057e8fbcebe9e3a1a36/ef3922076713872163e1aab47735361513b2c9ee-2400x1352.heif" length="0" type="image/*"/>
    <pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Conectando agentes elásticos ao Gemini Enterprise via protocolo A2A]]></title>
    <description><![CDATA[Aprenda a usar o Agent Builder para expor seu Elastic Agent personalizado a serviços externos como o Gemini Enterprise com o protocolo A2A.]]></description>
    <content:encoded><![CDATA[<p><strong>O Elastic Agent Builder</strong> é um conjunto de funcionalidades para criar agentes de IA orientados a dados diretamente no Elasticsearch. Em publicações anteriores desta <a href="https://www.elastic.co/search-labs/blog/series/context-aware-ai-agentic-workflows-with-elastic">série</a>, demonstramos como equipar agentes personalizados com ferramentas para executar tarefas complexas e fornecer-lhes um conjunto de instruções personalizadas para orientar seu comportamento.</p><p>Mas e se você quiser usar seus agentes personalizados com os aplicativos e ferramentas de produtividade que você já utiliza?</p><p>É aí que entra o <strong>protocolo Agente-para-Agente (A2A)</strong> . A2A é um <a href="https://github.com/a2aproject/A2A">padrão aberto</a> de interoperabilidade, permitindo que agentes de diferentes plataformas se comuniquem e colaborem. E nós o integramos diretamente ao Elastic Agent Builder.</p><p>Hoje, vamos mostrar como pegar um agente personalizado que você criou e expô-lo a outros serviços, especificamente, <strong>ao Gemini Enterprise </strong>(antigo Agentspace).</p><h2>O poder dos padrões abertos: por que a abordagem A2A é importante</h2><p>Na postagem do blog <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">"Seu primeiro Elastic Agent"</a>, mostramos como criar agentes personalizados, como um agente <em>de Assistente Financeiro</em> com acesso seguro aos seus dados de mercado. Mas seu valor é limitado se você não puder disponibilizar suas informações em outros ambientes, como o Gemini Enterprise, sem refazer todo o seu trabalho.</p><p>Esse desafio de interoperabilidade é o que impede o avanço da IA ativa. Os agentes precisam de uma linguagem comum para se comunicarem entre plataformas, e essa é precisamente a função do protocolo A2A. Ela fornece uma camada de comunicação padrão que não só permite a interação direta com o agente, como também abre caminho para um futuro em que agentes especializados em toda a organização possam colaborar e compartilhar informações.</p><p>Para tornar isso possível, o Elastic Agent Builder oferece suporte nativo ao protocolo A2A por meio de dois endpoints padrão para todos os seus agentes:</p><ol><li><p><strong>O endpoint do cartão do agente (</strong><strong><code>GET {your-kibana-url}/api/agent_builder/a2a/{agentId}.json</code></strong><strong>) - </strong>Este funciona como o cartão de visita personalizado do seu agente. Ele fornece metadados sobre seu agente (nome, descrição, capacidades, etc.) para qualquer serviço compatível com A2A.</p></li><li><p><strong>O ponto final do protocolo A2A (</strong><strong><code>POST {your-kibana-url}/api/agent_builder/a2a/{agentId}</code></strong><strong>)</strong> - Este é o canal de comunicação. Outros agentes enviam suas solicitações para cá, e seu agente as processa e retorna uma resposta, tudo seguindo a <a href="https://a2a-protocol.org/latest/specification/">especificação do protocolo A2A</a>.</p></li></ol><h2>Teste seu agente com o inspetor A2A.</h2><p>Antes de conectar nosso agente a um sistema de produção, é bom verificar se a comunicação está funcionando corretamente. A maneira mais fácil de fazer isso é com o <strong>A2A Inspector</strong>, uma ferramenta projetada especificamente para testar e depurar integrações A2A.</p><p>Colocar o inspetor em funcionamento é simples. Você pode clonar o repositório <a href="https://github.com/a2aproject/a2a-inspector">a2a-inspector</a> e seguir as instruções do arquivo README para <a href="https://github.com/a2aproject/a2a-inspector?tab=readme-ov-file#3-run-the-application">executar o aplicativo</a>. Uma vez iniciado, o UI está disponível por padrão em <code>http://localhost:5001/</code>.</p><p>Para conectar o A2A Inspector ao seu agente, você precisará fornecer duas informações essenciais:</p><ul><li><p>URL do Cartão do Agente: Este é o endpoint que descreve o seu agente. Para o <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">agente Assistente Financeiro da nossa postagem anterior</a>, este URL seria <code>{your-kibana-url}/api/agent_builder/a2a/financial_assistant.json</code>.</p></li><li><p>Cabeçalho de autenticação: Usaremos uma chave de API padrão para autenticação.</p></li></ul><p>Após inserir esses detalhes na interface do inspetor, você poderá se conectar e começar a conversar com seu agente imediatamente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6381135e3fb297df/6a17ef4bec0f898b0c5a66ea/7231c72bf30bed2a854f58658c1eca2843f43bfc-1600x1296.png" alt="Configuração do Cartão de Agente A2A e do Inspetor de Agentes" /><p>Essa validação simples nos dá a certeza de que nosso agente está configurado corretamente e pronto para a próxima etapa.</p><h2>Entre ao vivo! Seu agente personalizado na Gemini Enterprise</h2><p>Agora vem a parte emocionante: dar vida ao nosso agente de consultoria financeira personalizado dentro do Gemini Enterprise (antigo Agentspace). Essa integração é viabilizada pelo <a href="https://console.cloud.google.com/marketplace/product/elastic-prod/elastic-ai-agent">Elastic AI Agent, que está disponível no Google Cloud Marketplace</a>.</p><p>Uma vez conectado, o Gemini Enterprise usa o protocolo A2A para se comunicar diretamente com seu agente. É aqui que o verdadeiro poder da interoperabilidade se destaca: os usuários agora podem acessar insights profundos e baseados em dados do seu agente Elasticsearch personalizado sem precisar sair do ambiente familiar. Você pode ver seu agente elástico personalizado na lista de agentes:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f54f0bb15216d8e/6a17ef4d6df73107d90a0fdb/37a39e92ebf3d72c6c8014397cd8e846336173a4-1600x834.png" alt="Visualizando um agente personalizado em uma lista do Google Agentspace" /><p>Imagine um usuário do Gemini Enterprise perguntando:</p><p><em>"Estou preocupado com o sentimento do mercado. Você pode me mostrar quais dos nossos clientes estão mais vulneráveis a notícias negativas?</em>"</p><p>Nos bastidores, o Gemini Enterprise encaminha essa consulta por meio do protocolo A2A para o seu Elastic Agent personalizado. Seu agente então utiliza suas ferramentas especializadas para consultar seus dados, formular uma resposta e enviá-la de volta. Para o usuário final, a experiência é perfeita.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte130c332ee0648a6/6a17ef4fe9ea874426a9c6bb/e5f126c1a27a51c6e69a767aa87c9f746b62e39c-1600x1044.png" alt="Um usuário envia uma consulta ao Agentspace e o que acontece com essa consulta nos bastidores?" /><p>E não para por aqui! A resposta obtida com o agente elástico agora pode ser usada como contexto para suas próximas perguntas, que podem acionar um agente especializado diferente (por exemplo, seu agente de plataforma de investimentos para ajustar a exposição a empresas listadas). Tudo isso sem sair da sua barra de pesquisa.</p><p>Com seus agentes Elastic implantados no Gemini Enterprise com A2A, você pode unificar acesso, orquestração e fluxos de trabalho, eliminando atritos entre IA, pesquisa e sistemas corporativos, oferecendo uma interface de usuário única onde os usuários interagem com seus dados e ferramentas — tudo em contexto. Para os usuários, isso significa menos troca de ferramentas e assistentes de IA mais intuitivos e capazes. Para as organizações, isso significa governança coerente, escalabilidade e interoperabilidade integradas.</p><h2>Sua vez de construir</h2><p>Agora você tem as ferramentas para disponibilizar seus Agentes Elásticos em qualquer lugar. Ao aproveitar o protocolo aberto A2A, você pode ampliar o alcance de seus agentes personalizados e orientados a dados.</p><p>Neste post, apresentamos os principais passos:</p><ul><li><p>Exponha seu agente por meio do cartão de agente A2A e dos endpoints do protocolo.</p></li><li><p>Testando a conexão com o A2A Inspector.</p></li><li><p>Integrar seu agente em tempo real a um serviço externo como o Gemini Enterprise do Google.</p></li></ul><p>Seus agentes não precisam mais ficar isolados. Estamos ansiosos para ver os sistemas poderosos e interconectados que vocês criarão. Boa construção!</p><p>A maneira mais fácil de começar é com sua avaliação gratuita do Elastic Cloud no <a href="https://console.cloud.google.com/marketplace/product/elastic-prod/elastic-cloud?pli=1">Google Cloud Marketplace.</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Valerio Arvizzigno,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt63d7675adc5bc211/6a17ef51ddf97d38e8910bdf/5be8a425fab55dca2f9717d2e50812b0450fa625-1440x840.png" length="0" type="image/png"/>
    <pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Experimentos para aprimorar ferramentas de IA Agética para Elasticsearch]]></title>
    <description><![CDATA[Saiba como aprimoramos os fluxos de trabalho de agentes de IA para Elasticsearch por meio de experimentos iterativos, combinando recuperadores lineares, busca híbrida e semantic_text para otimização RAG escalável.]]></description>
    <content:encoded><![CDATA[<p>Assim como todo mundo hoje em dia, aqui na Elastic, estamos investindo pesado em Chat, Agentes e RAG. Na área de Busca, temos trabalhado recentemente em um Construtor de Agentes e um Registro de Ferramentas, tudo com o intuito de tornar trivial a interação com seus dados no Elasticsearch.</p><p>Leia o <a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">artigo "Building AI Agentic Workflows with Elasticsearch"</a> para obter mais informações sobre o panorama geral desse projeto, ou <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">"Your First Elastic Agent: From a Single Query to a AI-Powered Chat"</a> para uma introdução mais prática.</p><p>Neste blog, porém, vamos nos aprofundar um pouco em uma das primeiras coisas que acontecem quando você começa a conversar e apresentar algumas das melhorias recentes que implementamos.</p><h2>O que está acontecendo aqui?</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1331b1043612efe3/6a17f115505ac3dc41ad8c3c/25a24055a166d7d6ba81d80aa35cb97163662e23-1600x443.png" alt="" /><p>Ao interagir com seus dados do Elasticsearch, nosso agente de IA padrão segue este fluxo padrão:</p><ol><li><p>Examine o prompt.</p></li><li><p>Identifique qual índice provavelmente contém as respostas para essa pergunta.</p></li><li><p>Gere uma consulta para esse índice, com base no prompt.</p></li><li><p>Pesquise esse índice com essa consulta.</p></li><li><p>Sintetize os resultados.</p></li><li><p>Os resultados respondem à pergunta? Em caso afirmativo, responda. Caso contrário, repita, mas tente algo diferente.</p></li></ol><p>Isso não deve parecer muito inovador - é apenas Geração Aumentada por Recuperação (RAG). E, como seria de esperar, a qualidade das suas respostas depende muito da relevância dos resultados da sua pesquisa inicial. Enquanto trabalhávamos para melhorar a qualidade de nossas respostas, prestamos muita atenção às consultas que gerávamos na etapa 3 e executávamos na etapa 4. E percebemos um padrão interessante.</p><p>Muitas vezes, quando nossas primeiras respostas eram "ruins", não era porque tínhamos executado uma consulta ruim. Isso aconteceu porque <em>tínhamos escolhido o índice errado</em> para consultar. Os passos 3 e 4 geralmente não eram o nosso problema - era o passo 2.</p><h2>O que estávamos fazendo?</h2><p>Nossa implementação inicial foi simples. Tínhamos criado uma ferramenta (chamada index_explorer) que efetivamente faria um <code>_cat/indices</code> para listar todos os índices disponíveis para nós e, em seguida, pediria ao LLM para identificar qual desses índices era a melhor correspondência para a mensagem/pergunta/solicitação do usuário. Você pode ver a <a href="https://github.com/elastic/kibana/blob/0cc78184957fcd12110dabae50353392ea937508/x-pack/platform/packages/shared/onechat/onechat-genai-utils/tools/index_explorer.ts#L98-L113">implementação original aqui</a>.</p>You are an AI assistant for the Elasticsearch company.
based on a natural language query from the user, your task is to select up to ${limit} most relevant indices from a list of indices.

*The natural language query is:* ${nlQuery}

*List of indices:*
${indices.map((index) =&gt; `- ${index.index}`).join('\n')}

Based on those information, please return most relevant indices with your reasoning.
Remember, you should select at maximum ${limit} indices.<p>Quão bem isso estava funcionando? Não tínhamos certeza! Tínhamos exemplos claros de situações em que <em>não estava</em> funcionando bem, mas nosso primeiro desafio real foi quantificar nossa situação atual.</p><h2>Estabelecer uma linha de base</h2><h3>Tudo começa com dados.</h3><p>O que precisávamos era de um Conjunto de Dados Ideal para medir a eficácia de uma ferramenta na seleção do índice correto, dada uma solicitação do usuário e um conjunto preexistente de índices. E nós não tínhamos um conjunto de dados desse tipo disponível. Então, nós geramos um.</p><p>Reconhecimento: Sabemos que isso não é a "melhor prática". Mas, às vezes, é melhor seguir em frente do que ficar discutindo detalhes irrelevantes. <a href="https://www.elastic.co/about/our-source-code#progress-perfection">Progresso, SIMPLES Perfeição</a>.</p><p>Geramos índices iniciais para vários domínios diferentes usando <a href="https://gist.github.com/seanstory/a08db2e149897da656db3a1ca72e17ac">este prompt</a>. Em seguida, para cada domínio gerado, geramos mais alguns índices usando<a href="https://gist.github.com/seanstory/a280a85d067e61bfeb5911bf2654e6e2"> esse prompt</a> (o objetivo aqui é semear confusão para o LLM com negativos difíceis e exemplos difíceis de classificar). Em seguida, editamos manualmente cada índice gerado e suas respectivas descrições. Por fim, geramos consultas de teste usando <a href="https://gist.github.com/seanstory/44291b666c05a383136f6e36bb9106fa">esse prompt</a>. Isso nos deixou com dados de exemplo como:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1bd9cd78154195e3/6a17f117dbb4fff7b5fb57d2/9d96d87e286eddbc012402b1ecccd57419a99253-1600x782.png" alt="" /><p>e casos de teste como:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltadf30a0aeafd56ef/6a17f1192f4a5c160ffa89eb/4c2e9ad941d98d7e66033bbc08c9b8060ec19097-1600x797.png" alt="" /><h3>Construindo um arnês de teste</h3><p>A partir daqui, o processo foi muito simples. Crie uma ferramenta que possa:</p><ol><li><p>Crie um ambiente totalmente novo com um cluster Elasticsearch de destino.</p></li><li><p>Crie todos os índices definidos no conjunto de dados de destino.</p></li><li><p>Para cada cenário de teste, execute a ferramenta i<code>ndex_explorer</code> (felizmente, temos uma <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-post-agent-builder-tools-execute">API Execute Tool</a>).</p></li><li><p>Compare o índice resultante com o índice esperado e registre o resultado.</p></li><li><p>Após concluir todos os cenários de teste, tabule os resultados.</p></li></ol><h3>A pesquisa indica…</h3><p>Os resultados iniciais foram, previsivelmente, medíocres.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73367741359e258d/6a17f11a505ac39749ad8c40/9c10679bcd6291edfa2a9ba42e7dd922aa483f0b-1216x806.png" alt="" /><p>No geral, a precisão na identificação do índice correto foi de 77,14%. E isso no cenário "ideal", onde todos os índices têm nomes bons e semanticamente significativos. Qualquer pessoa que já tenha executado um `PUT test2/_doc/foo {...}` sabe que seus índices nem sempre têm nomes significativos.</p><p>Portanto, temos uma base de referência, e ela mostra que há muito espaço para melhorias. Chegou a hora de fazer ciência! 🧪</p><h2>Experimentação</h2><h3>Hipótese 1: Os mapeamentos ajudarão</h3><p>O objetivo aqui é identificar um índice que contenha dados relevantes para a pergunta original. E a parte de um índice que melhor descreve os dados que ele contém são os <em>mapeamentos</em> do índice. Mesmo sem obter nenhuma amostra do conteúdo do índice, saber que o índice possui um campo de preço do tipo double implica que os dados representam algo que está à venda. Um campo de autor do tipo texto implica alguns dados linguísticos não estruturados. A combinação dos dois pode sugerir que os dados são livros/histórias/poemas. Podemos obter muitas pistas semânticas apenas conhecendo as propriedades de um índice. Então, em uma branch local, eu ajustei nosso arquivo `.index_explorer`. Ferramenta para enviar os mapeamentos completos de um índice (juntamente com seu nome) ao LLM para que este tome uma decisão. </p><p>O resultado (dos registros do Kibana):</p>[2025-09-05T11:01:21.552-05:00][ERROR][plugins.onechat] Error: Error calling connector: event: error
data: {"error":{"code":"request_entity_too_large","message":"Received a content too large status code for request from inference entity id [.rainbow-sprinkles-elastic] status [413]","type":"error"}}


    at createInferenceProviderError (errors.ts:90:10)
    at convertUpstreamError (convert_upstream_error.ts:39:38)
    at handle_connector_response.ts:26:33
    at Observable.init [as _subscribe] (/Users/seanstory/Desktop/Dev/kibana/node_modules/rxjs/src/internal/observable/throwError.ts:123:68)...<p>Os autores originais da ferramenta já haviam previsto isso. Embora o mapeamento de um índice seja uma mina de ouro de informações, ele também é um bloco JSON bastante extenso. E em um cenário realista onde você está comparando inúmeros índices (nosso conjunto de dados de avaliação define 20), esses blocos JSON se acumulam. Assim, queremos fornecer ao LLM mais contexto para sua decisão, não apenas os nomes dos índices de todas as opções, mas também os mapeamentos completos de cada uma.</p><h3>Hipótese 2: Mapeamentos “achatados” (listas de campos) como solução de compromisso.</h3><p>Partimos do pressuposto de que os criadores de índices usarão nomes de índice semanticamente significativos. E se estendermos essa suposição também aos nomes dos campos? Nosso experimento anterior falhou porque o mapeamento de JSON inclui MUITOS metadados e código repetitivo desnecessários.</p>     "description_text": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          },
          "copy_to": [
            "description_semantic"
          ]
        },<p>O bloco acima, por exemplo, tem 236 caracteres e define apenas um único campo em um mapeamento do Elasticsearch. Enquanto a string “description_text” possui apenas 16 caracteres. Isso representa um aumento de quase 15 vezes na contagem de caracteres, sem uma melhoria semântica significativa na descrição do que esse campo implica sobre os dados disponíveis. E se buscássemos os mapeamentos para todos os índices, mas antes de enviá-los para o LLM, os "aplanássemos" em uma lista contendo apenas os nomes de seus campos?</p><p>Nós experimentamos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5eda7a79493ee81/6a17f11c9da390327fe46590/112c2f447c11f154b5082725cd49b51d0a3c8a65-1214x804.png" alt="" /><p>Isso é ótimo! Melhorias em todos os aspectos. Mas será que poderíamos fazer melhor?</p><h3>Hipótese 3: Descrições no mapeamento _meta</h3><p>Se apenas os nomes dos campos, sem nenhum contexto adicional, causaram um salto tão grande, presumivelmente adicionar um contexto substancial seria ainda melhor! Não é necessariamente convencional que cada índice tenha uma descrição associada, mas é possível adicionar metadados de qualquer tipo ao objeto _meta do mapeamento. Retornamos aos índices gerados e adicionamos descrições para cada índice em nosso conjunto de dados. Contanto que as descrições não sejam excessivamente longas, elas devem usar menos tokens do que o mapeamento completo e fornecer informações significativamente melhores sobre quais dados estão incluídos no índice. Nosso experimento validou essa hipótese.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt61b85cf40e0e6357/6a17f11dfbc5f82809491bbe/32d2692ad4479d0e52d8ee723dcc5710a6ec90f3-1208x806.png" alt="" /><p>Uma pequena melhoria, e agora temos mais de 90% de precisão em todos os aspectos.</p><h3>Hipótese 4: O todo é maior que a soma das partes.</h3><p>Os nomes dos campos aumentaram nossos resultados. As descrições aumentaram nossos resultados. Portanto, utilizar <em>tanto </em>as descrições quanto os nomes dos campos deve apresentar resultados ainda melhores, certo?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte6297c6aaf7db802/6a17f11e14d90c1bd779b6e6/114cbb408ff16b136251d2265416bd5270380fe5-1208x794.png" alt="" /><p>Os dados indicaram "não" (nenhuma mudança em relação ao experimento anterior). A principal teoria era que, como as descrições foram geradas a partir dos campos/mapeamentos do índice, não havia informações suficientes entre esses dois contextos para adicionar algo "novo" ao combiná-los. Além disso, a carga útil que estamos enviando para nossos 20 índices de teste está ficando bastante grande. A linha de raciocínio que seguimos até agora não é escalável. Na verdade, há bons motivos para acreditar que nenhum dos nossos experimentos até agora funcionaria em clusters Elasticsearch, onde existem centenas ou milhares de índices para escolher. Qualquer abordagem que aumente linearmente o tamanho da mensagem enviada ao LLM à medida que o número total de índices aumenta provavelmente não será uma estratégia generalizável.</p><p>O que realmente precisamos é de uma abordagem que nos ajude a reduzir um grande número de candidatos apenas às opções mais relevantes…</p><p>O que temos aqui é um problema de busca.</p><h3>Hipótese 5: Seleção via busca semântica</h3><p>Se o nome de um índice tiver significado semântico, ele poderá ser armazenado como um vetor e pesquisado semanticamente.</p><p>Se os nomes dos campos de um índice tiverem significado semântico, eles podem ser armazenados como vetores e pesquisados semanticamente.</p><p>Se um índice possui uma descrição com significado semântico, ele também pode ser armazenado como um vetor e pesquisado semanticamente.</p><p>Atualmente, os índices do Elasticsearch não tornam nenhuma dessas informações pesquisável (talvez devêssemos!), mas foi bastante trivial<a href="https://github.com/elastic/connectors/pull/3638"> improvisar algo</a> que pudesse contornar essa lacuna. Utilizando a estrutura de conectores da Elastic, criei um conector que gera um documento para cada índice em um cluster. Os documentos resultantes seriam algo como:</p> doc = {
                "_id": index_name,
                "index_name": index_name,
			"meta_description”: description,
"field_descriptions" = field_descriptions,
                "mapping": json.dumps(mapping),  
                "source_cluster": self.es_client.configured_host,
            }<p>Enviei esses documentos para um novo índice onde defini manualmente o mapeamento da seguinte forma:</p>{
   "mappings": {
       "properties": {
           "semantic_content": {
               "type": "semantic_text"
           },
           "index_name": {
               "type": "text",
               "copy_to": "semantic_content"
           },
           "mapping": {
               "type": "keyword",
               "copy_to": "semantic_content"
           },
           "source_cluster": {
               "type": "keyword"
           },
           "meta_description": {
               "type": "text",
               "copy_to": "semantic_content"
           },
           "field_descriptions": {
               "type": "text",
               "copy_to": "semantic_content"
           }
       }
   }
}<p>Isso cria um único campo semantic_content, onde todos os outros campos com significado semântico são divididos em blocos e indexados. A busca neste índice torna-se trivial, bastando:</p>GET indexed-indices/_search
{
 "query": {
   "semantic": {
     "field": "semantic_content",
     "query": "$query"
   }
 }
}<p>A ferramenta <code>index_explorer</code> modificada agora é <em>muito</em> mais rápida, pois não precisa fazer uma solicitação a um LLM, mas pode solicitar um único embedding para a consulta fornecida e executar uma operação de busca vetorial eficiente. Considerando o resultado mais relevante como nosso índice selecionado, obtivemos os seguintes resultados:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc27c302e6bef0b23/6a17f120577262d2f21bccdc/06ef5d78040d064d3444793f636d527d9e19a869-1214x800.png" alt="" /><p>Essa abordagem é escalável. Essa abordagem é eficiente. Mas essa abordagem é pouco melhor do que a nossa abordagem inicial. Isso não é surpreendente; a abordagem de busca aqui é incrivelmente ingênua. Não há nuances. Não há reconhecimento de que o nome e a descrição de um índice devam ter mais peso do que um nome de campo arbitrário que o índice contenha. Não há como priorizar correspondências lexicais exatas em detrimento de correspondências sinônimas. No entanto, construir uma consulta altamente detalhada exigiria muitas suposições sobre os dados disponíveis. Até agora, já fizemos algumas suposições importantes sobre o significado semântico dos nomes de índices e campos, mas precisaríamos ir um passo além e começar a supor <em>o quanto</em> de significado eles têm e como se relacionam entre si. Sem fazer isso, provavelmente não conseguiremos identificar com segurança a melhor correspondência como nosso resultado principal, mas podemos afirmar com mais certeza que a melhor correspondência está em algum lugar entre os N melhores resultados. Precisamos de algo que possa consumir informações semânticas no contexto em que existem, comparando-as com outra entidade que pode se representar de uma maneira semanticamente distinta, e fazendo um julgamento entre elas. Como um mestrado em Direito.</p><h3>Hipótese 6: Redução do conjunto de candidatos</h3><p>Houve vários outros experimentos que vou abordar superficialmente, mas o principal avanço foi abandonar a ideia de escolher a melhor correspondência puramente com base em uma busca semântica e, em vez disso, usar a busca semântica como um filtro para eliminar índices irrelevantes da análise do LLM. Combinamos os algoritmos Linear Retrievers, Hybrid Search com RRF e <code>semantic_text</code> em <a href="https://gist.github.com/seanstory/d704443120e20f6c844db10e30066860">nossa busca</a>, limitando os resultados aos 5 índices de correspondência principais.</p><p>Em seguida, para cada correspondência, adicionamos o nome do índice, a descrição e os nomes dos campos a uma mensagem para o LLM. Os resultados foram fantásticos:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7ac4cb8f7153fdf9/6a17f121af47b66d1dcde082/8fcabd78f591f90d6bc7c0e087d31317e4eef791-1206x804.png" alt="" /><p>A maior precisão obtida em qualquer experimento até hoje! E como essa abordagem não aumenta o tamanho da mensagem proporcionalmente ao número total de índices, ela é muito mais escalável.</p><h2>Resultados</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8d66130d9fae6bea/6a17f123ddf97d7527910c19/04d630797213dbb8bf567da41d1cdd5c7b4586c9-1600x521.png" alt="" /><p>O primeiro resultado claro foi que nossa linha de base <em>pode</em> ser melhorada. Isso parece óbvio em retrospectiva, mas antes do início da experimentação, houve uma discussão séria sobre se deveríamos abandonar completamente nossa ferramenta <code>index_explorer</code> e confiar na configuração explícita do usuário para limitar o espaço de busca. Embora essa ainda seja uma opção viável e válida, esta pesquisa mostra que existem caminhos promissores para automatizar a seleção de índices quando essas informações fornecidas pelo usuário não estão disponíveis.</p><p>A próxima conclusão clara foi que simplesmente adicionar mais caracteres descritivos ao problema tem resultados cada vez menores. Antes desta pesquisa, estávamos debatendo se deveríamos investir na expansão da capacidade do Elasticsearch para armazenar <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-field-meta">metadados em nível de campo</a>. Atualmente, esses valores <code>meta</code> são limitados a 50 caracteres, e havia uma suposição de que precisaríamos aumentar esse valor para podermos obter uma compreensão semântica de nossos campos. Claramente, esse não é o caso, e o LLM parece funcionar muito bem apenas com os nomes das áreas de estudo. Poderemos investigar isso mais a fundo posteriormente, mas já não parece urgente.</p><p>Por outro lado, isso forneceu evidências claras da importância de se ter metadados de índice "pesquisáveis". Para esses experimentos, nós hackeamos um índice de índices. Mas isso é algo que poderíamos investigar, integrando diretamente ao Elasticsearch, criando APIs para gerenciar ou, pelo menos, estabelecendo uma convenção a respeito. Estaremos avaliando nossas opções e discutindo internamente, então fiquem atentos.</p><p>Finalmente, esse esforço confirmou o valor de dedicarmos tempo para experimentar e tomar decisões baseadas em dados. Na verdade, isso nos ajudou a reafirmar que nosso produto Agent Builder precisará de recursos robustos de avaliação integrados. Se precisarmos construir toda uma estrutura de testes apenas para uma ferramenta que seleciona índices, nossos clientes certamente precisarão de maneiras de avaliar qualitativamente suas ferramentas personalizadas à medida que fazem ajustes iterativos.</p><p>Estou ansioso para ver o que vamos construir, e espero que você também esteja!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Na Elastic]]></category>
    <category><![CDATA[Busca híbrida]]></category>
    <dc:creator><![CDATA[Sean Story]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt68d11a4c7fd11d4c/6a17f1257b54f9b6598b39d4/42903c869e034674b30bb36013345aaa97f6608b-1184x864.png" length="0" type="image/png"/>
    <pubDate>Mon, 06 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Seu primeiro Agente Elástico: De uma simples consulta a um chat com inteligência artificial.]]></title>
    <description><![CDATA[Aprenda a usar o construtor de agentes de IA da Elastic para criar agentes de IA especializados. Neste blog, vamos construir um agente de IA para o setor financeiro.]]></description>
    <content:encoded><![CDATA[<p>Com o novo <a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Agent Builder</a> da Elastic, você pode criar agentes de IA especializados que atuam como especialistas em seus domínios de negócios específicos. Essa funcionalidade vai além de simples painéis e barras de pesquisa, transformando seus dados de um recurso passivo em um parceiro ativo e interativo.</p><p>Imagine um gerente financeiro que precisa se atualizar antes de uma reunião com um cliente. Em vez de vasculhar manualmente os feeds de notícias e comparar painéis de portfólio, agora eles podem simplesmente fazer uma pergunta direta ao seu agente personalizado. Essa é a vantagem de uma abordagem que prioriza o bate-papo. O gestor tem acesso direto e conversacional aos seus dados, podendo fazer perguntas como: "Quais são as últimas notícias sobre a ACME Corp e como isso afeta os investimentos do meu cliente?" e obtendo uma resposta sintetizada e especializada em segundos.</p><p>Embora estejamos criando um especialista financeiro hoje, as aplicações são tão variadas quanto seus dados. O mesmo poder pode criar um analista de cibersegurança para procurar ameaças, um engenheiro de confiabilidade de sites para diagnosticar uma interrupção ou um gerente de marketing para otimizar uma campanha. Independentemente da área, a missão principal é a mesma: transformar seus dados em um especialista com quem você possa conversar.</p><h2>Etapa 0: Nosso conjunto de dados</h2><p>Nosso conjunto de dados hoje é um conjunto de dados sintético baseado em finanças, composto por contas financeiras, posições de ativos, notícias e relatórios financeiros. Embora sintética, ela replica uma versão simplificada de um conjunto de dados financeiro real.</p><p><code>financial_accounts</code>Portfólios de clientes com perfis de risco</p><p><code>financial_holdings</code>Posições em ações/ETFs/títulos com histórico de compras</p><p><code>financial_asset_details</code>Detalhes sobre a ação/ETF/título</p><p><code>financial_news</code>Artigos de mercado gerados por IA com análise de sentimento</p><p><code>financial_reports</code>Resultados da empresa e notas dos analistas</p><p>Você pode carregar este conjunto de dados por conta própria seguindo as instruções do notebook que acompanha este documento, localizado <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">aqui</a>.</p><h2>Etapa 1: A Base — Sua Lógica de Negócios em ES|QL</h2><p>Toda habilidade de IA começa com uma base lógica sólida. Para o nosso agente de Gestão Financeira, precisamos ensiná-lo a responder a uma pergunta comum: "Estou preocupado com o sentimento do mercado." Você pode me mostrar quais dos nossos clientes correm maior risco em caso de más notícias? Essa questão vai além de uma simples pesquisa. Isso exige que correlacionemos o sentimento do mercado com as carteiras dos clientes.</p><p>Precisamos encontrar os ativos mencionados em artigos negativos, identificar todos os clientes que possuem esses ativos, calcular o valor de mercado atual da sua exposição e, em seguida, classificar os resultados para priorizar o maior risco. Essa análise complexa de múltiplas junções é a tarefa perfeita para nossa ferramenta avançada ES|QL.</p><p>Aqui está a consulta completa que usaremos. Parece impressionante, mas os conceitos são simples.</p><h2>Analisando em detalhes: Junções e guarda-corpos</h2><p>Nesta consulta, dois conceitos importantes entram em jogo e são essenciais para a criação do Agent Builder.</p><h3>1. A junção de pesquisa</h3><p>Durante anos, uma das funcionalidades mais solicitadas no Elasticsearch tem sido a capacidade de unir dados de diferentes índices com base em uma chave comum. Com ES|QL, isso agora é possível com <code>LOOKUP JOIN</code>.</p><p>Em nossa nova consulta, realizamos uma cadeia de três <code>LOOKUP JOIN</code>: primeiro conectando notícias negativas aos detalhes dos ativos, depois vinculando esses ativos às participações do cliente e, finalmente, unindo às informações da conta do cliente. Isso gera um resultado incrivelmente rico a partir de quatro índices diferentes em uma única consulta eficiente. Isso significa que podemos combinar conjuntos de dados distintos para criar uma resposta única e esclarecedora sem precisar desnormalizar todos os nossos dados em um único índice gigante antecipadamente.</p><h3>2. Parâmetros como guarda-corpos LLM</h3><p>Você notará que a consulta usa <code>?time_duration</code>. Isso não é apenas uma variável; é uma proteção para a IA. Embora os Modelos de Linguagem de Grande Porte (LLMs, na sigla em inglês) sejam ótimos para gerar consultas, permitir que eles tenham livre acesso aos seus dados pode levar a consultas ineficientes ou até mesmo incorretas.</p><p>Ao criar uma consulta parametrizada, forçamos o LLM a funcionar dentro da lógica de negócios testada, eficiente e correta que um especialista humano já definiu. É semelhante à forma como os desenvolvedores usam modelos de pesquisa há anos para expor com segurança os recursos de consulta aos aplicativos. O agente pode interpretar a solicitação de um usuário como "esta semana" para preencher o parâmetro <code>time_duration</code> , mas deve usar nossa estrutura de consulta para obter a resposta. Isso nos proporciona o equilíbrio perfeito entre flexibilidade e controle.</p><p>Em última análise, essa consulta permite que um especialista que entende os dados incorpore seu conhecimento em uma ferramenta. Outras pessoas — e agentes de IA — podem então usar essa ferramenta para obter resultados correlacionados, fornecendo simplesmente um único parâmetro, sem precisar saber nada sobre a complexidade subjacente.</p><h2>Etapa 2: A Habilidade — Transformar uma Consulta em uma Ferramenta Reutilizável</h2><p>Uma consulta ES|QL é apenas texto até que a registremos como uma <strong>ferramenta</strong>. No Construtor de Agentes, uma ferramenta é mais do que apenas uma consulta salva; é uma "habilidade" que um agente de IA pode entender e optar por usar. A mágica está na <strong>descrição em linguagem natural</strong> que fornecemos. Essa descrição serve de ponte entre a pergunta do usuário e a lógica de consulta subjacente. Vamos registrar a consulta que acabamos de criar.</p><h3>O Caminho da Interface do Usuário</h3><p>Criar uma ferramenta no Kibana é um processo simples.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte73e11c1d87593fa/6a17f2134202294dae29f6f2/a29c53a73b99af5972273c51218ea9004a9b0abb-1600x812.png" alt="Como criar uma ferramenta no Kibana." /><p>1. Navegue até <strong>Agentes</strong></p><ul><li><p>Clique em<strong> Ferramentas </strong>ou <strong>Gerenciar Ferramentas</strong> e clique no botão <strong>Nova ferramenta</strong> .</p></li></ul><p>2. Preencha o formulário com os seguintes dados:</p><ul><li><p><strong>ID da ferramenta:</strong> <code>find_client_exposure_to_negative_news</code></p></li></ul><p>             eu. Este é o ID exclusivo da ferramenta.</p><ul><li><p><strong>Descrição:</strong> "Identifica a exposição da carteira de clientes a notícias negativas." Esta ferramenta analisa notícias e relatórios recentes em busca de sentimentos negativos, identifica o ativo associado e encontra todos os clientes que possuem esse ativo. Retorna uma lista ordenada pelo valor de mercado atual da posição para destacar o maior risco potencial."</p></li></ul><p>             eu. É isso que o LLM lê para decidir se essa ferramenta é a adequada para o trabalho.</p><ul><li><p><strong>Rótulos</strong>: <code>retrieval</code> e <code>risk-analysis</code></p></li></ul><p>         Etiquetas são usadas para ajudar a agrupar várias ferramentas.</p><ul><li><p><strong>Configuração:</strong> Cole a consulta ES|QL completa da Etapa 1.</p></li></ul><p>            eu. Esta é a pesquisa que o agente usará.</p><p>3. Clique em <strong>Inferir parâmetros da consulta</strong>. A interface do usuário encontrará automaticamente <code>?time_duration</code> e listará abaixo. Adicione uma descrição simples para cada um, para ajudar o agente (e outros usuários) a entender sua finalidade.</p><ul><li><p><code>time_duration</code>O período de tempo para pesquisar notícias negativas. O formato é "X horas", com o valor padrão de 8760 horas.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7afbb0589c1828ad/6a17f2146864a44e7cb688a9/deb422d97863f78dbe08bfa2e3c708d1f75166ff-1600x938.png" alt="Configurar sua ferramenta, incluindo sua lógica e quaisquer parâmetros necessários, usando uma consulta ESQL. " /><p>4. Teste!</p><ul><li><p>Clique em Salvar e testar.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd09afbef6e21a93/6a17f2162f4a5c73b1fa89fd/57e768b88327821e70bd616744822f98fa367362-732x136.png" alt="O mesmo botão de teste no Kibana." /><ul><li><p>Você verá um novo menu suspenso onde poderá testar a consulta para garantir que ela esteja funcionando conforme o esperado.</p></li></ul><p>             eu. Em <code>time_duration</code> insira o intervalo desejado; aqui, estamos usando “8760 horas”.</p><ul><li><p>Clique em “Enviar” e, se tudo correr bem, você verá uma resposta em formato JSON. Para garantir que funcione como esperado, role para baixo e observe o objeto <code>values</code> . É aí que os documentos correspondentes são devolvidos.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89bdc3f093363f2a/6a17f217be60861c9c00488a/7e0c5171a4f7ffdfc1830f1a05a9acb987870b75-1600x722.png" alt="Resposta JSON que aparece após clicar em enviar." /><p>5. Clique no “X” no canto superior direito para fechar a janela de teste. Sua nova ferramenta agora aparecerá na lista, pronta para ser atribuída a um agente.</p><h3>O caminho da API</h3><p>Para desenvolvedores que preferem automação ou precisam gerenciar ferramentas programaticamente, é possível obter o mesmo resultado com uma única chamada de API. Basta enviar uma solicitação <code>POST</code> para o endpoint <code>/api/agent_builder/tools</code> com a definição da ferramenta.</p>POST kbn://api/agent_builder/tools
{
  "id": "find_client_exposure_to_negative_news",
  "type": "esql",
  "description": "Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.",
  "configuration": {
    "query": """
        FROM financial_news, financial_reports METADATA _index
        | WHERE sentiment == "negative"
        | WHERE coalesce(published_date, report_date) &gt;= NOW() - TO_TIMEDURATION(?time_duration)
        | RENAME primary_symbol AS symbol
        | LOOKUP JOIN financial_asset_details ON symbol
        | LOOKUP JOIN financial_holdings ON symbol
        | LOOKUP JOIN financial_accounts ON account_id
        | WHERE account_holder_name IS NOT NULL
        | EVAL position_current_value = quantity * current_price.price
        | RENAME title AS news_title
        | KEEP
            account_holder_name, symbol, asset_name, news_title,
            sentiment, position_current_value, quantity, current_price.price,
            published_date, report_date
        | SORT position_current_value DESC
        | LIMIT 50
      """,
    "params": {
      "time_duration": {
        "type": "keyword",
        "description": """The timeframe to search back for negative news. Format is "X hours" DEFAULT TO 8760 hours """
      }
    }
  },
  "tags": [
    "retrieval",
    "risk-analysis"
  ]
}<h2>Etapa 3: O Cérebro — Criando seu Agente Personalizado</h2><p>Criamos uma habilidade reutilizável (a Ferramenta). Agora, precisamos criar o <strong>Agente</strong>, a persona que de fato irá utilizá-lo. Um Agente é a combinação de um LLM (Licença de Aprendizagem Baseada em Leis), um conjunto específico de ferramentas às quais você lhe concede acesso e, mais importante, um conjunto de <strong>Instruções Personalizadas</strong> que atuam como sua constituição, definindo sua personalidade, regras e propósito.</p><h3>A Arte do Prompt</h3><p>O aspecto mais importante na criação de um agente confiável e especializado é o prompt. Um conjunto de instruções bem elaborado é o que diferencia um chatbot genérico de um assistente profissional e focado. É aqui que você define as diretrizes, define a saída e atribui ao agente sua missão.</p><p>Para o nosso agente <code>Financial Manager</code> , usaremos o seguinte prompt.</p>You are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.

**Your Core Mission:**
- Respond accurately and concisely to natural language queries from financial managers.
- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.
- Summarize key data points and trends based on user requests.

**Reasoning Framework:**
1.  **Understand:** Deconstruct the user's query to understand their core intent.
2.  **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.
3.  **Execute:** Use the available tools to execute your plan.
4.  **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.

**Key Directives and Constraints:**
- **If a user's request is ambiguous, ask clarifying questions before proceeding.**
- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.
- Stay strictly on topic with financial data queries.
- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.
- All numerical values should be formatted appropriately (e.g., currency, percentages).

**Output Format:**
- All responses must be formatted using **Markdown** for clarity.
- When presenting structured data, use Markdown tables, lists, or bolding.

**Start by greeting the financial manager and offering assistance.**<p>Vamos analisar por que essa estratégia é tão eficaz:</p><ul><li><p><strong>Define uma persona sofisticada: </strong>a primeira frase estabelece imediatamente o agente como um "Assistente de Inteligência de Dados especializado", definindo um tom profissional e competente.</p></li><li><p><strong>Isso fornece uma estrutura de raciocínio: </strong>ao dizer ao agente para "Compreender, Planejar, Executar e Sintetizar", estamos lhe dando um procedimento operacional padrão. Isso melhora sua capacidade de lidar com questões complexas e de várias etapas.</p></li><li><p><strong>Isso promove o diálogo interativo: </strong>a instrução para "fazer perguntas esclarecedoras" torna o agente mais robusto. Isso minimizará suposições incorretas sobre solicitações ambíguas, levando a respostas mais precisas.</p></li></ul><h3>O Caminho da Interface do Usuário</h3><p>1. Navegue até <strong>Agentes.</strong></p><ul><li><p>Clique em<strong> Ferramentas </strong>ou <strong>Gerenciar Ferramentas</strong> e clique no botão <strong>Nova ferramenta</strong> .</p></li></ul><p>2. Preencha os dados básicos:</p><ul><li><p><strong>ID do agente:</strong> <code>financial_assistant</code>.</p></li><li><p><strong>Instruções: </strong>Copie o enunciado acima.</p></li><li><p><strong>Rótulos</strong>: <code>Finance</code>.</p></li><li><p><strong>Nome de exibição:</strong> <code>Financial Assistant</code>.</p></li><li><p><strong>Descrição da exibição: </strong><code>An assistant for analyzing and understanding your financial data</code>.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ac12cbd2b689dee/6a17f219dbb4ff262bfb57ef/18ea73f1cae620129c0afa0e7ba9e2a3390224a7-1600x1189.png" alt="Criando um assistente financeiro - preenchendo o campo de identificação do agente." /><p>3. De volta ao topo, clique em <strong>Ferramentas</strong>.</p><ul><li><p>Marque a caixa ao lado da nossa ferramenta <code>find_client_exposure_to_negative_news</code> .</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcd23556e556a76c5/6a17f21baf47b63a9fcde0a0/0c1e4ecbbd51d0dd10c6e861dbe9a9ccddeb35f6-1600x149.png" alt="" /><p>4. Clique em <strong>Salvar</strong>.</p><h3>O caminho da API</h3><p>Você pode criar o mesmo agente com uma solicitação <code>POST</code> para o endpoint <code>/api/agent_builder/agents</code> . O corpo da solicitação contém todas as mesmas informações: o ID, o nome, a descrição, o conjunto completo de instruções e uma lista das ferramentas que o agente tem permissão para usar.</p>POST kbn://api/agent_builder/agents
    {
      "id": "financial_assistant",
      "name": "Financial Assistant",
      "description": "An assistant for analyzing and understanding your financial data",
      "labels": [
        "Finance"
      ],
      "avatar_color": "#16C5C0",
      "avatar_symbol": "💰",
      "configuration": {
        "instructions": """You are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.

**Your Core Mission:**
- Respond accurately and concisely to natural language queries from financial managers.
- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.
- Summarize key data points and trends based on user requests.

**Reasoning Framework:**
1.  **Understand:** Deconstruct the user's query to understand their core intent.
2.  **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.
3.  **Execute:** Use the available tools to execute your plan.
4.  **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.

**Key Directives and Constraints:**
- **If a user's request is ambiguous, ask clarifying questions before proceeding.**
- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.
- Stay strictly on topic with financial data queries.
- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.
- All numerical values should be formatted appropriately (e.g., currency, percentages).

**Output Format:**
- All responses must be formatted using **Markdown** for clarity.
- When presenting structured data, use Markdown tables, lists, or bolding.

**Start by greeting the financial manager and offering assistance.**
""",
        "tools": [
          {
            "tool_ids": [
              "platform.core.search",
              "platform.core.list_indices",
              "platform.core.get_index_mapping",
              "platform.core.get_document_by_id",
              "find_client_exposure_to_negative_news"
            ]
          }
        ]
      }
    }<h2>Passo 4: A Recompensa — Ter uma Conversa</h2><p>Temos nossa lógica de negócios encapsulada em uma ferramenta e um "cérebro" pronto para usá-la em nosso Agente. Chegou a hora de ver tudo se concretizar. Agora podemos começar a interagir com nossos dados usando um agente especializado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8826539b16e46f4/6a17f21d505ac35924ad8c5c/5414cb6b7c41365acb0356a8bfe1140751ffd8db-1600x1014.png" alt="Ter uma conversa com o Elastic Agent Builder após criar um assistente financeiro." /><h3>O Caminho da Interface do Usuário</h3><ol><li><p>Navegue até <strong>Agentes </strong>no Kibana.</p></li><li><p>Utilizando o menu suspenso no canto inferior direito da janela de chat, alterne do <strong>agente padrão Elastic AI</strong> para o nosso novo agente <strong>Assistente Financeiro </strong> .</p></li><li><p>Faça uma pergunta que permita ao agente usar nossa ferramenta especializada:</p><ol><li><p><em>Estou preocupado com o sentimento do mercado. Você pode me mostrar quais dos nossos clientes correm maior risco em caso de más notícias?</em></p></li></ol></li></ol><p>Após alguns instantes, o agente retornará uma resposta completa e perfeitamente formatada. Devido à natureza dos LLMs, sua resposta pode ser formatada de maneira ligeiramente diferente, mas nesta execução, o agente retornou:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta1e163fd7c4416bd/6a17f21f6864a4e35bb688ad/17b4ed43d279f9e53ee9fe3d482d0b2ec359a083-1600x1088.png" alt="Uma resposta criada pelo Elastic Agent Builder como assistente financeiro para: clientes com maior risco de sofrer com notícias negativas." /><h3>O que acabou de acontecer? O Raciocínio do Agente</h3><p>O agente não apenas "sabia" a resposta. Executou um plano de várias etapas centrado na seleção da melhor ferramenta para o trabalho. Eis uma análise do seu processo de pensamento:</p><ul><li><p><strong>Intenção identificada:</strong> Correspondeu a palavras-chave da sua pergunta, como "risco" e "notícias negativas", à descrição da ferramenta <code>find_client_exposure_to_negative_news</code> .</p></li><li><p><strong>Plano executado:</strong> o sistema extraiu o período de tempo da sua solicitação e fez uma <strong>única chamada</strong> para essa ferramenta especializada.</p></li><li><p><strong>Delegou o trabalho:</strong> a ferramenta então realizou todo o trabalho pesado: as junções encadeadas, os cálculos de valor e a classificação.</p></li><li><p><strong>Resultado Sintetizado:</strong> Por fim, o agente formatou os dados brutos da ferramenta em um resumo claro e legível para humanos, seguindo as regras do prompt.</p></li></ul><p>E não precisamos apenas supor, se ampliarmos nosso pensamento e observarmos mais detalhes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93f6075be8495418/6a17f221af47b65eadcde0a4/6a4da9262d3f88c60bfd8f8bf9b67c3b84e961ba-1600x607.png" alt="Os 50 documentos que a assistente financeira encontrou em clientes com maior exposição a notícias negativas." /><h3>O caminho da API</h3><p>Você pode iniciar essa mesma conversa programaticamente. Basta enviar a pergunta de entrada para o endpoint da API <code>converse</code> , certificando-se de especificar o <code>agent_id</code> do nosso <code>financial_manager</code>.</p>POST kbn://api/agent_builder/converse
{
  "input": "Show me our largest positions affected by negative news",
  "agent_id": "financial_assistant"
}<h2>Para desenvolvedores: Integração com a API</h2><p>Embora a interface do Kibana ofereça uma experiência fantástica e intuitiva para criar e gerenciar seus agentes, tudo o que você viu hoje também pode ser feito programaticamente. O Agent Builder é baseado em um conjunto de APIs, permitindo que você integre essa funcionalidade diretamente em seus próprios aplicativos, pipelines de CI/CD ou scripts de automação.</p><p>Os três principais endpoints com os quais você trabalhará são:</p><ul><li><p><strong><code>/api/agent_builder/tools</code></strong>O ponto de extremidade para criar, listar e gerenciar as habilidades reutilizáveis que seus agentes podem usar.</p></li><li><p><strong><code>/api/agent_builder/agents</code></strong>O ponto final para definir as personas dos seus agentes, incluindo as importantíssimas instruções e atribuições de ferramentas.</p></li><li><p><strong><code>/api/agent_builder/converse</code></strong>: O ponto de acesso para interagir com seus agentes, iniciar conversas e obter respostas.</p></li></ul><p>Para um passo a passo completo e prático de como usar essas APIs para executar cada etapa deste tutorial, confira o <strong>Jupyter Notebook</strong> que acompanha o tutorial, disponível <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">aqui</a> em nosso repositório do GitHub.</p><h2>Conclusão: Sua vez de construir</h2><p>Começamos por pegar numa consulta ES|QL e transformá-la numa habilidade reutilizável. Em seguida, criamos um agente de IA especializado, atribuindo-lhe uma missão e regras claras, e capacitando-o com essa habilidade. O resultado é um assistente sofisticado que consegue entender uma pergunta complexa e executar uma análise em várias etapas para fornecer uma resposta precisa e baseada em dados.</p><p>Esse fluxo de trabalho é fundamental para o novo <strong>Construtor de Agentes</strong> da Elastic. Ele foi projetado para ser simples o suficiente para que usuários sem conhecimento técnico possam criar agentes por meio da interface do usuário, mas também sofisticado o bastante para que desenvolvedores criem aplicativos personalizados com inteligência artificial utilizando nossas APIs. Mais importante ainda, permite que você conecte LLMs aos seus próprios dados de forma segura e protegida, regida pela lógica especializada que você define, e converse com seus dados.</p><h2>Pronto para usar agentes para conversar com seus dados?</h2><p>A melhor maneira de consolidar o que você aprendeu é colocar a mão na massa. Experimente tudo o que discutimos hoje em nossa <a href="https://www.elastic.co/training/elastic-ai-agents-mcp"><strong>oficina prática, gratuita e interativa</strong></a>. Você passará por todo esse processo e muito mais em um ambiente sandbox dedicado.</p><p>Em um post futuro do blog, mostraremos como usar um aplicativo independente que interage com nosso agente <code>Financial Assistant</code> e exploraremos o <strong>Protocolo de Contexto de Modelo (MCP)</strong> que torna tudo isso possível. E em um post separado, discutiremos o suporte do Agent Builder ao protocolo Agent2Agent, ou A2A, ainda em desenvolvimento.</p><p>Fiquem ligados e boas construções!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Na Elastic]]></category>
    <dc:creator><![CDATA[Jeff Vestal]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbe5e78eeb775d715/6a17f2230b0bed719ddd369a/ca853555eaa213f10f1db8c0ab0a2bbacee97b88-1456x816.png" length="0" type="image/png"/>
    <pubDate>Thu, 25 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando fluxos de trabalho com agentes de IA usando o Elasticsearch.]]></title>
    <description><![CDATA[Conheça o Agent Builder, uma nova camada de IA no Elasticsearch que fornece uma estrutura para a criação de fluxos de trabalho de IA baseados em agentes, usando pesquisa híbrida para fornecer aos agentes o contexto necessário para raciocinar e agir.]]></description>
    <content:encoded><![CDATA[<p>Aqui na Elastic, temos vindo a trazer contexto para LLMs e interfaces conversacionais com Assistentes de IA, RAG avançado e melhorias na base de dados vetorial. Recentemente, com o surgimento de agentes de IA, vimos crescer a necessidade de contexto relevante e aprendemos que<strong> agentes de IA de alto impacto precisam de uma ótima ferramenta de busca</strong>. Por isso, criamos novas funcionalidades nativas no Elastic Stack, projetadas para ajudar no desenvolvimento de agentes de IA que aproveitam seus dados no Elasticsearch. Gostaríamos de compartilhar nosso progresso nessa jornada e para onde vemos que ela nos levará no futuro.</p><h2>Construtor de Agentes: Uma Base para a Criação de Agentes de IA Orientados por Dados</h2><p>A promessa de um agente de IA é simples: dê a ele um objetivo e ele realizará a tarefa. Mas para os desenvolvedores, a realidade é uma série de desafios complexos. Em primeiro lugar, um agente é tão bom quanto a sua percepção do ambiente e das ferramentas que lhe são fornecidas para atingir os objetivos do usuário. Além disso, fornecer o contexto correto em meio a um mar de dados empresariais diversos é um desafio enorme. Finalmente, tudo isso precisa ser orquestrado por um circuito de raciocínio confiável que possa planejar, executar e aprender.</p><p>Para resolver isso, os desenvolvedores precisam construir uma estrutura complexa e frágil do zero. A arquitetura de agentes atual exige a integração de várias peças distintas: um LLM (Modelo de Aprendizado de Liderança), um banco de dados vetorial, um repositório de metadados, sistemas separados para registro e rastreamento, e alguma forma de avaliar se tudo está funcionando corretamente. Isso não é apenas complexo; é caro, propenso a erros e dificulta a criação de sistemas de IA confiáveis e de alta qualidade que seus usuários exigem.</p><p>Por isso, queremos simplificar. Para isso, nossa abordagem consiste em pegar os elementos essenciais de um agente orientado ao contexto eficaz e integrá-los diretamente ao núcleo do Elasticsearch com um novo conjunto de recursos chamado <strong>Elastic AI Agent Builder</strong>. Essa nova camada fornece uma estrutura com todos os componentes essenciais para a criação de agentes de IA baseados no Elasticsearch: um conjunto aberto de primitivas, protocolos baseados em padrões e acesso seguro aos dados — para que você possa criar sistemas de agentes adaptados a dados e requisitos do mundo real:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2779dae5df010328/6a17e15eabe0f24f18dfe931/1ee1e73dd3f485ce86294d39490c98ce2a3d9925-1238x1072.png" alt="" /><p><strong>Proporcionar experiências com IA</strong>: esse é o objetivo final. Com nossa Plataforma de IA de Busca e seus dados como base, você pode criar qualquer tipo de aplicativo de IA generativa: desde interfaces de bate-papo personalizadas até integrações com frameworks de agentes como o LangChain ou aplicativos de negócios como o Salesforce.</p><p><strong>Com tecnologia Agents &amp; Tools</strong>: sobre a plataforma, expomos uma camada de abstrações limpa e simples. Você interage diretamente com agentes e ferramentas, que podem ser personalizadas para atender às suas necessidades específicas. Você também pode acessar os recursos da plataforma por meio de APIs robustas e padrões abertos como MCP e A2A.</p><p><strong>Habilitado pela Plataforma de IA de Busca</strong>: este é o mecanismo principal onde integramos os componentes. O banco de dados vetorial avançado, a lógica do agente, a construção de consultas, os recursos de segurança e o rastreamento para avaliação, tudo reside aqui, gerenciado e otimizado pela Elastic.</p><p><strong>Desvendando o poder dos seus dados</strong>: a base de qualquer agente de sucesso são dados de alta qualidade. Nossa plataforma começa com a capacidade de ingerir ou federar o acesso a todos os dados da sua empresa.</p><h2>Construção de Agentes na Plataforma</h2><p>O Agent Builder, integrado à Plataforma de IA de Busca, fornece uma estrutura completa para o desenvolvimento de agentes. É construído sobre cinco pilares fundamentais, cada um projetado para abordar um aspecto crítico da construção e implantação de sistemas de IA de nível de produção. Vamos analisar como os agentes definem o objetivo, as ferramentas fornecem as capacidades, os padrões abertos garantem a interoperabilidade, a avaliação proporciona transparência e a segurança garante a confiança.</p><h3>Agentes</h3><p>Os agentes são o bloco de construção de nível mais alto nesta nova camada do Elasticsearch. Um agente define o objetivo a ser alcançado, o conjunto de ferramentas disponíveis para execução e as fontes de dados sobre as quais pode operar. Os agentes não se limitam a interações conversacionais; eles podem viabilizar fluxos de trabalho completos, automação de tarefas ou experiências voltadas para o usuário.</p><p>Quando uma consulta é direcionada a um agente, ela segue um ciclo estruturado:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt774ffd7df65bd01d/6a17e15f25daabd5cc08a17f/627ad1744b629bbe27359325702f40d97e40d1f4-704x852.png" alt="" /><ol><li><p>Interprete sua contribuição e objetivo.</p></li><li><p>Selecione a ferramenta e os argumentos corretos para a execução.</p></li><li><p>Analise a resposta da ferramenta.</p></li><li><p>Decida se deseja retornar um resultado ou continuar com outras invocações da ferramenta.</p></li></ol><p>A Elastic cuida da orquestração, do contexto e da execução desse ciclo. Os desenvolvedores se concentram em definir <em>o que</em> o agente deve fazer: objetivos, ferramentas e dados, enquanto o sistema gerencia <em>como</em> o raciocínio e os fluxos de trabalho são executados.</p><p><em>O Agente Padrão</em></p><p>Nosso primeiro agente desenvolvido nesta plataforma é um agente conversacional nativo do Kibana, que permite interagir imediatamente com seus dados. Proporciona uma experiência pronta a usar, mantendo-se totalmente extensível e permitindo que você comece a interagir com seus dados imediatamente, sem necessidade de configuração adicional.</p><p>Você pode interagir com essa experiência diretamente no Kibana por meio de uma nova experiência de chat ou via API.</p><p>Consultar o agente padrão por meio da API requer apenas uma única chamada:</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>Como as conversas mantêm estado, você pode continuar interagindo com um agente usando um `conversation_id` ou recuperar o histórico completo da conversa:</p>POST kbn://api/agent_builder/converse
{
    "input": "What about the second top?",
    "conversation_id": "ec757c6c-c3ed-4a83-8e2c-756238f008bb"
}

## get the full conversation
GET kbn://api/agent_builder/conversations/ec757c6c-c3ed-4a83-8e2c-756238f008bb<p><em>Agentes alfandegários</em></p><p>Os desenvolvedores também podem criar seus próprios agentes personalizados por meio de APIs simples. Os agentes encapsulam instruções, ferramentas e acesso a dados, criando mecanismos de raciocínio personalizados.</p><p>Criar um agente personalizado é tão simples quanto fazer uma única chamada à API. O exemplo abaixo ilustra isso. O campo "configuração" contém todos os detalhes importantes, como instruções ou ferramentas disponíveis:</p>POST kbn://api/agent_builder/agents
{
  "id": "custom_agent",
  "name": "My Custom Agent",
  "description": "Description of the custom agent",
  "configuration": {
      "instructions": "You are a log expert specialising in ...",
      "tools": 
...
   }
}<p>Uma vez criado, o agente pode ser consultado diretamente:</p>POST kbn://api/agent_builder/converse
{
    "input": "What news about DIA?",
    "agent_id": "custom_agent"
}<p>Essa abordagem transforma o agente, de um sistema complexo a ser construído do zero, em uma unidade simples e declarativa de lógica de negócios, permitindo que você implemente automação inteligente mais rapidamente.</p><p>Para uma análise aprofundada sobre como construir um agente especializado do zero, consulte nosso guia detalhado, passo a passo: <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">Seu primeiro agente elástico: de uma única consulta a um bate-papo com inteligência artificial</a>.</p><h3>Ferramentas</h3><p>Se os agentes definem <em>o que</em> realizar, as ferramentas definem <em>como</em>.</p><p>As ferramentas expõem funcionalidades específicas do Elastic Core para que os agentes executem e recuperem informações ou realizem uma ação. As ferramentas podem incluir funcionalidades básicas como obter índices ou obter mapeamentos, ou funcionalidades mais avançadas como conversão de linguagem natural para ES|QL.</p><p>O Elasticsearch é fornecido com um conjunto de ferramentas padrão otimizadas para necessidades comuns. Mas a verdadeira flexibilidade vem de criar a sua própria. Ao definir as ferramentas, você decide exatamente quais consultas, índices e campos são expostos a um agente com ES|QL, proporcionando controle preciso sobre velocidade, exatidão e segurança.</p><p>O registro de uma nova ferramenta também é tão simples quanto uma única chamada de API. Você poderia criar uma ferramenta que utilizasse nossa linguagem <a href="https://www.elastic.co/search-labs/blog/esql-timeline-of-improvements">ES|QL (Elasticsearch Query Language)</a> para encontrar notícias sobre um ativo financeiro específico:</p>POST kbn://api/agent_builder/tools
{
  "id": "news_on_asset",
  "type": "esql",
  "description": "Find news and reports about a particular asset where ...",
  "configuration": {
    "query": "FROM financial_news, financial_reports | where MATCH(company_symbol, ?symbol) OR MATCH(entities, ?symbol) | limit 5",
    "params": {
      "symbol": {
        "type": "keyword",
        "description": "The asset symbol"
      }
    }
  ...
  }
...
}<p>Após o registro, você pode atribuir a nova ferramenta aos seus agentes personalizados, oferecendo a eles um conjunto selecionado de habilidades para analisar e utilizar sempre que for adequado.</p><p>Oferecemos uma plataforma para criar ferramentas personalizadas para suas necessidades específicas, por exemplo, com ES|QL, que transforma o agente de um agente de propósito geral em um especialista em um domínio específico, fundamentado em seus dados e domínio de negócios exclusivos.</p><h3>Padrões Abertos e Interoperabilidade</h3><p>Os agentes e ferramentas do Elasticsearch são expostos por meio de APIs de padrão aberto, o que facilita sua integração como blocos fundamentais dentro do ecossistema mais amplo de frameworks de agentes. Nossa abordagem é simples: sem caixas pretas. Queremos que você possa aproveitar o principal ponto forte da Elastic em buscas e combiná-lo com recursos complementares e outros sistemas de agentes.</p><p>Para tornar isso possível, estamos disponibilizando nossas capacidades por meio de APIs, protocolos emergentes e padrões abertos.</p><p><em>Protocolo de Contexto do Modelo (MCP)</em></p><p><a href="https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch">O Protocolo de Contexto de Modelo (MCP)</a> está rapidamente se tornando o padrão aberto para conectar ferramentas em diferentes sistemas. Ao oferecer suporte ao MCP, o Elasticsearch pode conectar a IA conversacional aos seus bancos de dados, índices e APIs externas. Com um servidor MCP remoto integrado ao Elastic Stack, qualquer cliente compatível com MCP pode acessar as ferramentas da Elastic e usá-las como blocos de construção em seus fluxos de trabalho de agentes mais amplos.</p><p>Esta não é uma via de mão única. Você também poderá importar ferramentas de servidores MCP externos e disponibilizá-las dentro do Elasticsearch. Em breve, os servidores MCP provavelmente estarão disponíveis para quase tudo e serão muito mais abrangentes do que qualquer coisa que pudéssemos criar por conta própria. A Elastic oferece busca e recuperação em grande escala, e você pode combinar isso com recursos especializados de outras plataformas para criar agentes eficazes.</p><p><em>Agente para Agente (A2A)</em></p><p>Também estamos trabalhando no suporte de agente para agente (A2A). Enquanto o MCP se concentra em conectar ferramentas, o A2A se concentra em conectar agentes. Com um servidor A2A, os agentes Elastic que você criar poderão se comunicar diretamente com agentes de outros sistemas: compartilhando contexto, delegando tarefas e coordenando fluxos de trabalho.</p><p>Pense nisso como interoperabilidade na camada de raciocínio. Seu agente Elastic pode lidar com a busca e recuperação de dados, depois repassar a tarefa para um agente de suporte ou de TI especializado e obter o resultado de volta sem problemas. O resultado é um ecossistema de agentes cooperativos, cada um fazendo o que faz de melhor.</p><p>Em última análise, a adoção do MCP e do A2A reforça nosso compromisso com o papel do Elasticsearch como um elemento de primeira classe, garantindo a integração aberta em todo o ecossistema de agentes.</p><h3>Rastreamento e Avaliação</h3><p>À medida que a busca se integra aos agentes, o desafio da avaliação eficaz torna-se crucial. Para implantar agentes com segurança em ambientes empresariais reais, você precisa ter a garantia de que eles não sejam apenas precisos, mas também eficientes e confiáveis. Como você mede o desempenho, diagnostica uma resposta inadequada ou melhora o nível inicial? Tudo começa com a visibilidade.</p><p>É por isso que projetamos nossas APIs de agentes com foco na transparência desde o início. Considere esta interação simples entre agentes:</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>A resposta inclui não apenas a resposta final, mas também o rastreamento completo da execução, detalhando quais ferramentas o agente selecionou, os parâmetros que utilizou e os resultados de cada etapa.</p>{
  "conversation_id": "db5c0c8b-12bf-4928-a57e-d99129ad2fea",
  "steps": [
    {
      "type": "tool_call",
      "tool_call_id": "tooluse_Nfqr3mwtR92HTRIsTcGXZQ",
      "tool_id": ".index_explorer",
      "params": {
        "query": "indices containing portfolio data"
      },
      "results": [...]
    }
    // ... more steps ...
  ],
  "response": {
    "message": "Based on the information I've gathered...."
  }
}<p>O rastreamento e o registro abrangentes são essenciais para um ciclo de melhoria contínua e, em breve, você poderá armazenar e visualizar esses rastreamentos de agentes diretamente no Elasticsearch. Melhor ainda, esses rastreamentos são baseados no protocolo OpenTelemetry, garantindo que sejam padronizados e portáteis para integração com a plataforma de observabilidade de sua escolha.</p><p>Esse nível de detalhamento é a base para um verdadeiro ciclo de melhoria contínua. Ele permite que você crie um conjunto abrangente de testes, depure falhas, identifique modos de falha para evitar regressões e capture padrões de sucesso para otimizar o desempenho. Em última análise, essa abordagem orientada por dados é a chave para transformar um protótipo promissor em um sistema de IA confiável e pronto para produção.</p><h3>Segurança</h3><p>À medida que os agentes e as ferramentas se tornam mais capazes, a segurança deixa de ser opcional e passa a ser fundamental. Expor APIs, automatizar tarefas e fluxos de trabalho exige que os sistemas empresariais sejam confiáveis. Principalmente à medida que os agentes começam a automatizar mais fluxos de trabalho, a capacidade de protegê-los e garantir que atendam aos requisitos da empresa torna-se essencial.</p><p>Todas as funcionalidades acima herdam os controles já disponíveis no Elastic atualmente, incluindo <a href="https://www.elastic.co/search-labs/blog/rag-and-rbac-integration">o controle de acesso baseado em funções (RBAC)</a> para chamadas de API e o gerenciamento de chaves de API. Também estamos estendendo os mesmos controles a novos protocolos como o MCP. Isso significa suporte para padrões como o OAuth, bem como a capacidade de integrar mecanismos de autenticação personalizados.</p><p>Nosso objetivo é oferecer a flexibilidade necessária para que você experimente agentes e ferramentas, mantendo o nível de segurança, conformidade e governança que sua organização exige.</p><h2>O que vem a seguir</h2><p>Não estamos apenas adicionando funcionalidades; estamos expandindo o Elasticsearch para engenharia de contexto agente. Planejamos desenvolver nosso trabalho daqui para frente com base nesses princípios:</p><p>1. Compromisso com o código aberto e os padrões</p><p>Nosso compromisso com o código aberto e os padrões abertos garante que essas funcionalidades permaneçam interoperáveis com estruturas de agentes externas. Você sempre poderá conectar, estender e compor agentes em todo o seu ecossistema, mantendo seus dados e fluxos de trabalho sob seu controle.</p><p>2. Valor do Contexto</p><p>O contexto é o maior trunfo de um agente de IA. Gerenciar o contexto enquanto os agentes realizam buscas e operações de fluxo de trabalho pode ser uma tarefa desafiadora. Estamos aproveitando os principais pontos fortes da Elastic para resolver a engenharia de contexto, garantindo que as informações mais relevantes estejam sempre disponíveis para o seu agente.</p><p>3. Foque em fluxos de dados agéticos</p><p>No futuro, os agentes serão uma fonte de dados cada vez maior, incluindo a saída dos agentes (documentos gerados, relatórios, visualizações) e o rastro de execução dos agentes (seu raciocínio, chamadas de ferramentas, memória/contexto). A Elastic é ideal para lidar com esse tipo de dados, e estamos trabalhando em pesquisas sobre como realizar análises, avaliações e melhorias automatizadas usando esses dados.</p><p>4. Segurança e proteção por design</p><p>Os agentes de IA introduzem um conjunto totalmente novo de desafios em termos de segurança e proteção. A Elastic sempre foi líder em soluções seguras e continuamos a incorporar proteções de nível empresarial, controles de acesso e princípios de "confiança zero".</p><p>5. Integrado à plataforma</p><p>Os recursos para criar agentes de IA estão integrados na plataforma Elasticsearch. Isso significa que funcionalidades de nível de plataforma, como rastreamento, avaliação, visualização e análise, são todas aplicáveis aos agentes. Deseja desenvolver painéis de controle com base nas execuções dos agentes? Isso já está integrado. Deseja avaliar o desempenho do agente de IA usando análise de sentimentos? A plataforma permite isso. Isso possibilita a criação de um ciclo de vida completo em torno de suas experiências com IA.</p><p>O objetivo da Elastic é fornecer interfaces para que você possa criar IA conversacional e fluxos de trabalho automatizados que sejam totalmente integrados, extensíveis e baseados em seus dados. Mais detalhes técnicos e informações sobre o progresso serão compartilhados em breve.</p><p>O Construtor de Agentes já está disponível em versão prévia privada. <a href="https://www.elastic.co/contact?pg=global&amp;plcmt=nav&amp;cta=205352">Entre em contato conosco</a> para solicitar acesso. Tem perguntas ou comentários? Conecte-se com nossa comunidade de desenvolvedores em nosso <a href="https://elasticstack.slack.com/archives/C09GRHEQ4AG"><strong>espaço de trabalho no Slack</strong></a> ou em nosso <a href="https://discuss.elastic.co/c/search/84"><strong>fórum de discussão</strong></a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Na Elastic]]></category>
    <dc:creator><![CDATA[Anish Mathur,Dana Juratoni]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16a3d8736bf086e0/6a17e1616864a45410b686c7/71876470119e02a45bcbfcbf27a3e110328bbd14-1020x654.png" length="0" type="image/png"/>
    <pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Construindo um assistente RAG ativo com JavaScript, Mastra e Elasticsearch.]]></title>
    <description><![CDATA[Aprenda a criar agentes de IA no ecossistema JavaScript.]]></description>
    <content:encoded><![CDATA[<p>Essa ideia me ocorreu durante uma acirrada e decisiva liga de basquete de fantasia. Eu me perguntei: <em>será que eu conseguiria criar um agente de IA que me ajudasse a dominar meus confrontos semanais? Com certeza!</em></p><p>Neste artigo, exploraremos como construir um assistente RAG agente usando <a href="https://mastra.ai/en/docs">o Mastra</a> e um aplicativo web JavaScript leve para interagir com ele. Ao conectar este agente ao Elasticsearch, damos a ele acesso a dados estruturados dos jogadores e a capacidade de executar agregações estatísticas em tempo real, para fornecer recomendações baseadas em estatísticas dos jogadores. Acesse o <a href="https://github.com/jdarmada/nba-ai-assistant-js.git">repositório</a> do GitHub para acompanhar; o <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/README.md">arquivo README</a> fornece instruções sobre como clonar e executar o aplicativo por conta própria. </p><p>Eis como deverá ficar quando tudo estiver montado:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt63ea3e7a09306fbf/6a17f1d97f6f150e22c09c50/1c73bd1dc1b5fe54f025c7a2b7c322acc9122f3a-1999x1393.png" alt="" /><p>Nota: Este post do blog complementa o artigo “<a href="https://www.elastic.co/search-labs/blog/ai-agents-ai-sdk-elasticsearch">Criando agentes de IA com o SDK de IA e o Elastic</a>”. Se você é iniciante no estudo de agentes de IA em geral e em suas possíveis aplicações, comece por aí.
</p><h2><strong>Visão geral da arquitetura</strong></h2><p>No núcleo do sistema está um modelo de linguagem abrangente (LLM, na sigla em inglês), que atua como o motor de raciocínio do agente (o cérebro). Ele interpreta a entrada do usuário, decide quais ferramentas utilizar e orquestra as etapas necessárias para gerar uma resposta relevante.</p><p>O próprio agente é estruturado pelo Mastra, um framework de agentes no ecossistema JavaScript. O Mastra integra o LLM com infraestrutura de backend, expõe-no como um endpoint de API e fornece uma interface para definir ferramentas, prompts do sistema e comportamento do agente.</p><p>Na interface, usamos <a href="https://vite.dev/guide/">o Vite</a> para criar rapidamente um aplicativo web React que fornece uma interface de chat para enviar perguntas ao agente e receber suas respostas.</p><p>Por fim, temos o Elasticsearch, que armazena estatísticas de jogadores e dados de confrontos que o agente pode consultar e agregar.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte13f09493f217047/6a17f1db1d1b83178d93e546/443bdc00d84ed1dd49e9f9e431e86ca4b0892563-1999x977.png" alt="" /><h2><strong>Histórico</strong></h2><p>Vamos revisar alguns conceitos fundamentais:</p><h3><strong>O que é RAG agentivo?</strong></h3><p>Os agentes de IA podem interagir com outros sistemas, operar de forma independente e executar ações com base em parâmetros definidos por eles. O Agentic RAG combina a autonomia de um agente de IA com os princípios da geração aumentada por recuperação, permitindo que um LLM escolha quais ferramentas utilizar e quais dados usar como contexto para gerar uma resposta. Leia mais sobre a RAG <a href="https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag">aqui</a>.</p><h3><strong>Ao escolher uma estrutura, por que ir além do AI-SDK?</strong></h3><p>Existem muitas estruturas de agentes de IA disponíveis e você provavelmente já ouviu falar das mais populares, como <a href="https://www.elastic.co/search-labs/blog/using-crewai-with-elasticsearch">CrewAI</a>, <a href="https://www.elastic.co/search-labs/blog/using-autogen-with-elasticsearch">AutoGen</a> e <a href="https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch">LangGraph</a>. A maioria dessas estruturas compartilha um conjunto comum de funcionalidades, incluindo suporte para diferentes modelos, uso de ferramentas e gerenciamento de memória.</p><p>Segue abaixo uma <a href="https://docs.google.com/spreadsheets/d/1B37VxTBuGLeTSPVWtz7UMsCdtXrqV5hCjWkbHN8tfAo/edit?gid=0#gid=0">tabela comparativa</a> de frameworks elaborada por Harrison Chase (CEO da LangChain).</p><p>O que despertou meu interesse no Mastra foi o fato de ser um framework que prioriza o JavaScript, criado para que desenvolvedores full-stack possam integrar agentes facilmente em seu ecossistema. O SDK de IA da Vercel também faz a maior parte disso, mas o grande diferencial do Mastra é quando seus projetos incluem fluxos de trabalho de agentes mais complexos. O Mastra aprimora os padrões básicos definidos pelo AI-SDK e, neste projeto, usaremos os dois em conjunto.</p><h3><strong>Considerações sobre estruturas e escolha de modelos</strong></h3><p>Embora essas estruturas possam ajudá-lo a criar agentes de IA rapidamente, existem algumas desvantagens a serem consideradas. Por exemplo, ao usar qualquer outra estrutura fora dos agentes de IA ou de qualquer camada de abstração em geral, você perde um pouco do controle. Se o LLM não usar as ferramentas corretamente ou fizer algo que você não deseja, a abstração dificulta a depuração. Ainda assim, na minha opinião, essa troca vale a pena pela facilidade e rapidez que se obtém ao construir, especialmente porque essas estruturas estão ganhando força e sendo constantemente aprimoradas.</p><p>Novamente, essas estruturas são agnósticas em relação ao modelo, o que significa que você pode usar diferentes modelos sem problemas. Lembre-se de que os modelos variam nos conjuntos de dados em que foram treinados e, consequentemente, variam nas respostas que fornecem. Alguns modelos sequer suportam a chamada de ferramentas. Portanto, é possível alternar e testar diferentes modelos para ver qual oferece as melhores respostas, mas lembre-se de que provavelmente você terá que reescrever o prompt do sistema para cada um deles. Por exemplo, usando Llama3.3 Em comparação com o GPT-40, é necessário muito mais estímulo e instruções específicas para obter a resposta desejada.</p><h3><strong>Basquete de fantasia da NBA</strong></h3><p>O basquete de fantasia envolve a criação de uma liga com um grupo de amigos (atenção: dependendo do nível de competitividade do grupo, isso pode afetar o status das suas amizades), geralmente com algum dinheiro em jogo. Cada um de vocês monta uma equipe de 10 jogadores para competir contra a equipe de 10 jogadores de um amigo, alternando semanalmente. Os pontos que contribuem para a sua pontuação geral são definidos pelo desempenho de cada um dos seus jogadores contra os adversários em uma determinada semana.</p><p>Se um jogador da sua equipe se lesionar, for suspenso, etc., existe uma lista de jogadores disponíveis no mercado para adicionar à sua equipe. É aqui que entra em jogo grande parte da estratégia complexa nos esportes de fantasia, porque você tem um número limitado de jogadores para escolher e todos estão constantemente em busca do melhor jogador.</p><p>É aqui que nosso assistente de IA da NBA brilhará, especialmente em situações em que você precisa decidir rapidamente qual jogador escolher. Em vez de ter que pesquisar manualmente o desempenho de um jogador contra um adversário específico, o assistente pode encontrar esses dados rapidamente e comparar as médias para fornecer uma recomendação precisa.</p><p>Agora que você já conhece alguns conceitos básicos sobre RAG agentivo e basquete fantasy da NBA, vamos ver como funciona na prática.</p><h2><strong>Construindo o projeto</strong></h2><p>Se você ficar preso em algum ponto ou não quiser construir tudo do zero, consulte o <a href="https://github.com/jdarmada/nba-ai-assistant-js.git">repositório</a>.</p><h3><strong>O que abordaremos</strong></h3><ol><li><p><strong>Estruturando o projeto:</strong></p><ol><li><p><strong>Backend (Mastra):</strong> Use o comando `npx create mastra@latest` para criar a estrutura do backend e definir a lógica do agente.</p></li><li><p><strong>Frontend (Vite + React):</strong> Use o comando `npm create vite@latest` para criar a interface de chat do frontend para interação com o agente.</p></li></ol></li><li><p><strong>Configurando variáveis de ambiente</strong></p><ol><li><p>Instale o dotenv para gerenciar variáveis de ambiente.</p></li><li><p>Crie um arquivo .env arquive e forneça as variáveis necessárias.</p></li></ol></li><li><p><strong>Configurando o Elasticsearch</strong></p><ol><li><p>Crie um cluster Elasticsearch (localmente ou na nuvem).</p></li><li><p>Instale o cliente oficial do Elasticsearch.</p></li><li><p>Garanta que as variáveis de ambiente estejam acessíveis.</p></li><li><p>Estabelecer conexão com o cliente.</p></li></ol></li><li><p><strong>Ingestão em massa de dados da NBA no Elasticsearch</strong></p><ol><li><p>Crie um índice com os mapeamentos apropriados para habilitar agregações.</p></li><li><p>Importar em massa estatísticas de jogo de jogadores de um arquivo CSV para um índice do Elasticsearch.</p></li></ol></li><li><p><strong>Definir agregações do Elasticsearch</strong></p><ol><li><p>Consulta para calcular as médias históricas contra um adversário específico.</p></li><li><p>Consulta para calcular as médias da temporada contra um adversário específico.</p></li></ol></li><li><p><strong>Arquivo utilitário de comparação de jogadores</strong></p><ol><li><p>Consolida funções auxiliares e agregações do Elasticsearch.</p></li></ol></li><li><p><strong>Construindo o agente</strong></p><ol><li><p>Adicione a definição do agente e o prompt do sistema.</p></li><li><p>Instale o Zod e defina as ferramentas.</p></li><li><p>Adicionar configuração de middleware para lidar com CORS.</p></li></ol></li><li><p><strong>Integrando o frontend</strong></p><ol><li><p>Utilizando o useChat do AI-SDK para interagir com o agente.</p></li><li><p>Crie a interface do usuário para manter conversas formatadas adequadamente.</p></li></ol></li><li><p><strong>Executando o aplicativo</strong></p><ol><li><p>Inicie tanto o backend (servidor Mastra) quanto o frontend (aplicativo React).</p></li><li><p>Exemplos de consultas e uso.</p></li></ol></li><li><p><strong>O que vem a seguir: tornar o agente mais inteligente.</strong></p><ol><li><p>Adicionando recursos de busca semântica para possibilitar recomendações mais relevantes.</p></li><li><p>Habilite consultas dinâmicas movendo a lógica de busca para o servidor Elasticsearch MCP (Model Context Protocol).</p></li></ol></li></ol><h3><strong>Pré-requisitos</strong></h3><ul><li><p><strong>Node.js e npm</strong>: Tanto o backend quanto o frontend são executados em Node. Certifique-se de ter o Node 18+ e o npm v9+ instalados (que já vêm incluídos no Node 18+).</p></li><li><p><strong>Cluster Elasticsearch:</strong> Um cluster Elasticsearch ativo, seja localmente ou na nuvem.</p></li><li><p><strong>Chave da API da OpenAI</strong>: Gere uma na página de chaves da API no <a href="https://platform.openai.com/api-keys">portal de desenvolvedores da OpenAI</a>.</p></li></ul><p></p><h3><strong>Estrutura do projeto</strong></h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt749baa120552e4ab/6a17f1dd1d1b83bfe993e54a/1c0bde11ad0eead523a95e03b9b905aa776e3fd1-1420x934.png" alt="" /><h4><strong>Etapa 1: Estruturando o projeto</strong></h4><ol><li><p>Primeiro, crie o diretório nba-ai-assistant-js e navegue até ele usando: </p></li></ol>mkdir nba-ai-assistant-js &amp;&amp; cd nba-ai-assistant-js<p><strong>Backend:</strong></p><ol><li><p>Utilize a ferramenta de criação do Mastra com o comando: </p></li></ol>npx create-mastra@latest<p>2. Você deverá receber algumas mensagens no seu terminal. Para a primeira, vamos nomear o backend do projeto:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt65abf68fe588e968/6a17f1de63baff2814741d5b/de2725031ed6837db99a979efcdd0ece1e197dbb-608x84.png" alt="" /><p>3. Em seguida, manteremos a estrutura padrão para armazenar os arquivos Mastra, então insira <code>src/</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89bd829fcf0ae6b9/6a17f1e04b055dd30e432302/88919d9ff1852126395e1fcd700ecb1b59aac63c-866x116.png" alt="" /><p>4. Em seguida, escolheremos a OpenAI como nosso provedor padrão de LLM.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd167cc77a40b9a8/6a17f1e11480099e29b48863/2328761e769f3ded134e5a21e8a0bf8f41e88f68-404x210.png" alt="" /><p>5. Por fim, será solicitada a sua chave de API da OpenAI. Por agora, vamos escolher a opção de ignorar e fornecer isso mais tarde em um arquivo<code> .env</code> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt12654151ed495370/6a17f1e22f4a5c0f84fa89f9/0662de9bd28758e377e4c63df8d08b479068ce63-444x120.png" alt="" /><p><strong>Front-end:</strong></p><ol><li><p>Volte ao diretório raiz e execute a <a href="https://vite.dev/guide/">ferramenta de criação do Vite</a> usando este comando: <code>npm create vite@latest frontend -- --template react</code></p></li></ol><p>Isso deverá criar um aplicativo React leve chamado <code>frontend</code> com um modelo específico para React.</p><p>Se tudo correr bem, dentro do diretório do seu projeto, você deverá ver um diretório backend que contém o código Mastra e um diretório <code>frontend</code> com seu aplicativo React.</p><p></p><h4><strong>Etapa 2: Configurando as variáveis de ambiente</strong></h4><ol><li><p>Para gerenciar chaves sensíveis, usaremos o pacote <code>dotenv</code> para carregar nossas variáveis de ambiente do arquivo .env. arquivo. Navegue até o diretório backend e instale <code>dotenv</code>:</p></li></ol>cd backend
npm install dotenv --save<p>2. No diretório backend, um arquivo example.env é fornecido com as variáveis apropriadas para preenchimento. Se você criar o seu próprio, certifique-se de incluir as seguintes variáveis:</p># OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key_here

# Elasticsearch Configuration
ELASTIC_ENDPOINT=your_elasticsearch_endpoint_here
ELASTIC_API_KEY=your_elasticsearch_api_key_here
<p></p><p>Nota: Certifique-se de que este arquivo seja excluído do seu controle de versão adicionando <code>.env</code> a <code>.gitignore</code>.</p><h4><strong>Etapa 3: Configurando o Elasticsearch</strong></h4><p>Primeiro, você precisa de um cluster Elasticsearch ativo. Existem duas opções:</p><ul><li><p><strong>Opção A: Usar o Elasticsearch Cloud</strong></p><ul><li><p>Inscreva-se no <a href="https://cloud.elastic.co/registration">Elastic Cloud.</a></p></li><li><p>Criar uma nova implantação</p></li><li><p>Obtenha o URL do seu endpoint e a chave da API (codificada).</p></li></ul></li><li><p><strong>Opção B: Executar o Elasticsearch localmente</strong></p><ul><li><p>Instale e execute o Elasticsearch localmente.</p></li><li><p>Use http://localhost:9200 como seu endpoint.</p></li><li><p>Gere uma chave de API</p></li></ul></li></ul><p></p><p><strong>Instalando o cliente Elasticsearch no servidor:</strong></p><ol><li><p>Primeiro, instale o cliente oficial do Elasticsearch no diretório do seu backend:</p></li></ol>npm install @elastic/elasticsearch<p>2. Em seguida, crie um diretório chamado lib para armazenar funções reutilizáveis e navegue até ele:</p>mkdir lib &amp;&amp; cd lib<p>3. Dentro da pasta, crie um novo arquivo chamado <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/elasticClient.js">elasticClient.js</a>. Este arquivo inicializará o cliente Elasticsearch e o disponibilizará para uso em todo o seu projeto.</p><p>4. Como estamos usando módulos ECMAScript (ESM), os nomes de arquivo __dirname and __não estão disponíveis. Para garantir que suas variáveis de ambiente sejam carregadas corretamente a partir do arquivo .env No arquivo localizado na pasta backend, adicione esta configuração ao início do seu arquivo:</p>import { config } from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { Client } from '@elastic/elasticsearch';

// Grab current directory and load .env from backend folder
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const envPath = join(__dirname, '../.env');

// Load environment variables from the correct path
config({ path: envPath });<p>5. Agora, inicialize o cliente Elasticsearch usando suas variáveis de ambiente e verifique a conexão:</p>//Elastic client Initialization, make sure environment variables are being loaded in correctly
const config= {
    node: `${process.env.ELASTIC_ENDPOINT}`,
    auth: {
        apiKey: `${process.env.ELASTIC_API_KEY}`,
    },
};

export const elasticClient = new Client(config);

//Check if the client is connected
async function checkConnection() { 
    try {
        const info = await elasticClient.info();
        console.log('Elasticsearch is connected:', info);
    } catch (error) {
        console.error('Elasticsearch connection error:', error);
    }
}

checkConnection();
<p>Agora, podemos importar essa instância de cliente para qualquer arquivo que precise interagir com o seu cluster Elasticsearch.</p><p></p><h4><strong>Etapa 4: Ingestão em massa de dados da NBA no Elasticsearch</strong></h4><p><strong>Conjunto de dados:</strong></p><p>Para este projeto, utilizaremos como referência os conjuntos de dados disponíveis no diretório <a href="https://github.com/jdarmada/nba-ai-assistant-js/tree/main/backend">backend/data</a> do repositório. Nosso assistente da NBA usará esses dados como base de conhecimento para realizar comparações estatísticas e gerar recomendações.</p><ul><li><p><a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/data/sample_nba_data.csv">sample_player_game_stats.csv</a> - Estatísticas de jogo de jogadores (por exemplo, pontos, rebotes, roubos de bola, etc., por jogo, por jogador, ao longo de toda a sua carreira na NBA). Usaremos esse conjunto de dados para realizar agregações. (Observação: estes são dados fictícios, pré-gerados para fins de demonstração e não provenientes de fontes oficiais da NBA.)</p></li><li><p><a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/data/playerAndTeamInfo.js">playerAndTeamInfo.js</a> - Substitui os metadados de jogadores e equipes que normalmente seriam fornecidos por uma chamada de API, permitindo que o agente associe nomes de jogadores e equipes a IDs. Como estamos usando dados de exemplo, não queremos a sobrecarga de buscar dados em uma API externa, então definimos alguns valores fixos que o agente pode referenciar.</p></li></ul><p></p><p><strong>Implementação:</strong></p><ol><li><p>No diretório <code>backend/lib</code> , crie um arquivo chamado <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/playerDataIngestion.js">playerDataIngestion.js</a>.</p></li><li><p>Configure as importações, resolva o caminho do arquivo CSV e configure a análise sintática. Novamente, como estamos usando ESM, precisamos reconstruir <code>__dirname</code> para resolver o caminho para o CSV de amostra. Além disso, importaremos <a href="http://node.js/">o Node.js.</a> módulos integrados, <code>fs</code> e <code>readline</code>, para analisar o arquivo CSV fornecido linha por linha.</p></li></ol>import fs from 'fs';
import readline from 'readline';
import path from 'path';
import { fileURLToPath } from 'url';
import { elasticClient } from './elasticClient.js';

const indexName = 'sample-nba-player-data'; //Replace with your preferred index name

//Since we are using ES modules __dirname and __filename don't exist, so this is a workaround that allows us to use the absolute file path for our sample data.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const filePath = path.resolve(__dirname, '../data/sample_nba_data.csv');<p>Isso prepara você para ler e analisar o CSV de forma eficiente quando chegarmos à etapa de ingestão em massa.</p><p>3. Crie um índice com o mapeamento apropriado. Embora o Elasticsearch possa inferir automaticamente os tipos de campo com <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dynamic">mapeamento dinâmico</a>, queremos ser explícitos aqui para que cada estatística seja tratada como um campo numérico. Isso é importante porque usaremos esses campos para agregações mais tarde. Também queremos usar o tipo <code>float </code>para estatísticas como pontos, rebotes, etc., para garantir que incluamos valores decimais. Finalmente, queremos adicionar a propriedade de mapeamento <code>dynamic: 'strict'</code> para que o Elasticsearch não mapeie dinamicamente campos não reconhecidos. 
</p>// Function to create an index with mappings
async function createIndex() {
    try {
        // Check if the index already exists
        const exists = await elasticClient.indices.exists({ index: indexName });

        if (exists) {
            console.log(`Index "${indexName}" already exists, deleting it now.`);
            await elasticClient.indices.delete({ index: indexName });
            console.log(`Deleted index "${indexName}".`);
        }
        // Create the index with mappings
        const response = await elasticClient.indices.create({
            index: indexName,
            body: {
                mappings: {
                    dynamic: 'strict', // Prevent dynamic mapping
                    properties: {
                        game_id: { type: 'integer' },
                        game_date: { type: 'date' },
                        player_id: { type: 'integer' },
                        player_full_name: { type: 'text' },
                        player_team_id: { type: 'integer' },
                        player_team_name: { type: 'text' },
                        home_team: { type: 'boolean' },
                        opponent_team_id: { type: 'integer' },
                        opponent_team_name: { type: 'text' },
                        points: { type: 'float' },
                        rebounds: { type: 'float' },
                        assists: { type: 'float' },
                        steals: { type: 'float' },
                        blocks: { type: 'float' },
                        fg_percentage: { type: 'float' },
                        minutes_played: { type: 'float' },
                    },
                },
            },
        });

        console.log('Index created:', response);
        return true;
    } catch (error) {
        console.error('Error creating index:', error);
        return false;
    }
}
<p>4. Adicione a função para ingerir em massa os dados CSV no seu índice Elasticsearch. Dentro do bloco de código, omitimos a linha de cabeçalho. Em seguida, separe cada item da linha por vírgula e insira-os no objeto do documento. Esta etapa também os limpa e garante que sejam do tipo correto. Em seguida, inserimos os documentos na matriz bulkBody juntamente com as informações do índice, que servirão como carga útil para a ingestão em massa no Elasticsearch.</p>async function bulkIngestCsv(filePath) {
    const readStream = fs.createReadStream(filePath);
    const rl = readline.createInterface({
        input: readStream,
        crlfDelay: Infinity,
    });

    const bulkBody = [];
    let lineNum = 0;

    //Skip the header line
    let headerLine = true;
    for await (const line of rl) {
        if (headerLine) {
            headerLine = false;
            continue;
        }
        lineNum++;

        // Split the line by comma and remove whitespace
        const [
            game_id,
            game_date,
            player_id,
            player_full_name,
            player_team_id,
            player_team_name,
            home_team,
            opponent_team_id,
            opponent_team_name,
            points,
            rebounds,
            assists,
            steals,
            blocks,
            fg_percentage,
            minutes_played,
        ] = line.split(',');

        // Create a document object
        const document = {
            game_id: parseInt(game_id),
            game_date: game_date.trim(),
            player_id: parseInt(player_id),
            player_full_name: player_full_name.trim(),
            player_team_id: parseInt(player_team_id),
            player_team_name: player_team_name.trim(),
            home_team: home_team.trim() === 'True', // Converts True/False into a boolean
            opponent_team_id: parseInt(opponent_team_id),
            opponent_team_name: opponent_team_name.trim(),
            points: parseFloat(points),
            rebounds: parseFloat(rebounds),
            assists: parseFloat(assists),
            steals: parseFloat(steals),
            blocks: parseFloat(blocks),
            fg_percentage: parseFloat(fg_percentage),
            minutes_played: parseFloat(minutes_played),
        };

        // Prepare the bulk operation format
        bulkBody.push({ index: { _index: indexName } });
        bulkBody.push(document);
    }

    console.log(`Parsed ${lineNum} lines from CSV`);
<p>5. Então, podemos usar <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-bulk">a API Bulk</a> do Elasticsearch com <code>elasticClient.bulk()</code> para ingerir vários documentos em uma única solicitação. O tratamento de erros abaixo está estruturado para fornecer uma contagem de quantos documentos não foram ingeridos e quantos foram ingeridos com sucesso.</p>try {
        // Perform the bulk request
        const response = await elasticClient.bulk({ body: bulkBody });

        if (response.errors) {
            console.log('Bulk Ingestion had some hiccups:');

            // Count successful vs failed operations
            let successCount = 0;
            let errorCount = 0;
            const errorDetails = [];

            response.items.forEach((item, index) =&gt; {
                const operation = item.index || item.create || item.update || item.delete;
                if (operation.error) {
                    errorCount++;
                    errorDetails.push({
                        document: index + 1,
                        error: operation.error,
                    });
                } else {
                    successCount++;
                }
            });

            console.log(`Successfully indexed: ${successCount} documents`);
            console.log(`Failed to index: ${errorCount} documents, here are the details`, errorDetails);

        } else {
            console.log(`Bulk Ingestion fully successful!`);
        }

    } catch (error) {
        console.error('Error performing bulk ingestion:', error);
    }
}
<p>6. Execute a função <code>main()</code> abaixo para executar sequencialmente as funções <code>createIndex()</code> e <code>bulkIngestCsv()</code> .</p>// Run this function
async function main() {
    const result = await createIndex();
    if (!result) {
        console.error('Index setup failed. Aborting.');
        return;
    }

    await bulkIngestCsv(filePath);
    console.log('Bulk ingestion completed!');
}

main();
<p>Se você vir um registro no console indicando que a ingestão em massa foi bem-sucedida, faça uma verificação rápida no seu índice do Elasticsearch para confirmar se os documentos foram realmente ingeridos com sucesso.</p><h4><strong>Etapa 5: Definindo e consolidando as agregações do Elasticsearch</strong></h4><p>Essas serão as principais funções que serão utilizadas quando definirmos as ferramentas para o Agente de IA, a fim de comparar as estatísticas dos jogadores entre si.</p><p>1. Navegue até o diretório <code>backend/lib</code> e crie um arquivo chamado <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/elasticAggs.js">elasticAggs.js</a>.</p><p>2. Adicione a consulta abaixo para calcular as médias históricas de um jogador contra um adversário específico. Esta consulta usa um <a href="https://www.elastic.co/search-labs/tutorials/search-tutorial/full-text-search/filters">filtro</a> <code>bool</code> com 2 condições: uma que corresponde <code>player_id</code> e outra que corresponde a <code>opponent_team_id</code>, para recuperar apenas os jogos relevantes. Não precisamos retornar nenhum documento, só nos interessam as agregações, então definimos <code>size:0</code>. No bloco <code>aggs</code> , executamos várias <a href="https://www.elastic.co/docs/explore-analyze/query-filter/aggregations">agregações</a> de métricas em paralelo em campos como <code>points, rebounds, assists, steals, blocks</code> e <code>fg_percentage</code> para calcular seus valores médios. Os cálculos dos LLMs podem ser inconsistentes, e essa solução transfere esse processo para o Elasticsearch, garantindo que nosso assistente de IA da NBA tenha acesso a dados precisos.</p>export async function getHistoricalAveragesAgainstOpponent(player_id, opponent_team_id) {
    try {
        //Query for Historical Averages
        const historicalQuery = await elasticClient.search({
            index: 'sample-nba-player-data', 
            size: 0,
            query: {
                bool: {
                    must: [
                        {
                            term: {
                                player_id: {
                                    value: player_id,
                                },
                            },
                        },
                        {
                            term: {
                                opponent_team_id: {
                                    value: opponent_team_id,
                                },
                            },
                        },
                    ],
                },
            },
            aggs: {
                avg_points: { avg: { field: 'points' } },
                avg_rebounds: { avg: { field: 'rebounds' } },
                avg_assists: { avg: { field: 'assists' } },
                avg_steals: { avg: { field: 'steals' } },
                avg_blocks: { avg: { field: 'blocks' } },
             avg_fg_percentage: { avg: { field: 'fg_percentage' } },
            },
        });

        return {
            points: historicalQuery.aggregations.avg_points.value || 0,
            rebounds: historicalQuery.aggregations.avg_rebounds.value || 0,
            assists: historicalQuery.aggregations.avg_assists.value || 0,
            steals: historicalQuery.aggregations.avg_steals.value || 0,
            blocks: historicalQuery.aggregations.avg_blocks.value || 0,
            fgPercentage: historicalQuery.aggregations.avg_fg_percentage.value || 0,
        };
    } catch (error) {
        console.error('Query error from getHistoricalAveragesAgainstOpponent function:', error);
        return { error: 'Queries failed in getting historical averages against opponent.' };
    }
}
<p>3. Para calcular as médias da temporada de um jogador contra um adversário específico, usaremos praticamente a mesma consulta que a consulta histórica. A única diferença nesta consulta é que o filtro <code>bool</code> tem uma condição adicional para <code>game_date</code>. O campo <code>game_date</code> tem que estar dentro do intervalo da temporada atual da NBA. Neste caso, o intervalo está entre <code>2024-10-01</code> e <code>2025-06-30</code>. Essa condição adicional abaixo garante que as agregações subsequentes isolarão apenas os jogos desta temporada.
</p>        {
                            range: {
                    //Range for this season, change to match current season
                                game_date: {
                                    gte: '2024-10-01',
                                    lte: '2025-06-30',
                                },
                            },
<h4><strong>Etapa 6: Ferramenta de comparação de jogadores</strong></h4><p>Para manter nosso código modular e de fácil manutenção, criaremos um arquivo utilitário que consolida funções auxiliares de metadados e agregações do Elasticsearch. Isso alimentará a principal ferramenta usada pelo agente. Mais sobre isso adiante:</p><p>1. Crie um novo arquivo <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/comparePlayers.js">comparePlayers.js</a> no diretório <code>backend/lib</code> .</p><p>2. Adicione a função abaixo para consolidar os auxiliares de metadados e a lógica de agregação do Elasticsearch em uma única função que alimenta a ferramenta principal usada pelo agente.
</p>import { playersByName } from '../data/playerAndTeamInfo.js';
import { teamsByName } from '../data/playerAndTeamInfo.js';
import { upcomingMatchups } from '../data/playerAndTeamInfo.js';
import { getHistoricalAveragesAgainstOpponent } from './elasticAggs.js';
import { getSeasonAveragesAgainstOpponent } from './elasticAggs.js';

//Simple helper functions to simulate API calls for player and team metadata. These reference the hardcoded values from playerAndTeamInfo.js in the data directory
export function getPlayerInfo(playerFullName) {
    return playersByName[playerFullName];
}

export function getTeamID(teamFullName) {
    return teamsByName[teamFullName];
}

export function getUpcomingMatchups(teamId) {
    return upcomingMatchups[teamId];
}

//Main function used by the 'playerComparisonTool' agent tool
export async function comparePlayersForNextMatchup(player1Name, player2Name) {
    //Get Player Info
    const player1Info = getPlayerInfo(player1Name);
    const player2Info = getPlayerInfo(player2Name);

    //Get upcoming matchups
    const player1NextGame = getUpcomingMatchups(player1Info.team_id)[0];
    const player2NextGame = getUpcomingMatchups(player2Info.team_id)[0];

    //Get season and historical averages against next opponent for player 1
    const player1SeasonAverages = await getSeasonAveragesAgainstOpponent(
        player1Info.player_id,
        player1NextGame.opponent_team_id
    );
    const player1HistoricalAverages = await getHistoricalAveragesAgainstOpponent(
        player1Info.player_id,
        player1NextGame.opponent_team_id
    );

    //Get season and historical averages against next opponent for player 2
    const player2SeasonAverages = await getSeasonAveragesAgainstOpponent(
        player2Info.player_id,
        player2NextGame.opponent_team_id
    );
    const player2HistoricalAverages = await getHistoricalAveragesAgainstOpponent(
        player2Info.player_id,
        player2NextGame.opponent_team_id
    );

    const player1 = {
        name: player1Name,
        playerId: player1Info.player_id,
        teamId: player1Info.team_id,
        nextOpponent: {
            teamId: player1NextGame.opponent_team_id,
            teamName: player1NextGame.opponent_team_name,
            home: player1NextGame.home,
        },
        stats: {
            seasonAverages: player1SeasonAverages,
            historicalAverages: player1HistoricalAverages,
        },
    };

    const player2 = {
        name: player2Name,
        playerId: player2Info.player_id,
        teamId: player2Info.team_id,
        nextOpponent: {
            teamId: player2NextGame.opponent_team_id,
            teamName: player2NextGame.opponent_team_name,
            home: player2NextGame.home,
        },
        stats: {
            seasonAverages: player2SeasonAverages,
            historicalAverages: player2HistoricalAverages,
        },
    };

    return [player1, player2];
}
<h4><strong>Etapa 7: Construindo o agente</strong></h4><p>Agora que você criou a estrutura básica do frontend e do backend, importou os dados dos jogos da NBA e estabeleceu uma conexão com o Elasticsearch, podemos começar a juntar todas as peças para construir o agente.</p><p><strong>Definindo o agente</strong></p><p>1. Navegue até o arquivo <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/agents/index.ts">index.ts</a> dentro do diretório <code>backend/src/mastra/agents</code> e adicione a definição do agente. Você pode especificar campos como:</p><ul><li><p><strong>Nome:</strong> Dê ao seu agente um nome que será usado como referência quando ele for chamado na interface.</p></li><li><p><strong>Instruções/mensagem do sistema: </strong>Uma mensagem do sistema fornece ao LLM o contexto inicial e as regras a seguir durante a interação. É semelhante à mensagem que os usuários enviam pelo chat, mas esta é exibida antes de qualquer interação do usuário. Novamente, isso irá variar dependendo do modelo que você escolher.</p></li><li><p><strong>Modelo:</strong> Qual modelo de aprendizagem de linguagem (LLM) usar (o Mastra suporta modelos OpenAI, antrópicos, locais, etc.).</p></li><li><p><strong>Ferramentas:</strong> Uma lista de funções de ferramentas que o agente pode chamar.</p></li><li><p><strong>Memória:</strong> (Opcional) se quisermos que o agente se lembre do histórico da conversa, etc. Para simplificar, podemos começar sem memória persistente, embora o Mastra a suporte.</p></li></ul><p></p>import { openai } from '@ai-sdk/openai';
import { Agent } from '@mastra/core/agent';
import { playerComparisonTool } from '../tools';

export const basketballAgent = new Agent({
    name: 'Basketball Agent',
    instructions: `
      You are a NBA Basketball expert.
      Your primary function is to compare two NBA players and recommend which one is the better fantasy pickup.

      Only compare players from the following list:
      - LeBron James
      - Stephen Curry
      - Jayson Tatum
      - Jaylen Brown
      - Nikola Jokic
      - Luka Doncic
      - Kyrie Irving
      - Anthony Davis
      - Kawhi Leonard
      - Russell Westbrook

      Input Handling Rules:
      - If the user asks about a player that is not on this list, respond with the list of available players for comparison.
      - If the user only inputs one player, ask the user to add another player from the list provided.
      - If the user inputs a player with the wrong spelling or capitalizations, infer from the list of available players provided.
      - IMPORTANT: If the user asks a question or asks you to generate a response about anything outside of basketball or the scope of this project, DO NOT answer and affirm you can only talk about basketball.

      Tool Usage:
      - Extract and standardize player names to match the list exactly.
      - Use the playerComparisonTool, passing both names as strings.
      - The tool will return an object with game information, stats, and analysis.

      Format your response using Markdown syntax. Use:

        Example output format:

       
        #### Next Game Info
        - ***LeBron James** vs Warriors, May 24 (Home)  
        - ***Stephen Curry** vs Lakers, May 24 (Away)


        #### Stats Comparison  
        \`\`\`  
        Stat                  LeBron James (vs Warriors)    Stephen Curry (vs Lakers)  
        --------------------  -----------------------------  ----------------------------  
        Historical Points     28.3                          30.3  
        Historical Assists    6.7                           8.7  
        Season Points         28.8                          23.3  
        Season Assists        6.2                           4.7  
        \`\`\`

        #### Fantasy Recommendation  
        Explain which player is the better fantasy pickup and why.
      
    `,
    model: openai('gpt-4o'),
    tools: { playerComparisonTool },
});
<p><strong>
Ferramentas de definição</strong></p><ol><li><p>Navegue até o arquivo <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/tools/index.ts">index.ts</a> dentro do diretório <code>backend/src/mastra/tools</code> .</p></li><li><p>Instale o Zod usando o comando:</p></li></ol>npm install zod<p>3. Adicionar definições de ferramentas. Observe que importamos a função dentro do arquivo <code>comparePlayers.js</code> como a função principal que o agente usará ao chamar esta ferramenta. Usando a função <code>createTool()</code> do Mastra, vamos registrar nosso <code>playerComparisonTool</code>. Os campos incluem:</p><ul><li><p><code>id</code>Esta é uma descrição em linguagem natural para ajudar o agente a entender o que a ferramenta faz.</p></li><li><p><code>input schema</code>Para definir o formato da entrada para a ferramenta, o Mastra utiliza o esquema <a href="https://zod.dev/">Zod</a> , que é uma biblioteca de validação de esquemas TypeScript. Zod ajuda garantindo que o agente insira dados estruturados corretamente e impede que a ferramenta seja executada caso a estrutura de entrada não corresponda.</p></li><li><p><code>description</code>Esta é uma descrição em linguagem natural para ajudar o agente a entender quando ligar e usar a ferramenta.</p></li><li><p><code>execute</code>A lógica que é executada quando a ferramenta é chamada. No nosso caso, estamos usando uma função auxiliar importada para retornar estatísticas de desempenho.</p></li></ul>import { comparePlayersForNextMatchup } from '../../../lib/comparePlayers.js'
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const playerComparisonTool = createTool({
    id: "Compare two NBA players",
    inputSchema: z.object({
        player1:z.string(),
        player2:z.string()
    }),
    description: "Use this tool to compare two players given in the user prompt.",
    execute: async ({ context: { player1, player2 } }) =&gt; {
        return await comparePlayersForNextMatchup(player1, player2);
      },
})<p><strong>Adicionando middleware para lidar com CORS</strong></p><p>Adicione um middleware no servidor Mastra para lidar com <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS">CORS</a>. Dizem que existem três coisas na vida que você não pode evitar: a morte, os impostos e, para desenvolvedores web, o CORS. Em resumo, o Compartilhamento de Recursos de Origem Cruzada (CORS) é um recurso de segurança do navegador que impede que o frontend faça solicitações a um backend executado em um domínio ou porta diferente. Embora executemos tanto o backend quanto o frontend em localhost, eles usam portas diferentes, acionando a política CORS. Precisamos adicionar o middleware especificado na <a href="https://mastra.ai/en/docs/server-db/middleware">documentação do Mastra</a> para que nosso backend permita essas solicitações do frontend.</p><p>1. Navegue até o arquivo <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/index.ts">index.ts</a> dentro do diretório <code>backend/src/mastra</code> e adicione a configuração para CORS:</p><ul><li><p><code>origin: ['http://localhost:5173']</code></p><ul><li><p>Permite solicitações somente deste endereço (endereço padrão do Vite)</p></li></ul></li><li><p><code>allowMethods: ["GET", "POST"]</code></p><ul><li><p>Métodos HTTP permitidos. Na maioria das vezes, será utilizado o método POST.</p></li></ul></li><li><p><code>allowHeaders: ["Content-Type", "Authorization", "x-mastra-client-type, "x-highlight-request", "traceparent"],</code></p><ul><li><p>Essas configurações definem quais cabeçalhos personalizados podem ser usados nas solicitações.</p></li></ul></li></ul><p></p>import { Mastra } from '@mastra/core/mastra';
import { basketballAgent } from './agents';

console.log('Starting Mastra server...');

export const mastra = new Mastra({
  agents: { basketballAgent },
  server:{
    timeout: 10 * 60 * 1000, // 10 minutes
    cors: {
      origin: ['http://localhost:5173'],
      allowMethods: ["GET", "POST"],
      allowHeaders: [
        "Content-Type",
        "Authorization",
        "x-mastra-client-type",
        "x-highlight-request",
        "traceparent",
      ],
      exposeHeaders: ["Content-Length", "X-Requested-With"],
      credentials: false,
    },
  },

});

console.log('Mastra server configured.'); // Log after server configuration
<h4><strong>Etapa 8: Integrando o frontend</strong></h4><p>Este componente React fornece uma interface de chat simples que se conecta ao agente de IA Mastra usando o gancho <a href="https://mastra.ai/en/docs/frameworks/agentic-uis/ai-sdk#using-the-usechat-hook">useChat()</a> de <code>@ai-sdk/react</code>. Também usaremos esse recurso para exibir o uso de tokens, chamadas de ferramentas e para renderizar a conversa. No prompt do sistema acima, também pedimos ao agente para exibir a resposta em markdown, então usaremos <code>react-markdown</code> para formatar a resposta corretamente.</p><p></p><p>1. No diretório frontend, instale o pacote @ai-sdk/react para usar o gancho useChat().</p>npm install @ai-sdk/react<p>2. Ainda no mesmo diretório, instale o React Markdown para que possamos formatar corretamente a resposta gerada pelo agente.</p>npm install react-markdown<p>3. Implemente <code>useChat()</code>. Este gancho gerenciará a interação entre seu frontend e o backend do seu agente de IA. Ele gerencia o estado das mensagens, a entrada do usuário, o status e fornece ganchos de ciclo de vida para fins de observabilidade. As opções que passamos incluem:</p><ul><li><p><code>api:</code> Isso define o ponto final do seu agente Mastra AI. A porta padrão é a 4111 e também queremos adicionar a rota que suporta respostas em fluxo contínuo.</p></li><li><p><code>onToolCall</code>Este comando é executado sempre que o agente chama uma ferramenta; estamos usando-o para rastrear quais ferramentas nosso agente está chamando.</p></li><li><p><code>onFinish</code>Esta ação é executada depois que o agente conclui uma resposta completa. Mesmo que tenhamos habilitado o streaming, <code>onFinish</code> ainda será executado após o recebimento da mensagem completa e não após cada parte. Aqui, estamos usando isso para rastrear o uso de nossos tokens. Isso pode ser útil para monitorar e otimizar os custos do LLM.</p></li></ul><p>4. Finalmente, acesse o componente <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/frontend/components/ChatUI.jsx">ChatUI.jsx</a> no diretório <code>frontend/components</code> para criar a interface do usuário para manter nossa conversa. Em seguida, envolva a resposta em um componente <code>ReactMarkdown</code> para formatar corretamente a resposta do agente.</p>import React, { useState } from 'react';
import { useChat } from '@ai-sdk/react';
import ReactMarkdown from 'react-markdown';

export default function ChatUI() {
    const [totalTokenUsage, setTotalTokenUsage] = useState(0);
    const [promptTokenUsage, setPromptTokenUsage] = useState(0);
    const [completionTokenUsage, setCompletionTokenUsage] = useState(0);
    const [toolsCalled, setToolsCalled] = useState([]);

    const { messages, input, handleInputChange, handleSubmit, status } = useChat({
        api: 'http://localhost:4111/api/agents/basketballAgent/stream', //Replace with your own endpoint for your agent
        id: 'my-chat-session',

        //Optional parameter to check agent tool calls
        onToolCall: ({ toolCall }) =&gt; {
            setToolsCalled((prev) =&gt; [...prev, toolCall.toolName]);
        },

        //Optional parameter to check token usages
        onFinish: (message, { usage }) =&gt; {
            setTotalTokenUsage((prev) =&gt; prev + usage.totalTokens);
            setPromptTokenUsage((prev) =&gt; prev + usage.promptTokens);
            setCompletionTokenUsage((prev) =&gt; prev + usage.completionTokens);
        },

        //Optional parameter for error handling
        onError: (error) =&gt; {
            console.error('Agent error:', error);
        },
    });

    return (
        &lt;div&gt;
            &lt;div className="agent-info"&gt;
                &lt;h4 className="stats-title"&gt;What's My Agent Doing?&lt;/h4&gt;

                &lt;div className="stats-box"&gt;
                    &lt;strong className="stats-sub-title"&gt;Tools Called:&lt;/strong&gt;
                    &lt;ul className="tool-list"&gt;
                        {toolsCalled.map((tool, idx) =&gt; (
                            &lt;li key={idx}&gt;{tool}&lt;/li&gt;
                        ))}
                        {toolsCalled.length === 0 &amp;&amp; &lt;li&gt;No tools called yet.&lt;/li&gt;}
                    &lt;/ul&gt;

                    &lt;div className="usage-stats"&gt;
                        &lt;p&gt;Prompt Token Usage: {promptTokenUsage}&lt;/p&gt;
                        &lt;p&gt;Completion Token Usage: {completionTokenUsage}&lt;/p&gt;
                        &lt;p&gt;Total Token Usage: {totalTokenUsage}&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;strong&gt;Conversation:&lt;/strong&gt;
            &lt;div className="convo-box"&gt;
                {messages.map((msg) =&gt; (
                    &lt;div key={msg.id} className="message-item"&gt;
                        &lt;strong className="message-role"&gt;{msg.role === 'assistant' ? 'Basketbot' : 'You'}:&lt;/strong&gt;
                        &lt;ReactMarkdown&gt;{msg.content}&lt;/ReactMarkdown&gt;
                    &lt;/div&gt;
                ))}
            &lt;/div&gt;

            &lt;form onSubmit={handleSubmit}&gt;
                &lt;input
                    type="text"
                    value={input}
                    onChange={handleInputChange}
                    placeholder="Input two players you want to compare."
                    className="input-box"
                /&gt;
                &lt;button type="submit" disabled={status === 'streaming'}&gt;
                    {status === 'streaming' ? 'Thinking...' : 'Send'}
                &lt;/button&gt;
            &lt;/form&gt;
        &lt;/div&gt;
    );
}<h4><strong>Etapa 9: Executando o aplicativo</strong></h4><p>Parabéns! Agora você está pronto para executar o aplicativo. Siga estes passos para iniciar tanto o backend quanto o frontend.</p><ol><li><p>Em uma janela de terminal, partindo do diretório raiz, navegue até o diretório de backend e inicie o servidor Mastra:</p></li></ol>cd backend

npm run dev<p>2. Em outra janela do terminal, partindo do diretório raiz, navegue até o diretório frontend e inicie o aplicativo React:</p><p></p>cd frontend

npm run dev<p></p><p>3. Acesse seu navegador e navegue até:</p><p></p><p><a href="http://localhost:5173/">http://localhost:5173</a></p><p></p><p>Você deverá conseguir visualizar a interface de bate-papo. Experimente estas sugestões:</p><ul><li><p>"Compare LeBron James e Stephen Curry"</p></li><li><p>"Quem devo escolher entre Jayson Tatum e Luka Doncic?"</p></li></ul><p></p><h3><strong>O que vem a seguir: tornar o agente mais inteligente.</strong></h3><p>Para tornar o assistente mais proativo e as recomendações mais relevantes, adicionarei algumas melhorias importantes na próxima versão.</p><p></p><p><strong>Busca semântica para notícias da NBA</strong></p><p>Existem inúmeros fatores que podem afetar o desempenho do jogador, muitos dos quais não aparecem nas estatísticas brutas. Informações como relatórios de lesões, alterações na escalação ou até mesmo análises pós-jogo só podem ser encontradas em artigos de notícias. Para capturar esse contexto adicional, adicionarei recursos de busca semântica para que o agente possa recuperar artigos relevantes da NBA e incorporar essa narrativa em suas recomendações.</p><p></p><p><strong>Pesquisa dinâmica com o servidor Elasticsearch MCP</strong></p><p>O MCP (Model Context Protocol) está rapidamente se tornando o padrão para a forma como os agentes se conectam às fontes de dados. Vou migrar a lógica de busca para o servidor Elasticsearch MCP, o que permite que o agente construa consultas dinamicamente em vez de depender de funções de busca predefinidas que fornecemos. Isso nos permite usar fluxos de trabalho em linguagem mais natural e reduz a necessidade de escrever manualmente cada consulta de pesquisa. Saiba mais sobre o servidor Elasticsearch MCP e o estado atual do ecossistema <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">aqui</a>.</p><p></p><p>Essas mudanças já estão em andamento, fique ligado!</p><h3><strong>Conclusão</strong></h3><p></p><p>Neste blog, criamos um assistente RAG interativo que fornece recomendações personalizadas para o seu time de basquete de fantasia usando JavaScript, Mastra e Elasticsearch. Nós abordamos os seguintes tópicos:</p><ul><li><p><strong>Fundamentos do RAG agético</strong> e como a combinação da autonomia de um agente de IA com as ferramentas para usar o RAG de forma eficaz pode levar a agentes mais dinâmicos e com nuances.</p></li><li><p><strong>Elasticsearch </strong>e como seus recursos de armazenamento de dados e poderosas agregações nativas o tornam um excelente parceiro como base de conhecimento para um mestrado em Direito (LLM).</p></li><li><p><strong>O framework Mastra </strong>e como ele simplifica a criação desses agentes para desenvolvedores no ecossistema JavaScript.</p></li></ul><p>Seja você um fanático por basquete, esteja explorando como construir agentes de IA, ou ambos como eu, espero que este blog tenha lhe dado algumas bases para começar. O repositório completo está disponível no <a href="https://github.com/jdarmada/nba-ai-assistant-js">GitHub</a>. Sinta-se à vontade para cloná-lo e fazer alterações. Agora, vá ganhar essa liga de fantasia!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agentic-rag</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agentic-rag</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Javascript]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ffd561836a4cb20/6a17f1e47b54f978588b39e4/8132ed781c1ea5d46ca244182f421ed5c721f23b-1200x628.png" length="0" type="image/png"/>
    <pubDate>Tue, 01 Jul 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Conecte agentes ao Elasticsearch com o protocolo de contexto do modelo]]></title>
    <description><![CDATA[Vamos usar o servidor Model Context Protocol para conversar com seus dados no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>E se interagir com seus dados fosse tão fácil quanto conversar com um colega? Imagine simplesmente perguntar: "Mostre-me todos os pedidos acima de US$ 500 do mês passado" ou "Quais produtos receberam mais avaliações de 5 estrelas?" e obter respostas instantâneas e precisas, sem precisar fazer perguntas.</p><p>O Model Context Protocol (MCP) torna isso possível. Ele conecta perfeitamente a IA conversacional com seus bancos de dados e APIs externas, transformando solicitações complexas em conversas naturais. Embora os LLMs modernos sejam ótimos para entender a linguagem, seu verdadeiro potencial é revelado quando integrados a sistemas do mundo real. O MCP preenche a lacuna entre eles, tornando a interação de dados mais intuitiva e eficiente.</p><p>Nesta postagem, exploraremos:</p><ul><li><p>Arquitetura MCP – Como funciona nos bastidores</p></li><li><p>Benefícios de um servidor MCP conectado ao Elasticsearch</p></li><li><p>Construindo um <a href="https://github.com/elastic/mcp-server-elasticsearch">servidor MCP com tecnologia Elasticsearch</a></p></li></ul><p>Tempos emocionantes estão por vir! A integração do MCP com sua pilha Elastic transforma a maneira como você interage com as informações, tornando consultas complexas tão intuitivas quanto conversas cotidianas.</p><h2>Protocolo de Contexto do Modelo</h2><p><a href="https://modelcontextprotocol.io/introduction">O Model Context Protocol</a> (MCP), desenvolvido pela Anthropic, é um padrão aberto que conecta modelos de IA a fontes de dados externas por meio de canais bidirecionais seguros. Ele resolve uma grande limitação da IA: acesso em tempo real a sistemas externos, preservando o contexto da conversa.</p><h3>Arquitetura MCP</h3><p>A arquitetura do Protocolo de Contexto do Modelo consiste em dois componentes principais:</p><ul><li><p><strong>Clientes MCP</strong> – Assistentes de IA e chatbots que solicitam informações ou executam tarefas em nome dos usuários.</p></li><li><p><strong>Servidores MCP</strong> – Repositórios de dados, mecanismos de busca e APIs que recuperam informações relevantes ou executam ações solicitadas (por exemplo, chamar APIs externas).</p></li></ul><p>Os servidores MCP expõem quatro funcionalidades principais aos clientes:</p><ul><li><p><strong>Recursos</strong> - Dados estruturados, documentos e conteúdo que podem ser recuperados e usados como contexto para interações de LLM. Isso permite que assistentes de IA acessem informações relevantes de bancos de dados, índices de pesquisa ou outras fontes.</p></li><li><p><strong>Ferramentas</strong> - Funções executáveis que permitem que os LLMs interajam com sistemas externos, realizem cálculos ou tomem ações no mundo real. Essas ferramentas estendem os recursos de IA além da geração de texto, permitindo que os assistentes acionem fluxos de trabalho, chamem APIs ou manipulem dados dinamicamente.</p></li><li><p><strong>Prompts</strong> - Modelos de prompts e fluxos de trabalho reutilizáveis para padronizar e compartilhar interações comuns de LLM.</p></li><li><p><strong>Amostragem</strong> - Solicite conclusões de LLM por meio do cliente para permitir comportamentos de agente sofisticados, mantendo a segurança e a privacidade.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfe82754551bb187a/6a17f7ec6864a43e71b6895d/bef5178133391e96e3d66ae634e41a85712a33a9-2345x1620.png" alt="Arquitetura do Protocolo de Contexto do Modelo (MCP)" /><h2>Servidor MCP + Elasticsearch</h2><p></p><p>Os sistemas tradicionais de Recuperação-Geração Aumentada (RAG) recuperam documentos com base em consultas do usuário, mas o MCP vai um passo além: ele permite que agentes de IA construam e executem tarefas dinamicamente em tempo real. Isso permite que os usuários façam perguntas em linguagem natural como:</p><p></p><ul><li><p>"Mostre-me todos os pedidos acima de US$ 500 do mês passado."</p></li><li><p>"Quais produtos receberam mais avaliações de 5 estrelas?"</p></li></ul><p></p><p>E obtenha respostas instantâneas e precisas, sem precisar escrever uma única consulta.</p><p></p><p>O MCP consegue isso por meio de:</p><ul><li><p>Seleção dinâmica de ferramentas – Os agentes escolhem de forma inteligente as ferramentas certas expostas por meio de servidores MCP com base na intenção do usuário. LLMs “mais inteligentes” geralmente são melhores em selecionar as ferramentas certas com os argumentos apropriados com base no contexto.</p></li><li><p>Comunicação bidirecional – Agentes e fontes de dados trocam informações fluidamente, refinando consultas conforme necessário (por exemplo, primeiro mapeie o índice de pesquisa e só então construa a consulta ES).</p></li><li><p>Orquestração de múltiplas ferramentas – Os fluxos de trabalho podem aproveitar ferramentas de vários servidores MCP simultaneamente.</p></li><li><p>Contexto persistente – Os agentes lembram interações anteriores, mantendo a continuidade entre as conversas.</p></li></ul><p>Um servidor MCP conectado ao Elasticsearch desbloqueia uma poderosa arquitetura de recuperação em tempo real. Os agentes de IA podem explorar, consultar e analisar dados do Elasticsearch sob demanda. Seus dados podem ser pesquisados por meio de uma interface de bate-papo simples.</p><p>Além de apenas recuperar dados, o MCP possibilita ações. Ele se integra a outras ferramentas para acionar fluxos de trabalho, automatizar processos e fornecer insights aos sistemas de análise. Ao separar a pesquisa da execução, o MCP mantém os aplicativos com tecnologia de IA flexíveis, atualizados e perfeitamente integrados aos fluxos de trabalho do agente.</p><h2>Prático: servidor MCP para conversar com seus dados do Elasticsearch</h2><p>Para interagir com o Elasticsearch por meio de um servidor MCP, precisamos de pelo menos funções para:</p><ul><li><p>Recuperar índices</p></li><li><p>Obter mapeamentos</p></li><li><p>Realizar pesquisas usando o Query DSL do Elasticsearch</p></li></ul><p>Nosso servidor é escrito em TypeScript e usaremos o <a href="https://github.com/modelcontextprotocol/typescript-sdk">SDK oficial do MCP TypeScript</a>. Para configuração, recomendamos instalar o aplicativo Claude Desktop (a versão gratuita é suficiente), pois ele inclui um cliente MCP integrado. Nosso servidor MCP essencialmente expõe o <a href="https://www.elastic.co/pt/guide/en/elasticsearch/client/javascript-api/current/index.html">cliente oficial do JavaScript Elasticsearch</a> por meio de ferramentas MCP.</p><p>Vamos começar definindo o cliente Elasticsearch e o servidor MCP:</p> const esClient = new Client({
    node: url,
    auth: {
      apiKey: apiKey,
    },
  });

  const server = new McpServer({
    name: "elasticsearch-mcp-server",
    version: "0.1.0",
  });<p>Usaremos as seguintes ferramentas de servidor MCP que podem interagir com o Elasticsearch:</p><ul><li><p><strong>Listar índices</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L46">list_indices</a>): esta ferramenta recupera todos os índices disponíveis do Elasticsearch, fornecendo detalhes como nome do índice, status de integridade e contagem de documentos.</p></li><li><p><strong>Obter mapeamentos</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L94">get_mappings</a>): esta ferramenta busca os mapeamentos de campos para um índice especificado do Elasticsearch, ajudando os usuários a entender a estrutura e os tipos de dados dos documentos armazenados.</p></li><li><p><strong>Pesquisar</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L147">search</a>): Esta ferramenta executa uma pesquisa no Elasticsearch usando um DSL de consulta fornecido. Ele habilita automaticamente destaques para campos de texto, facilitando a identificação de resultados de pesquisa relevantes.</p></li></ul><p>A implementação completa do servidor Elasticsearch MCP está disponível no repositório <a href="https://github.com/elastic/mcp-server-elasticsearch">elastic/mcp-server-elasticsearch</a> .</p><h4>Converse com seu índice</h4><p>Vamos explorar como configurar o servidor Elasticsearch MCP para que você possa fazer perguntas em linguagem natural sobre seus dados, como "Encontrar todos os pedidos acima de US$ 500 do mês passado".</p><p><strong>Configure seu aplicativo Claude Desktop</strong></p><ul><li><p>Abra o aplicativo Claude Desktop</p></li><li><p>Navegue até Configurações &gt; Desenvolvedor &gt; Servidores MCP</p></li><li><p>Clique em "Editar configuração" e adicione esta configuração ao seu <code>claude_desktop_config.json</code>:</p></li></ul>{
  "mcpServers": {
    "Elasticsearch MCP Server": {
      "command": "npx",
      "args": [
        "-y",
        "@elastic/mcp-server-elasticsearch"
      ],
      "env": {
        "ES_URL": "",
        "ES_API_KEY": ""
      }
    }
  }
}<p>Observação: esta configuração utiliza o pacote npm <a href="https://www.npmjs.com/package/@elastic/mcp-server-elasticsearch">@elastic/mcp-server-elasticsearch</a> publicado pela Elastic. Se você quiser desenvolver localmente, poderá encontrar mais detalhes sobre como configurar o servidor Elasticsearch MCP <a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/README.md">aqui</a>.</p><p><strong>Preencha seu índice Elasticseach</strong></p><ul><li><p>Você pode usar nossos <a href="https://gist.github.com/jedrazb/60e9400cbe40addfd9e4337749c28431">dados de exemplo</a> para preencher o índice de "pedidos" para esta demonstração</p></li><li><p>Isso permitirá que você tente consultas como "Encontrar todos os pedidos acima de US$ 500 do mês passado"</p></li></ul><p><strong>Comece a usar</strong></p><ul><li><p>Abra uma nova conversa no aplicativo Claude Desktop</p></li><li><p>O servidor MCP se conectará automaticamente</p></li><li><p>Comece a fazer perguntas sobre seus dados do Elasticsearch!</p></li></ul><p>Confira esta demonstração para ver como é fácil consultar seus dados do Elasticsearch usando linguagem natural:</p><h4>Como funciona?</h4><p>Quando perguntado "Encontre todos os pedidos acima de US$ 500 do mês passado", o LLM reconhece a intenção de pesquisar o índice do Elasticsearch com restrições especificadas. Para realizar uma busca eficaz, o agente deve:</p><ul><li><p>Descubra o nome do índice: <code>orders</code></p></li><li><p>Entenda os mapeamentos do índice <code>orders</code></p></li><li><p>Crie o DSL de consulta compatível com mapeamentos de índice e, finalmente, execute a solicitação de pesquisa</p></li></ul><p>Essa interação pode ser representada como:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt152f41bc8c3e9752/6a17f7ee6df73152df0a10cc/8875bc75745124be87deac0be666509446887de2-2345x1620.png" alt="Como funciona o servidor MCP + Elasticsearch" /><h2>Conclusão</h2><p>O Model Context Protocol aprimora a maneira como você interage com os dados do Elasticsearch, permitindo conversas em linguagem natural em vez de consultas complexas. Ao unir recursos de IA com seus dados, o MCP cria um fluxo de trabalho mais intuitivo e eficiente que mantém o contexto em todas as suas interações.</p><p>O servidor Elasticsearch MCP está disponível como um pacote npm público (<a href="https://www.npmjs.com/package/@elastic/mcp-server-elasticsearch">@elastic/mcp-server-elasticsearch</a>), tornando a integração simples para desenvolvedores. Com configuração mínima, sua equipe pode começar a explorar dados, acionar fluxos de trabalho e obter insights por meio de conversas simples.</p><p>Pronto para experimentar isso você mesmo? Experimente o <a href="https://github.com/elastic/mcp-server-elasticsearch">servidor Elasticsearch MCP</a> hoje mesmo e comece a conversar com seus dados.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltce68a95c633809ae/6a17f7f0148009fa28b48915/65b378f644bd13e3edf2f108d48186f1889f546c-1200x628.png" length="0" type="image/png"/>
    <pubDate>Fri, 28 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[O agente de IA para gerenciar projetos Elasticsearch Serverless]]></title>
    <description><![CDATA[Um agente de IA com capacidade de linguagem natural que gerencia projetos Elasticsearch Serverless sem esforço, permitindo a criação, exclusão e verificação de status de projetos.]]></description>
    <content:encoded><![CDATA[<h2>Como usar um agente de IA para gerenciar projetos Elasticsearch sem servidor</h2><ol><li><p><strong>Clone o repositório:</strong> Baixe o código da ferramenta do GitHub usando <code>git clone https://github.com/elastic/elasticsearch-labs/supporting-blog-content/serverless-ai-agent</code> <code>a</code>e navegue até o diretório com <code>cd serverless-ai-agent</code>.</p></li><li><p><strong>Configurar ambiente: </strong>Crie um ambiente virtual (opcional) com <code>python -m venv venv</code> e ative-o (<code>source venv/bin/activate</code> ou <code>venv\Scripts\activate</code> no Windows). Em seguida, instale os pacotes Python necessários usando <code>pip install -r requirements.txt</code>.</p></li><li><p><strong>Configure as credenciais: </strong>Crie um arquivo <code>.env</code> na raiz do projeto e preencha-o com o URL da API do Elasticsearch (<code>ES_URL</code>), a chave da API (<code>API_KEY</code>), a região (<code>REGION</code>) e a chave da API do OpenAI (<code>OPENAI_API_KEY</code>).</p></li><li><p><strong>Execute a ferramenta: </strong>Execute a ferramenta executando <code>python main.py</code> em seu terminal. Isso iniciará o agente de IA e exibirá uma tela para que você insira seus comandos.</p></li><li><p><strong>Gerencie projetos com linguagem natural:</strong> interaja com a ferramenta usando comandos em inglês simples, como "Criar um projeto serverless chamado my_project", "Obter o status do projeto serverless chamado my_project" ou "Excluir o projeto serverless chamado my_project". A IA interpretará seus comandos e executará as funções correspondentes.</p></li></ol><h2>Histórico</h2><p>Esta pequena ferramenta de linha de comando permite gerenciar seus <a href="https://www.elastic.co/guide/en/serverless/current/intro.html">projetos Serverless Elasticsearch</a> em linguagem simples. Ele se comunica com uma IA (neste caso, a OpenAI) para entender o que você quer dizer e chamar as funções corretas usando o LlamaIndex!</p><h3>O que o agente de IA Serverless do Elasticsearch pode fazer?</h3><ul><li><p><strong>Criar um projeto</strong>: Inicie um novo projeto Elasticsearch sem servidor.</p></li><li><p><strong>Excluir um projeto</strong>: Remove um projeto existente (sim, ele limpa tudo depois).</p></li><li><p><strong>Obtenha o status do projeto</strong>: verifique como está o andamento do seu projeto.</p></li><li><p><strong>Obtenha detalhes do projeto</strong>: Descubra todas as informações relevantes sobre o seu projeto.</p></li></ul><p>Confira o código no <a href="https://github.com/elastic/elasticsearch-labs/tree/a65f7bc1e4a041765d1c0a45ac44b9cd9fc1589f/supporting-blog-content/serverless-ai-agent">GitHub.</a></p><h3>Como funciona o agente de IA sem servidor do Elasticsearch</h3><p>Quando você digita algo como:</p><p><em>"Crie um projeto sem servidor chamado my_project"</em></p><p>…eis o que acontece nos bastidores:</p><ul><li><p><strong>Entrada e contexto do usuário:</strong> Seu comando em linguagem natural é enviado ao agente de IA.</p></li><li><p><strong>Descrição das funções:</strong> O agente de IA já conhece algumas funções — como create_ess_project, delete_ess_project, get_ess_project_status e get_ess_project_details — porque fornecemos descrições detalhadas. Essas descrições informam à IA o que cada função faz e quais parâmetros elas precisam.</p></li><li><p><strong>Processamento LLM:</strong> Sua consulta, juntamente com as informações da função, é enviada para o LLM. Isso significa que a IA vê:</p><ul><li><p><strong>Consulta do usuário</strong>: Sua instrução em linguagem simples.</p></li><li><p><strong>Funções e descrições disponíveis</strong>: Detalhes sobre o que cada ferramenta faz para que você possa escolher a mais adequada.</p></li><li><p><strong>Informações de contexto/histórico do chat</strong>: Como se trata de uma conversa, o sistema se lembra do que foi dito anteriormente.</p></li></ul></li><li><p><strong>Chamada e resposta de função:</strong> A IA determina qual função chamar, passa os parâmetros corretos (como o nome do seu projeto) e, em seguida, a função é executada. A resposta será enviada a você em um formato amigável.</p></li></ul><p>Resumindo, estamos enviando ao LLM tanto sua consulta em linguagem natural quanto uma lista de descrições detalhadas das ferramentas para que ele possa "entender" e escolher a ação correta para sua solicitação.</p><h3>Configure o agente de IA</h3><h4>Pré-requisitos:</h4><p>Antes de executar o agente de IA, certifique-se de que a seguinte configuração esteja correta:</p><ol><li><p><strong>Python (versão 3.7 ou posterior)</strong> instalado.</p></li><li><p>Configuração de <strong>uma conta serverless do Elasticsearch</strong> no Elastic Cloud.</p></li><li><p><strong>Conta OpenAI</strong> para interagir com o modelo de linguagem.</p></li></ol><h4>Passos:</h4><p><strong>1. Clone o repositório:</strong></p>git clone https://github.com/elastic/elasticsearch-labs/supporting-blog-content/serverless-ai-agent
cd serverless-ai-agent<p><strong>2. Criar um ambiente virtual (opcional, mas recomendado):</strong> Se você estiver enfrentando problemas relacionados ao ambiente, pode configurar um ambiente virtual para isolamento:</p>python -m venv venv
source venv/bin/activate  # On Windows, use venv\Scripts\activate<p><strong>3. Instale as dependências:</strong> Certifique-se de que todas as dependências necessárias estejam instaladas executando o seguinte comando:</p>pip install -r requirements.txt<p><strong>4. Configure seu ambiente:</strong> Crie um arquivo .env Arquivo na raiz do projeto com as seguintes variáveis. Aqui está um exemplo de arquivo <code>.env.example</code> para te ajudar:</p>ES_URL=your_elasticsearch_api_url  # The base URL for your Elasticsearch service (e.g., https://your-cluster-id.es.region.aws.elastic-cloud.com)
API_KEY=your_elasticsearch_api_key  # Your API key for Elasticsearch
REGION=your_region  # Example: aws-eu-west-1
OPENAI_API_KEY=your_openai_api_key  # Your OpenAI API key<p>Certifique-se de que você tem os valores corretos para <code>ES_URL</code>, <code>API_KEY</code> e <code>OPENAI_API_KEY</code>. Você pode encontrar suas chaves de API nos respectivos painéis de serviço.</p><p><strong>5. Arquivo de Projetos:</strong> A ferramenta usa um arquivo <code>projects.json</code> para armazenar seus mapeamentos de projetos (nomes de projetos para seus detalhes). Este arquivo será criado automaticamente caso ainda não exista.</p><h3>Executando o agente de IA</h3>python main.py<p>Você verá uma mensagem como esta:</p>Welcome to the Serverless Project AI Agent Tool!
You can ask things like:
 - 'Create a serverless project named my_project'
 - 'Delete the serverless project named my_project'
 - 'Get the status of the serverless project named my_project'
 - 'Get the details of the serverless project named my_project'<p>Digite o comando e o agente de IA fará a sua mágica! Quando terminar, digite <code>exit</code> ou <code>quit</code> para sair.</p><h3>Mais alguns detalhes</h3><ul><li><p><strong>Integração com o LLM</strong>: O LLM recebe tanto a sua consulta quanto descrições detalhadas de cada função disponível. Isso ajuda a entender o contexto e a decidir, por exemplo, se deve chamar <code>create_ess_project</code> ou <code>delete_ess_project</code>.</p></li><li><p><strong>Descrição das ferramentas</strong>: Cada ferramenta de função (criada usando FunctionTool.from_defaults) Possui uma descrição amigável. Essa descrição está incluída no prompt enviado ao LLM para que ele "saiba" quais ações estão disponíveis e o que cada ação espera.</p></li><li><p><strong>Persistência</strong>: Seus projetos e seus detalhes são salvos em projects.json. Assim você não precisa inserir as informações novamente toda vez.</p></li><li><p><strong>Registro detalhado</strong>: O agente está configurado para o modo detalhado, o que é ótimo para depuração e para ver como suas instruções são traduzidas em chamadas de função.</p></li></ul><h3>Exemplo de utilização do agente de IA do Elasticsearch</h3>python main.py 

Welcome to the Serverless Project AI Agent Tool!

You can ask things like:
 - 'Create a serverless project named my_project'
 - 'Delete the serverless project named my_project'
 - 'Get the status of the serverless project named my_project'
 - 'Get the details of the serverless project named my_project'

User: Create a serverless project named my-february-test
Added user message to memory: Create a serverless project named my-february-test

=== Calling Function ===
Calling function: create_ess_project with args: {"project_name":"my-february-test"}
========================


Agent: The serverless Elasticsearch project named "my-february-test" has been created successfully. Here are the details:

- **Project ID:** &lt;&gt;&gt;
- **Elasticsearch Endpoint:** [https://my-february-test-ccc399.es.eu-west-1.aws.qa.elastic.cloud](https://my-february-test-ccc399.es.eu-west-1.aws.qa.elastic.cloud)
- **Kibana Endpoint:** [https://my-february-test-ccc399.kb.eu-west-1.aws.qa.elastic.cloud](https://my-february-test-ccc399.kb.eu-west-1.aws.qa.elastic.cloud)

User: get my-february-test status
Added user message to memory: get my-february-test status

=== Calling Function ===
Calling function: get_ess_project_status with args: {"project_name":"my-february-test"}
========================

Agent: The status of the "my-february-test" project is currently **initializing**.

User: get my-february-test info
Added user message to memory: get my-february-test info

=== Calling Function ===
Calling function: get_ess_project_details with args: {"project_name":"my-february-test"}
========================

Agent: Here are the details for the "my-february-test" project:

- **Project Name:** my-february-test
- **Alias:** my-february-test-ccc399
- **Cloud ID:** ""
- **Project ID:** ""
- **Region ID:** aws-eu-west-1
- **Created At:** 2025-02-12T15:42:00.530177619Z
- **Created By:** 571213384
- **Organization ID:** ""
- **Type:** Elasticsearch
- **Optimized For:** General Purpose
- **Search Lake:**
  - **Boost Window:** 7
  - **Search Power:** 100
- **Endpoints:**
  - **Elasticsearch:** https://my-february-test-ccc399.es.eu-west-1.aws.qa.elastic.cloud
  - **Kibana:** https://my-february-test-ccc399.kb.eu-west-1.aws.qa.elastic.cloud
- **Credentials:**
  - **Username:** ""
  - **Password:** ""

Please ensure to keep the credentials secure.

User: please delete the my-february-test project
Added user message to memory: please delete the my-february-test project

=== Calling Function ===
Calling function: delete_ess_project with args: {"project_name":"my-february-test"}
========================

Agent: The "my-february-test" project has been deleted successfully.<p></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/serverless-elasticsearch-ai-agent</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/serverless-elasticsearch-ai-agent</guid>
    <category><![CDATA[Elastic Cloud Serverless]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Fram Souza]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt88526af16bafdb7c/6a17d7807f6f15825dc0998d/d11e1ba058784ec92b8953fb8db62e1bad21c210-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 04 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>