Author: Make.com Service User

  • Estenda o Gerador de SBOM do Amazon Inspector com Plugins

    O que é o Amazon Inspector SBOM Generator?

    O Amazon Inspector é um serviço de gerenciamento de vulnerabilidades que escaneia continuamente workloads da Amazon Web Services (AWS) em busca de falhas de segurança em software. O motor por trás dessa capacidade é o Amazon Inspector SBOM Generator — conhecido como inspector-sbomgen — uma ferramenta de linha de comando independente que gera uma Lista de Materiais de Software (SBOM — Software Bill of Materials) a partir de imagens de contêiner, diretórios, arquivos compactados, sistemas locais, binários compilados e muito mais.

    Ao longo dos últimos dois anos, a AWS expandiu a cobertura do inspector-sbomgen para dezenas de ecossistemas de linguagens de programação, sistemas operacionais e aplicações amplamente utilizadas. Agora, a empresa anuncia uma novidade relevante para quem constrói com essa ferramenta: um sistema de plugins para criação de coletores de pacotes personalizados.

    Por que a AWS construiu um sistema de plugins?

    Ecossistemas de software são dinâmicos por natureza. Novos gerenciadores de pacotes, formatos de lockfile e aplicações surgem constantemente — muitas vezes com pouco escrutínio de segurança. Isso deixa equipes de segurança com uma lacuna de visibilidade: workloads em produção rodando software que as ferramentas de SBOM ainda não reconhecem.

    Antes dos plugins, o único caminho para suportar um novo ecossistema era abrir uma solicitação de funcionalidade e aguardar que a equipe do inspector-sbomgen integrasse o ecossistema e publicasse uma nova versão. O sistema de plugins muda esse cenário completamente.

    Com plugins, é possível:

    • Integrar ecossistemas não suportados nativamente: novos ecossistemas open source, formatos de pacote de nicho e ferramentas internas ou proprietárias podem ser inventariados sem modificar o inspector-sbomgen.
    • Prototipar detecção rapidamente: o sistema foi projetado para ser amigável tanto para desenvolvedores quanto para assistentes de codificação com IA. Os plugins são escritos em Lua, carregados em tempo de execução e não exigem toolchain Go nem compilação.
    • Construir sobre uma base estável: a API de plugins abstrai as diferenças entre tipos de artefatos, então a lógica de detecção é escrita uma única vez e funciona em imagens de contêiner, arquivos compactados, sistemas locais e mais.

    Internamente, a AWS já utilizou o sistema de plugins para acelerar a entrega de novos ecossistemas. Na versão 1.13, mais de 20 ecossistemas que antes eram implementados em Go — incluindo Apache Tomcat, NGINX, MySQL, Redis, WordPress e a toolchain do OpenSSH — foram convertidos para plugins embutidos no binário. A mesma versão também adicionou mais de dez ecossistemas totalmente novos como plugins, incluindo Apache Cassandra, Apache Struts, Conda, pacotes Swift e coletores de agentes de IA (Amazon Q Developer, Kiro CLI, Claude Code, GitHub Copilot e Ollama).

    Como os plugins do inspector-sbomgen funcionam

    Os plugins seguem um pipeline de duas etapas:

    • Descoberta (Discovery): varre o sistema de arquivos do artefato para identificar arquivos que contêm metadados de pacotes instalados.
    • Coleta (Collection): abre cada arquivo descoberto, analisa seu conteúdo e publica os resultados no SBOM.

    Por baixo dos panos, um barramento de eventos conecta os plugins de descoberta e coleta. Os plugins de descoberta publicam eventos listando os arquivos encontrados, e um ou mais plugins de coleta se inscrevem nesses eventos para disparar a coleta de pacotes. Desenvolvedores familiarizados com padrões de design vão reconhecer esse comportamento como o padrão observer.

    Esse desacoplamento permite que um único plugin de descoberta alimente múltiplos coletores — por exemplo, um extraindo metadados de pacotes, outro buscando segredos e outro verificando políticas — tudo a partir da mesma lista de arquivos, sem precisar percorrer o sistema de arquivos do artefato novamente.

    Criando seu primeiro plugin em 5 minutos

    O inspector-sbomgen facilita a criação de um ambiente de plugin. O comando plugin new cria um novo workspace de plugin, e a flag --with-example popula o workspace com um par de plugins de descoberta e coleta prontos para execução imediata.

    inspector-sbomgen plugin new --with-example

    Após invocar o comando, será solicitado um nome para o plugin e um diretório para o workspace. É possível fornecer valores personalizados ou usar os valores padrão:

    Plugin name (identifies the software ecosystem your plugin will inventory, e.g. debian-dpkg, rhel-rpm, python-pip, cmake) [my-custom-ecosystem]: <enter>
    Project directory [my-sbomgen-plugins]: <enter>
    Created plugin "my-custom-ecosystem" in my-sbomgen-plugins/

    Também é possível pular os prompts interativos especificando o nome do plugin e o diretório diretamente via argumentos de Interface de Linha de Comando (CLI — Command Line Interface):

    inspector-sbomgen plugin new \
      --with-example \
      --name my-custom-ecosystem \
      --path my-sbomgen-plugins

    Após criar o workspace, o inspector-sbomgen exibe uma tela de próximos passos que guia desenvolvedores e assistentes de IA aos arquivos que precisam ser modificados e à documentação de suporte:

    Next steps:
    
      Get started:
        1. Open plugin folder in a code editor (VS Code recommended)
        2. Add test files that your plugin will discover and parse (e.g., config files, lockfiles, binaries, etc.):
           my-sbomgen-plugins/discovery/cross-platform/extra-ecosystems/my-custom-ecosystem/_testdata/
    
      Develop:
        3. Edit discovery:   my-sbomgen-plugins/discovery/cross-platform/extra-ecosystems/my-custom-ecosystem/init.lua
        4. Edit collection:  my-sbomgen-plugins/collection/cross-platform/extra-ecosystems/my-custom-ecosystem/init.lua
    
      Test:
        5. Write unit tests: my-sbomgen-plugins/discovery/cross-platform/extra-ecosystems/my-custom-ecosystem/init_test.lua
        6. Run unit tests:   inspector-sbomgen plugin test --path my-sbomgen-plugins
    
      Deploy:
        7. Distribute your plugin directory wherever you run inspector-sbomgen:
           inspector-sbomgen <arguments> --plugin-dir /path/to/my-sbomgen-plugins
           Example:
           inspector-sbomgen container --image alpine:latest -o /tmp/sbom.json --plugin-dir /path/to/my-sbomgen-plugins
    
    For code completion, install the VS Code Lua language server extension:
      https://luals.github.io/#vscode-install
    
    For more information:
      - Plugin guide:    my-sbomgen-plugins/docs/sbomgen-plugin-developer-guide.md
      - Testing guide:   my-sbomgen-plugins/docs/sbomgen-plugin-testing-guide.md
      - API reference:   my-sbomgen-plugins/docs/sbomgen-plugin-api-reference.md
      - Documentation:   https://docs.aws.amazon.com/inspector/latest/user/sbom-generator.html

    A estrutura do workspace gerado é a seguinte:

    tree my-sbomgen-plugins
    ├── AGENTS.md
    ├── collection
    │   └── cross-platform
    │       └── extra-ecosystems
    │           └── my-custom-ecosystem
    │               └── init.lua
    ├── discovery
    │   └── cross-platform
    │       └── extra-ecosystems
    │           └── my-custom-ecosystem
    │               ├── _testdata
    │               │   ├── empty
    │               │   └── example.lock
    │               ├── init_test.lua
    │               └── init.lua
    ├── docs
    │   ├── sbomgen-plugin-api-reference.md
    │   ├── sbomgen-plugin-developer-guide.md
    │   └── sbomgen-plugin-testing-guide.md
    ├── library
    │   └── sbomgen.lua
    └── README.md

    O projeto gerado inclui um par funcional de plugins de descoberta e coleta, testes unitários com fixtures em _testdata/, integração com o Ambiente de Desenvolvimento Integrado (IDE — Integrated Development Environment) e uma cópia local da documentação do desenvolvedor. O scaffolding é deliberadamente conciso e completo, com comentários claros em cada arquivo explicando o que cada função faz.

    Exemplo de plugin de descoberta

    O plugin de exemplo inventaria um arquivo fictício example.lock com o seguinte conteúdo:

    my-package-alpha==1.0.0
    my-package-beta==2.3.1
    my-package-gamma==0.9.5

    O plugin de descoberta sabe como localizar instâncias de example.lock no sistema de arquivos do artefato:

    -- my-custom-ecosystem discovery plugin
    -- Discovers example.lock files in the artifact file list.
    function discover()
        return sbomgen.find_files_by_name({"example.lock"})
    end

    Exemplo de plugin de coleta

    O plugin de coleta sabe como analisar o conteúdo de example.lock e publicar os pacotes encontrados no SBOM de saída:

    -- my-custom-ecosystem collection plugin
    -- Parses example.lock files and extracts package name and version.
    function collect(file_path)
        local content = sbomgen.read_file(file_path)
        if content == nil then
            return
        end
        for line in content:gmatch("[^\n]+") do
            local name, ver = line:match("^(.+)==(.+)$")
            if name and ver then
                sbomgen.push_package({
                    name           = name,
                    version        = ver,
                    purl_type      = "generic",
                    namespace      = "my-custom-ecosystem",
                    component_type = sbomgen.component_types.APPLICATION,
                })
            end
        end
    end

    Executando os testes

    Os plugins incluem um framework de testes integrado para validar a lógica antes de escanear um artefato real. Os testes são escritos em Lua, ficam ao lado do plugin em init_test.lua e referenciam dados de fixture em _testdata/:

    function test_discovers_packages()
        local result = testing.scan_directory("_testdata")
        testing.assert_equals(3, #result.findings)
        testing.assert_equals("my-package-alpha", result.findings[1].name)
        testing.assert_equals("1.0.0", result.findings[1].version)
    end
    
    function test_no_findings_for_empty_directory()
        local result = testing.scan_directory("_testdata/empty")
        testing.assert_equals(0, #result.findings)
    end

    Execute os testes com o seguinte comando:

    inspector-sbomgen plugin test --path my-sbomgen-plugins -v
    
    === RUN   my-custom-ecosystem/discovery/init_test/test_discovers_packages
    --- PASS: my-custom-ecosystem/discovery/init_test/test_discovers_packages (0.04s)
    === RUN   my-custom-ecosystem/discovery/init_test/test_no_findings_for_empty_directory
    --- PASS: my-custom-ecosystem/discovery/init_test/test_no_findings_for_empty_directory (0.04s)
    ok  2 tests passed

    Esse é o ciclo de desenvolvimento mais ágil possível: sem toolchain Go, sem recompilação, sem inicialização de contêiner. Escreva o teste, execute, itere.

    Escaneando um artefato real

    Para que os plugins produzam resultados, o inspector-sbomgen precisa de um artefato que contenha os arquivos que o plugin procura. Para o plugin de exemplo, qualquer diretório com um arquivo example.lock funciona:

    inspector-sbomgen directory \
      --plugin-dir ./my-sbomgen-plugins \
      --path ./my-sbomgen-plugins/discovery/cross-platform/extra-ecosystems/my-custom-ecosystem/_testdata \
      -o sbom.json

    A flag --plugin-dir indica ao inspector-sbomgen onde carregar os plugins Lua. O SBOM resultante contém um componente CycloneDX para cada um dos três pacotes do example.lock, por exemplo:

    {
      "bom-ref": "comp-2",
      "type": "application",
      "name": "my-package-alpha",
      "version": "1.0.0",
      "scope": "optional",
      "purl": "pkg:generic/my-sbomgen-plugin/my-package-alpha@1.0.0",
      "properties": [
        {
          "name": "amazon:inspector:sbom_generator:source_path",
          "value": "./my-sbomgen-plugins/example.lock"
        }
      ]
    }

    Todo componente gerado por plugin carrega uma propriedade amazon:inspector:sbom_generator:source_path que registra o arquivo de origem, permitindo rastrear cada componente até o artefato que o produziu.

    Escaneamento de vulnerabilidades com o Amazon Inspector

    Os resultados gerados por plugins são componentes SBOM de primeira classe e funcionam com qualquer consumidor downstream que leia SBOMs CycloneDX, incluindo o próprio Amazon Inspector. Para enviar um SBOM ao Amazon Inspector para análise de vulnerabilidades, basta adicionar a flag --scan-sbom (requer uma conta AWS ativa):

    inspector-sbomgen directory \
      --path ./my-sbomgen-plugins/discovery/cross-platform/extra-ecosystems/my-custom-ecosystem/_testdata \
      --plugin-dir ./my-sbomgen-plugins \
      --scan-sbom \
      --aws-profile your_profile \
      --aws-region your_region \
      -o /tmp/sbom.json

    Um ponto importante: plugins podem inventariar ecossistemas arbitrários, mas o Amazon Inspector só consegue reportar vulnerabilidades para componentes cujos ecossistemas já estão em seus feeds de avisos. Quando um componente de ecossistema ainda não suportado é enviado, o Inspector retorna o componente com a propriedade Component skipped: no supported rules found. — comportamento esperado, não um erro. O SBOM ainda é gerado corretamente e o componente continua sendo rastreado. Quando o Inspector adicionar cobertura para aquele ecossistema, o mesmo SBOM passará a produzir resultados de vulnerabilidades automaticamente, sem nenhuma alteração no plugin.

    Suporte a IDE de primeira classe

    Todo projeto de plugin gerado com o comando plugin new inclui um arquivo library/sbomgen.lua e um .vscode/settings.json que se integra automaticamente à extensão sumneko.lua do Servidor de Linguagem Lua para o VS Code. Com isso, cada função sbomgen.* passa a ter:

    • Dicas de parâmetros com tipos.
    • Documentação ao passar o cursor.
    • Autocompletar para constantes (sbomgen.component_types.*, sbomgen.groups.*, sbomgen.platform.*).
    • Verificação de tipos nas chamadas de função.
    • Avisos inline quando campos obrigatórios estão ausentes em push_package().

    O mesmo arquivo de definição torna o desenvolvimento de plugins eficiente com assistentes de codificação por IA, pois os tipos e a documentação estão embutidos em um formato que essas ferramentas conseguem ler.

    Modelo de segurança dos plugins

    Como os plugins executam código real dentro do mesmo processo do inspector-sbomgen, o ambiente de execução foi projetado para manter esse código estável e endurecido do ponto de vista de segurança. Cada plugin Lua roda em um sandbox isolado, com acesso apenas a um subconjunto restrito da biblioteca padrão Lua:

    • Sem acesso direto ao sistema de arquivos: a biblioteca io do Lua não é carregada. Todas as operações de arquivo passam pelas funções sbomgen.*.
    • Sem execução de subprocessos ou mutação de ambiente: a biblioteca os do Lua é bloqueada, impedindo que plugins iniciem processos, modifiquem variáveis de ambiente ou toquem em arquivos fora do artefato.
    • Sem introspecção da Máquina Virtual (VM — Virtual Machine): a biblioteca debug do Lua é bloqueada.
    • Sem carregamento irrestrito de código: dofile, loadfile e loadstring são removidos. O require() está disponível, mas restrito à árvore de diretórios do próprio plugin.

    Se um plugin gerar um erro Lua não tratado, o inspector-sbomgen registra um aviso e continua com o próximo arquivo ou plugin — um plugin com falha não impede os demais de rodar. Além disso, plugins nunca sobrescrevem os coletores internos do inspector-sbomgen: todo plugin precisa declarar um nome único, e se um plugin personalizado usar um nome já reservado por um plugin oficial, ele é ignorado com um aviso. Os plugins internos sempre têm precedência.

    Próximos passos

    Para começar a construir seus próprios plugins, a AWS recomenda:

    • Instalar a versão mais recente do inspector-sbomgen pelo guia do usuário do Amazon Inspector.
    • Executar inspector-sbomgen plugin new --with-example e seguir os prompts.
    • Rodar inspector-sbomgen plugin test --path ./my-sbomgen-plugins -v para ver os testes de exemplo passando.
    • Substituir a lógica de exemplo pela detecção do seu próprio ecossistema.

    A documentação de referência completa cobre todas as funções, constantes e comandos em profundidade:

    Conclusão

    O sistema de plugins do inspector-sbomgen foi projetado para encurtar ao máximo o caminho entre uma ideia e um SBOM funcional — seja para adicionar suporte a um formato interno de lockfile, prototipar detecção para um novo ecossistema open source ou substituir um scanner caseiro por algo que toda a organização possa executar em escala. Com Lua, sandbox seguro, suporte a IDE e integração nativa com o Amazon Inspector, a AWS entrega uma extensibilidade real sem abrir mão da segurança e da previsibilidade da ferramenta.

    Fonte

    Extend Amazon Inspector SBOM Generator with Plugins (https://aws.amazon.com/blogs/security/extend-amazon-inspector-sbom-generator-with-plugins/)

  • Amazon SageMaker Unified Studio agora oferece controle de versão Git completo em todas as ferramentas de projeto

    Controle de versão Git chega a todas as ferramentas do SageMaker Unified Studio

    A AWS anunciou uma atualização significativa no Amazon SageMaker Unified Studio: a plataforma agora oferece controle de versão Git completo e integrado diretamente em todas as ferramentas de projeto — incluindo Query Editor, Visual ETL, Workflows e Notebooks.

    A novidade representa uma evolução importante para equipes que trabalham com dados e machine learning na AWS, pois unifica a experiência de controle de código-fonte em um único ambiente, sem a necessidade de alternar entre ferramentas externas.

    O que mudou na experiência de repositórios

    A experiência aprimorada de repositórios substitui o modelo anterior de sincronização automática por uma abordagem mais flexível, com controle de versão em nível de arquivo. Isso significa que cada membro do projeto pode escolher exatamente quais arquivos deseja rastrear no Git — o controle de versão não é imposto no nível do projeto, ficando a critério de cada equipe definir o que será versionado e quando.

    Um ponto de destaque é que os Notebooks, que anteriormente não tinham suporte a Git no SageMaker Unified Studio, agora passam a contar com essa integração de forma consistente, igualando-se às demais ferramentas da plataforma.

    Flexibilidade na conexão com repositórios

    A integração suporta os principais provedores de controle de versão do mercado: GitHub, GitLab e Bitbucket. Entre os principais recursos disponíveis, destacam-se:

    • Os repositórios são desacoplados da criação do projeto — é possível adicionar um repositório a qualquer momento, conforme as necessidades da equipe evoluem;
    • Um projeto pode se conectar a múltiplos repositórios e branches simultaneamente;
    • É possível criar branches, puxar atualizações e resolver conflitos sem sair do ambiente do projeto;
    • Ao finalizar as alterações, o commit e o push de todas as mudanças podem ser feitos em uma única ação.

    Acesso via terminal para usuários avançados

    Para quem utiliza o JupyterLab ou o Code Editor, a AWS manteve o acesso completo à interface de linha de comando (CLI) do Git por meio do terminal integrado. Isso garante que usuários mais avançados continuem tendo a flexibilidade do Git CLI sem abrir mão do ambiente unificado.

    Disponibilidade e migração

    O recurso está disponível em todas as regiões da AWS onde o Amazon SageMaker Unified Studio é suportado, tanto para domínios com IAM quanto para domínios com IAM Identity Center.

    Projetos que ainda utilizam a experiência anterior de Git podem migrar para o novo modelo de forma opcional, bastando atualizar as configurações do projeto. Para começar, a AWS disponibiliza a documentação Trabalhando com repositórios no Guia do Usuário e Configurando conexões Git no Guia do Administrador.

    Fonte

    Amazon SageMaker Unified Studio brings richer Git version control to all project tools (https://aws.amazon.com/about-aws/whats-new/2026/07/amazon-sagemaker-unified-studio-git/)

  • Gere Insights de Negócio com Agentes de IA e Servidores MCP no Amazon Bedrock AgentCore

    O problema clássico: dados em abundância, insights escassos

    Imagine uma gerente de produção que, toda segunda-feira antes das 10h, precisa responder a uma pergunta simples: quais linhas de montagem precisam de atenção esta semana? Para chegar a essa resposta, ela percorre o painel de Internet das Coisas (IoT), o sistema de Planejamento de Recursos Empresariais (ERP), logs de histórico, tendências de Eficiência Geral de Equipamento (OEE) e taxas de defeito — tudo em sistemas separados, com logins diferentes, sem nenhuma visão consolidada. Uma hora e meia depois, ela finalmente tem uma resposta confiável.

    Dois andares abaixo, um supervisor de linha faz o mesmo exercício com um relatório em PDF de três dias atrás. E uma técnica de manutenção que identificou uma vibração suspeita numa máquina precisa pedir os dados para o supervisor, que pede para o analista, que envia um CSV quatro horas depois. Nesse ponto, ela já passou para outra ordem de serviço.

    Três pessoas. Três níveis de acesso diferentes. Cinco sistemas desconectados. Os mesmos dados de base. Horas de costura manual, troca de contexto e espera — para respostas que deveriam levar segundos. A AWS usa exatamente esse cenário para ilustrar o problema que o Amazon Bedrock AgentCore se propõe a resolver.

    A solução: configuração, não código

    A proposta central do Amazon Bedrock AgentCore é inverter a lógica tradicional. Em vez de construir um sistema de inteligência autônoma do zero — com conectores customizados, infraestrutura de memória, lógica de orquestração e código de segurança — a empresa configura um. O Amazon Bedrock AgentCore cuida de orquestração, segurança, memória e escalabilidade. O time de negócio traz as fontes de dados e as regras.

    Fonte

    Generate Autonomous Business Insights with AI Agent and MCP Servers (https://aws.amazon.com/blogs/machine-learning/generate-autonomous-business-insights-with-ai-agent-and-mcp-servers/)

  • Automatizando fluxos de retenção de clientes com o Amazon Quick

    O problema: cinco dias é tempo demais

    Imagine perder 12% das contas em risco simplesmente porque a equipe de retenção demorou cinco dias para identificar e contatar clientes insatisfeitos. Quando alguém finalmente revisava planilhas de CSAT (Pontuação de Satisfação do Cliente, uma avaliação de 1 a 5 dada pelo cliente após cada atendimento) e transcrições de chamadas manualmente, esses clientes já tinham ido embora. Esse cenário real de uma empresa SaaS de médio porte motivou a AWS a publicar um guia completo de como o Amazon Quick pode comprimir esse ciclo de resposta de dias para minutos.

    Este post explica como funciona esse pipeline automatizado de retenção e o que você precisa para reproduzi-lo no seu ambiente.

    Visão geral da solução

    O pipeline conecta quatro componentes do Amazon Quick em sequência, cada um com uma responsabilidade clara:

    • Quick Dashboard: monitora KPIs do contact center, incluindo CSAT, FCR (Resolução no Primeiro Contato — se o problema foi resolvido em uma única chamada) e AHT (Tempo Médio de Atendimento). Identifica clientes com pontuação CSAT igual ou inferior a 2.
    • Quick Chat Agent: usa linguagem natural para consultar dados estruturados e transcrições de chamadas não estruturadas. Combina sinais quantitativos com análise de sentimento qualitativa — revelando por que um cliente está em risco, não apenas que ele está.
    • Quick Flows: transforma a análise baseada em chat em uma automação reutilizável, que pode rodar sob demanda ou em agendamento, sem intervenção manual. O resultado final é uma lista estruturada de clientes em risco que etapas subsequentes podem consumir diretamente.
    • Quick Automate: orquestra o pipeline completo em múltiplas etapas — ingere a lista de clientes em risco, pontua cada um via MCP Action customizada, ranqueia por prioridade, gera cartas de retenção personalizadas e faz upload no Amazon S3 para distribuição.

    Arquitetura do pipeline Automate

    O pipeline executa cinco etapas sequenciais:

    • Etapa 1: Download dos dados de clientes em risco e do dataset do contact center a partir do Amazon S3.
    • Etapa 2: Pontuação de retenção — cada cliente é avaliado com base no CSAT e na recência do problema, e os dois casos de maior prioridade são selecionados.
    • Etapa 3: Geração de cartas de bônus personalizadas, referenciando os problemas específicos de cada cliente.
    • Etapa 4: Criação de PDF com as cartas geradas.
    • Etapa 5: Upload dos PDFs no Amazon S3 para entrega e arquivamento.

    Pré-requisitos

    Para seguir o walkthrough, você vai precisar de:

    • Uma conta AWS com o Amazon Quick ativado (Dashboard, Chat, Flows e Automate).
    • Um dataset estruturado de contact center em formato CSV chamado contact_center_data.csv, com as colunas: customer_id, csat_score, call_date, call_reason, team_id.
    • Documentos de transcrição de chamadas chamados Call_transcripts.docx em formato PDF ou TXT.
    • Um bucket Amazon S3 para entrada e saída do pipeline (exemplo: amzn-s3-demo-bucket).

    Passo a passo da construção

    1. Preparando o Quick Space

    O Quick Space é a camada de dados que dá ao Chat Agent acesso tanto a datasets estruturados quanto a documentos não estruturados. No console do Quick, crie um Space chamado ContactSpace, adicione o dataset contact_center_data e faça upload do arquivo Call_transcripts.docx. Aguarde o status Ready aparecer para ambos antes de continuar.

    2. Criando o conector MCP Action

    Uma MCP Action é um endpoint serverless que estende o Quick Automate com lógica de negócio customizada. O MCP (Model Context Protocol) é um padrão aberto que permite que assistentes de IA como o Amazon Quick chamem ferramentas externas em um formato consistente de requisição e resposta. Consulte o guia de desenvolvedor MCP do Quick Automate para mais detalhes.

    O processo envolve três partes: criar uma função AWS Lambda com o algoritmo de pontuação, expô-la via Amazon API Gateway e registrar o endpoint no Amazon Quick.

    A função Lambda abaixo implementa um servidor MCP mínimo. Ela trata os três métodos JSON-RPC que o Amazon Quick utiliza: initialize (handshake), tools/list (anuncia a ferramenta score_customers) e tools/call (executa a pontuação quando invocada):

    import json
    
    # Tool catalog advertised to Amazon Quick during discovery (tools/list).
    # inputSchema uses JSON Schema Draft 7 (required is an array at the root).
    TOOLS = [
        {
            "name": "score_customers",
            "description": "Scores contact center customers by retention priority.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "customers": {
                        "type": "array",
                        "description": "Customer records to score.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "customer_id": {"type": "string"},
                                "csat_score": {"type": "number"},
                                "days_since_last_issue": {"type": "number"}
                            },
                            "required": ["customer_id"]
                        }
                    }
                },
                "required": ["customers"]
            }
        }
    ]
    
    def score_customers(customers):
        scored = []
        for c in customers:
            score = 0
            # Weight factors: low CSAT = high churn risk
            score += (5 - c.get("csat_score", 3)) * 20
            # Recency: issues in last 7 days score higher
            score += 30 if c.get("days_since_last_issue", 30) < 7 else 0
            scored.append({
                "customer_id": c["customer_id"],
                "retention_score": round(score, 1),
                "explanation": f"CSAT:{c.get('csat_score')}, days_since_last_issue:{c.get('days_since_last_issue')}"
            })
        scored.sort(key=lambda x: x["retention_score"], reverse=True)
        return scored
    
    def lambda_handler(event, context):
        """MCP-compliant JSON-RPC handler for customer retention scoring."""
        req = json.loads(event.get("body", "{}"))
        method = req.get("method")
        req_id = req.get("id")
    
        def rpc(result):
            return {"statusCode": 200, "headers": {"Content-Type": "application/json"},
                    "body": json.dumps({"jsonrpc": "2.0", "id": req_id, "result": result})}
    
        if method == "initialize":
            return rpc({
                "protocolVersion": "2024-11-05",
                "capabilities": {"tools": {}},
                "serverInfo": {"name": "customer-scoring", "version": "1.0.0"}
            })
        if method == "tools/list":
            return rpc({"tools": TOOLS})
        if method == "tools/call":
            params = req.get("params", {})
            if params.get("name") == "score_customers":
                args = params.get("arguments", {})
                scored = score_customers(args.get("customers", []))
                return rpc({"content": [{"type": "text", "text": json.dumps(scored)}]})
    
        return {"statusCode": 200, "headers": {"Content-Type": "application/json"},
                "body": json.dumps({"jsonrpc": "2.0", "id": req_id, "error": {"code": -32601, "message": "Method not found"}})}

    Com a função implantada, crie o endpoint via AWS CLI. Execute os comandos abaixo em ordem, substituindo os valores entre <> pelos seus próprios:

    # 1. Create REST API
    aws apigateway create-rest-api --name customer-scoring-api --endpoint-configuration types=REGIONAL
    # Note the "id" value from the response -> <API_ID>
    
    # 2. Get root resource ID
    aws apigateway get-resources --rest-api-id <API_ID>
    # Note the "id" value -> <ROOT_RESOURCE_ID>
    
    # 3. Create POST method
    aws apigateway put-method --rest-api-id <API_ID> --resource-id <ROOT_RESOURCE_ID> --http-method POST --authorization-type NONE
    
    # 4. Integrate with Lambda
    aws apigateway put-integration --rest-api-id <API_ID> --resource-id <ROOT_RESOURCE_ID> --http-method POST --type AWS_PROXY --integration-http-method POST --uri "arn:aws:apigateway:<REGION>:lambda:path/2015-03-31/functions/arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function:<LAMBDA_FUNCTION_NAME>/invocations"
    
    # 5. Allow API Gateway to invoke Lambda
    aws lambda add-permission --function-name <LAMBDA_FUNCTION_NAME> --statement-id apigateway-invoke --action lambda:InvokeFunction --principal apigateway.amazonaws.com --source-arn "arn:aws:execute-api:<REGION>:<ACCOUNT_ID>:<API_ID>/*/POST/"
    
    # 6. Deploy
    aws apigateway create-deployment --rest-api-id <API_ID> --stage-name prod
    
    # Your endpoint URL:
    # https://<API_ID>.execute-api.<REGION>.amazonaws.com/prod/mcp

    Consideração para produção: este walkthrough usa o API Gateway diretamente na frente do Lambda por simplicidade. Para cargas de trabalho em produção, a AWS recomenda usar gateways Agentcore na frente do Lambda, que oferecem autenticação, throttling e observabilidade nativos.

    Depois de obter a URL do endpoint, registre o conector no Amazon Quick: acesse More > Connectors, selecione Model Context Protocol, informe o nome mcp-customer-score, a URL do endpoint e tipo de conexão Public network. Na etapa de autenticação, selecione None (adequado para demonstração; em produção, use OAuth 2LO). Publique e aguarde o status Ready.

    3. Criando o Chat Agent personalizado

    O Chat Agent conecta o ContactSpace e o conector MCP registrado. O prompt de sistema é o componente crítico — ele instrui o agente sobre como interpretar os dados, quais perguntas fazer nas transcrições e quando invocar a ferramenta de pontuação. Crie um agente chamado Contact Center Strategy Analyst com o seguinte prompt:

    You are a Contact Center Strategy Analyst. You have access to:
    1. contact_center_data.csv - structured CSAT, call, and team data
    2. Call_transcripts.docx - unstructured call transcript documents
    3. mcp-customer-score tool - calculates retention priority scores
    
    When asked about at-risk customers:
    - Query the structured dataset for low CSAT scores
    - Cross-reference with transcripts to identify sentiment and root causes
    - When asked to score customers, call the mcp-customer-score tool
    - Always explain WHY a customer is at risk, not just that they are
    - Format results as tables when showing multiple customers

    4. Analisando clientes em risco com o Chat Agent

    Com o agente configurado, use-o para identificar e entender os clientes em risco. Comece com o prompt:

    Show me customers that rated low CSAT (at or below 2) using contact center data

    O agente retorna uma tabela com IDs de clientes, datas de chamada, pontuações CSAT e métricas relacionadas — isso identifica quem está em risco, mas não o porquê. Aprofunde com:

    Using the call transcripts, summarize the main reasons these customers were dissatisfied

    O agente lê as transcrições e resume os achados. Por exemplo, pode identificar que o Cliente 4471 expressou frustração repetida com erros de cobrança em três chamadas, enquanto o Cliente 8832 teve uma única interação intensa sobre uma interrupção de serviço. Essa distinção importa: frustrações repetidas exigem uma abordagem de retenção diferente de um único incidente grave.

    Para gerar um resultado estruturado que a automação downstream possa consumir, use o prompt final:

    For the top 20 most at-risk customers, return only a JSON array where each object has customer_id, csat_score, and days_since_last_issue (calculated from the most recent call date). Do not include any other text.

    Salve o JSON retornado como at_risk_customers.json e faça upload no seu bucket S3 (por exemplo, no prefixo inputs/).

    5. Convertendo a análise em um Quick Flow

    O Quick Flows permite transformar a conversa do chat em uma automação reutilizável com um único passo. Na interface do Chat, selecione o símbolo + na barra de ferramentas, depois Flow. Selecione Generate new flow, mantenha o prompt sugerido e clique em Generate. Após revisar, publique o Flow. Ele agora pode ser compartilhado com a equipe ou agendado para rodar semanalmente.

    6. Criando o workflow no Quick Automate

    Antes de criar o projeto de automação, é necessário criar um Automation Group — o agrupamento que define quais conectores estarão disponíveis. No Amazon Quick, acesse More > Automations, vá para a aba Groups e crie um grupo adicionando as ações necessárias: Amazon S3 (duas conexões: uma para dados de origem e outra para uploads de saída) e o agente MCP customizado criado anteriormente.

    Com o grupo criado, crie o projeto de automação associado a ele. O pipeline é construído em quatro etapas principais dentro do canvas do Automate, cada uma descrita via linguagem natural para o assistente de chat da ferramenta:

    • Etapa 1 — Carregar dados do S3: baixa o arquivo contact_center_data_complete.csv do bucket S3, lê como CSV com headers e armazena o resultado como call_data.
    • Etapa 2 — Filtrar clientes de alto risco: baixa o arquivo input/NegativeSentiment.docx do bucket S3, que contém os clientes com sentimento negativo identificados anteriormente.
    • Etapa 3 — Agregar métricas por cliente: itera sobre os resultados agregados e registra, para cada cliente, métricas como total de chamadas, CSAT médio, taxa de FCR, taxa de resolução, transferências médias, tempo médio de espera e taxa de reclamações.
    • Etapa 4 — Identificar top clientes e gerar cartas: usa um agente inline no modo "pro" para analisar as métricas agregadas e identificar os 2 clientes de maior pontuação. Para cada um, gera uma carta em HTML formatada com oferta de crédito bônus de US$ 100, converte para PDF e faz upload no S3 com o caminho output/{customer_id}{timestamp}.pdf.

    7. Testando e implantando a automação

    No canvas, use o modo Debug (ou Test) para executar o pipeline completo. Verifique nos logs se a etapa de pontuação retorna os dois clientes corretos, se as cartas referenciam os problemas específicos de cada cliente e se o upload no S3 é concluído com sucesso. Quando o resultado estiver correto, clique em Commit para criar uma versão e depois em Deploy. Para execução agendada, configure um trigger com frequência, horário de início e fuso horário na página de Deployment.

    Para mais detalhes sobre testes e implantação, consulte a documentação oficial: testando automações e implantando automações.

    Resultados observados

    Após implantar o pipeline em ambiente de teste com dados históricos de contact center, a AWS reporta melhorias em quatro dimensões — com a ressalva de que os resultados podem variar conforme a implementação:

    • Tempo de resposta: caiu de dias de identificação e redação manuais para minutos de execução automatizada.
    • Taxa de retenção: melhorou entre os clientes sinalizados em comparação com a abordagem reativa anterior. O contato mais rápido, enquanto a experiência ainda está fresca, impulsionou essa melhoria.
    • Aceitação das ofertas: aumentou quando as cartas referenciavam o problema específico do cliente em vez de oferecer um desconto genérico.
    • Tempo de implantação: menos de um dia. Usuários de negócio construíram o workflow completo via linguagem natural e interfaces point-and-click.

    Troubleshooting

    Os problemas mais comuns e suas resoluções:

    • Chat Agent retorna "No data found": indexação do Space incompleta. Verifique o status do ContactSpace e aguarde o indicador Ready antes de executar consultas.
    • Análise de sentimento genérica: transcrições não indexadas. Confirme que os documentos foram enviados para a seção Documents do Space.
    • Automação não pontua clientes ou pontua os errados: JSON de clientes em risco não encontrado, ou o agente não o recebeu. Confirme que at_risk_customers.json existe no caminho S3 referenciado e que as instruções do agente referenciam a variável baixada.
    • MCP Action retorna timeout: endpoint sem resposta. Aumente o timeout da MCP Action ou reduza o escopo do dataset.
    • Cartas genéricas ou sem detalhes do cliente: o agente gerador de cartas não recebeu os resultados da pontuação. Confirme que o prompt referencia a variável de saída da etapa de pontuação (inserida com @).

    Limpeza dos recursos

    Para evitar custos contínuos quando não precisar mais dos recursos:

    aws s3 rm s3://amzn-s3-demo-bucket/inputs/ --recursive
    aws s3 rm s3://amzn-s3-demo-bucket/output/letters/ --recursive

    Além disso, exclua o workflow do Automate, o Flow, cancele o registro do endpoint MCP Action customizado e remova os dados enviados ao ContactSpace.

    Conclusão

    O walkthrough publicado pela AWS demonstra como construir um pipeline de retenção de clientes que vai dos dados brutos do contact center até ações de retenção direcionadas — sem escrever código de aplicação. A combinação do monitoramento de KPIs via Quick Dashboard, análise de transcrições via Chat Agent, automação reutilizável via Quick Flows e processamento em múltiplas etapas via Quick Automate forma um sistema coeso e operável por usuários de negócio.

    O MCP Action connector estende o pipeline com lógica de pontuação customizada que reflete os critérios específicos de retenção de cada organização. O mesmo padrão pode ser aplicado a casos de uso adjacentes: monitoramento de saúde de contas de clientes, escalação de riscos de compliance ou recuperação proativa de serviço.

    Para explorar mais, consulte a documentação do Amazon Quick e o framework de MCP Actions.

    Fonte

    Automating customer retention workflows in Amazon Quick (https://aws.amazon.com/blogs/machine-learning/automating-customer-retention-workflows-in-amazon-quick/)

  • Autentique Agentes com Private Key JWT usando o Amazon Bedrock AgentCore Identity

    O que mudou no AgentCore Identity

    A AWS anunciou que o Amazon Bedrock AgentCore Identity agora suporta autenticação de cliente via Token Web JSON (JWT) de Chave Privada — o chamado Private Key JWT. Essa novidade muda a forma como agentes de IA se autenticam perante provedores de identidade externos, eliminando a necessidade de compartilhar segredos OAuth 2.0.

    Em vez de depender de um segredo de cliente compartilhado, o agente apresenta uma asserção JWT assinada digitalmente. A chave pública fica registrada no provedor de identidade, enquanto a chave privada correspondente permanece protegida dentro do AWS Key Management Service (KMS). O próprio AgentCore Identity solicita ao KMS que assine a asserção — sem que a chave privada precise sair do serviço em nenhum momento.

    Como o fluxo de autenticação funciona

    Para entender a mecânica, considere um agente de suporte ao cliente que precisa consultar o histórico de pedidos de um usuário em uma API interna protegida por um provedor de identidade. O fluxo acontece assim:

    • O agente chama GetResourceOauth2Token no AgentCore Identity para solicitar um token de acesso à API de pedidos.
    • O AgentCore Identity lê o ID do cliente, o ARN da chave KMS e o algoritmo de assinatura configurados no provedor de credenciais.
    • O serviço monta uma asserção JWT de curta duração com os atributos (claims) necessários e chama kms:Sign usando o algoritmo configurado — RS256, PS256 ou ES256.
    • O KMS assina a asserção e devolve apenas a assinatura. A chave privada nunca sai do KMS.
    • O AgentCore Identity envia a asserção assinada ao endpoint de token do provedor de identidade com grant_type=client_credentials e client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
    • O provedor de identidade verifica a assinatura usando a chave pública registrada e retorna um token de acesso.
    • O agente usa esse token para chamar a API de pedidos e receber os dados do cliente.

    Fluxos de concessão suportados

    A autenticação via Private Key JWT funciona com três modelos de fluxo OAuth diferentes, cobrindo os principais cenários de uso de agentes em produção.

    Máquina para máquina (M2M)

    Neste modelo, o agente age por conta própria, sem representar nenhum usuário humano. É o caso de jobs em background que sincronizam dados ou serviços que qualquer instância do agente pode acessar independentemente de quem o acionou. O token representa a identidade da aplicação ou do agente. Utiliza o fluxo client_credentials e o subject do token é o próprio cliente.

    Em nome de um usuário (On-Behalf-Of — OBO)

    Aqui, o agente age em nome de um usuário específico que já está autenticado. Existe um token de entrada do usuário, e o AgentCore Identity o troca por um token downstream que representa esse usuário — mantendo as permissões e a identidade dele na cadeia de chamadas. Dependendo do provedor de identidade, é possível usar a troca de token do RFC 8693 ou a concessão de autorização JWT do RFC 7523.

    Acesso delegado pelo usuário

    Neste cenário, não há token de entrada para trocar. O usuário passa por um fluxo interativo de login e consentimento — o fluxo de código de autorização OAuth de três pernas — aprovando explicitamente o que o agente pode fazer. Após o consentimento, o agente recebe um token que representa o usuário. Utiliza o fluxo authorization_code.

    Pré-requisitos

    Para seguir a configuração, a AWS indica que você precisa de:

    • Uma conta AWS com acesso ao Console de Gerenciamento para o KMS, o AgentCore e o AWS CloudTrail.
    • Um tenant no seu provedor de identidade onde seja possível registrar uma chave pública para uma aplicação.
    • URL de descoberta e ID de cliente do provedor de identidade.
    • Confirmação do algoritmo de assinatura exigido pelo provedor e verificação de que ele é suportado pelo KMS e pelo AgentCore Identity.
    • Permissões IAM: kms:CreateKey e kms:PutKeyPolicy para criar a chave; kms:GetPublicKey para exportar a chave pública; bedrock-agentcore-control:CreateOauth2CredentialProvider para criar o provedor de credenciais. Se o provedor de identidade gerar o par de chaves e fornecer o material da chave privada, também serão necessárias kms:GetParametersForImport e kms:ImportKeyMaterial para importar a chave no KMS.

    Passo a passo: configurando o Private Key JWT

    Passo 1 — Criar a chave de assinatura no KMS e registrar a chave pública

    O primeiro passo é criar uma chave KMS assimétrica que o AgentCore Identity usará para assinar as asserções JWT. Abra o console do AWS KMS na mesma região AWS do seu provedor de credenciais. Em Customer managed keys, escolha Create key e configure:

    • Key type: Asymmetric
    • Key usage: Sign and verify
    • Key spec: compatível com o algoritmo de assinatura desejado (o exemplo da AWS usa ECC_NIST_P256 com o algoritmo ES256)

    Na etapa de política da chave, adicione o seguinte statement para conceder ao AgentCore Identity permissão de uso — substituindo 111122223333 pelo ID da sua conta AWS e <region> pela região em uso. A condição kms:ViaService garante que a chave só pode ser usada quando a requisição vier do AgentCore Identity:

    {
      "Id": "BedrockAgentCoreIdentityPrivateKeyJwtAccess",
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::111122223333:root"
          },
          "Action": [
            "kms:Sign",
            "kms:DescribeKey"
          ],
          "Resource": "*",
          "Condition": {
            "StringEquals": {
              "aws:ResourceAccount": "${aws:PrincipalAccount}"
            },
            "StringLike": {
              "kms:ViaService": "bedrock-agentcore-identity.<region>.amazonaws.com"
            }
          }
        }
      ]
    }

    Após criar a chave, anote o ARN — ele será necessário na configuração do provedor de credenciais. Em seguida, acesse a aba Public key da chave e faça o download da chave pública. O KMS fornece a chave em formato DER. Converta-a para o formato exigido pelo seu provedor de identidade (por exemplo, um certificado X.509 para o Microsoft Entra ID ou uma JSON Web Key para o Okta) e registre-a na sua aplicação.

    Passo 2 — Adicionar um cliente OAuth no AgentCore Identity

    Abra o console do Amazon Bedrock AgentCore. No painel de navegação esquerdo, em Build, acesse Identity. Na seção Outbound Auth, escolha Add Outbound Auth e depois Add OAuth client.

    Passo 3 — Selecionar Private Key JWT como método de autenticação

    Na página de adição do cliente OAuth, na seção Provider configurations, configure o Configuration type como Discovery URL para que o AgentCore Identity recupere automaticamente a configuração do provedor. Em Client authentication method, selecione Private key JWT.

    Passo 4 — Informar URL de descoberta, ID do cliente, chave KMS e algoritmo

    • Discovery URL: a URL onde o provedor publica sua configuração OpenID Connect (terminando em .well-known/openid-configuration).
    • Client ID: o identificador do cliente registrado no provedor de identidade.
    • KMS key: o ARN da chave KMS assimétrica criada anteriormente. A chave deve ter sido criada com uso SIGN_VERIFY e estar na mesma região. Também é possível usar uma chave de outra conta na mesma região informando o ARN diretamente — nesse caso, são necessárias permissões adicionais em ambas as contas. Veja a documentação sobre como permitir que usuários de outras contas usem uma chave KMS.
    • Signing algorithm: o algoritmo exigido pelo seu provedor de identidade, compatível com o key spec da chave KMS.

    Passo 5 — (Opcional) Adicionar claims customizados

    Se o seu provedor de identidade exigir claims adicionais na asserção JWT, é possível adicioná-los nesta etapa. Em Header claims, adicione claims de cabeçalho específicos do provedor (como um identificador de chave). As chaves reservadas alg e typ não podem ser definidas. Em Payload claims, adicione claims de payload específicos do provedor. As chaves reservadas iss, sub, jti, exp, iat e nbf não podem ser definidas. Por fim, clique em Add OAuth Client e confirme que o provedor de credenciais aparece na lista de Outbound Auth.

    Auditoria com CloudTrail

    Toda vez que um agente usa o provedor de credenciais para buscar um token, as operações ficam registradas no AWS CloudTrail. Os principais eventos que você verá são:

    GetWorkloadAccessToken (fonte: bedrock-agentcore.amazonaws.com) — o agente obtém seu token de identidade de workload. O token retornado é ocultado por razões de segurança:

    {
      "eventSource": "bedrock-agentcore.amazonaws.com",
      "eventName": "GetWorkloadAccessToken",
      "requestParameters": {
        "workloadName": "my-agent-workload"
      },
      "responseElements": {
        "workloadAccessToken": "HIDDEN_DUE_TO_SECURITY_REASONS"
      },
      "resources": [
        {
          "accountId": "111122223333",
          "type": "AWS::BedrockAgentCore::WorkloadIdentity",
          "ARN": "arn:aws:bedrock-agentcore:us-east-1:111122223333:workload-identity-directory/default/workload-identity/my-agent-workload"
        }
      ]
    }

    GetResourceOauth2Token (fonte: bedrock-agentcore.amazonaws.com) — o agente solicita um token de acesso para o recurso downstream. Os parâmetros mostram qual provedor de credenciais, escopos e fluxo OAuth foram usados:

    {
      "eventSource": "bedrock-agentcore.amazonaws.com",
      "eventName": "GetResourceOauth2Token",
      "requestParameters": {
        "workloadIdentityToken": "HIDDEN_DUE_TO_SECURITY_REASONS",
        "resourceCredentialProviderName": "my-private-key-jwt-provider",
        "scopes": [
          "https://graph.microsoft.com/.default"
        ],
        "oauth2Flow": "M2M"
      },
      "resources": [
        {
          "accountId": "111122223333",
          "type": "AWS::BedrockAgentCore::OAuth2CredentialProvider",
          "ARN": "arn:aws:bedrock-agentcore:us-east-1:111122223333:token-vault/default/oauth2credentialprovider/my-private-key-jwt-provider"
        }
      ]
    }

    Sign (fonte: kms.amazonaws.com) — o AgentCore Identity assina a asserção JWT com a chave KMS. Este é o evento que comprova o funcionamento do Private Key JWT: os campos userIdentity.invokedBy, sourceIPAddress e userAgent são todos bedrock-agentcore.amazonaws.com, confirmando que foi o AgentCore Identity quem chamou o kms:Sign. Note que o evento registra o nome do algoritmo de assinatura do KMS, não o nome do algoritmo JWT configurado:

    {
      "eventSource": "kms.amazonaws.com",
      "eventName": "Sign",
      "userIdentity": {
        "invokedBy": "bedrock-agentcore.amazonaws.com"
      },
      "sourceIPAddress": "bedrock-agentcore.amazonaws.com",
      "userAgent": "bedrock-agentcore.amazonaws.com",
      "requestParameters": {
        "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_256",
        "keyId": "arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
        "messageType": "DIGEST"
      },
      "responseElements": null,
      "readOnly": true,
      "managementEvent": true,
      "resources": [
        {
          "accountId": "111122223333",
          "type": "AWS::KMS::Key",
          "ARN": "arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
        }
      ]
    }

    Limpando os recursos criados

    Para evitar cobranças desnecessárias e remover recursos que não serão mais usados, a AWS recomenda os seguintes passos:

    Remover o provedor de credenciais OAuth

    Abra o console do Amazon Bedrock AgentCore, acesse Identity no painel de navegação e localize o provedor criado na seção Outbound Auth. Selecione o provedor, escolha Delete e confirme a exclusão.

    Agendar a exclusão da chave KMS

    A exclusão de uma chave KMS é irreversível. Por isso, o KMS exige que você agende a exclusão com um período de espera em vez de excluir imediatamente. Antes de agendar, confirme que a chave não está mais referenciada por nenhum provedor de credenciais ou registro de provedor de identidade. Se não tiver certeza se a chave ainda está em uso, considere desativar a chave — o que impede seu uso mas mantém a possibilidade de recuperação.

    Abra o console do AWS KMS na região onde a chave foi criada. Em Customer managed keys, selecione a chave assimétrica criada. Em Key actions, escolha Schedule key deletion e defina um período de espera entre 7 e 30 dias. Durante esse período, a chave fica desativada mas pode ser recuperada cancelando a exclusão agendada. Após o período, o KMS a exclui permanentemente. Lembre-se também de remover ou rotacionar a chave pública registrada no provedor de identidade.

    Conclusão

    Com o suporte a Private Key JWT no AgentCore Identity, a AWS oferece aos desenvolvedores uma forma sem segredos compartilhados e totalmente auditável de autenticar agentes em provedores de identidade externos. A chave privada permanece no KMS, cada operação de assinatura fica registrada no CloudTrail, e o mesmo provedor de credenciais cobre os fluxos M2M, on-behalf-of e de acesso delegado pelo usuário.

    Para exemplos completos — incluindo registro em provedores como Entra e Okta, além de fluxos M2M e OBO — a AWS disponibilizou os samples do Amazon Bedrock AgentCore no GitHub.

    Fonte

    Authenticate with Private Key JWT using Amazon Bedrock AgentCore Identity (https://aws.amazon.com/blogs/machine-learning/authenticate-with-private-key-jwt-using-amazon-bedrock-agentcore-identity/)

  • AWS WAF adiciona transformações de texto pré-parse e novas opções de normalização

    O que foi anunciado

    A AWS expandiu as capacidades do AWS WAF (Web Application Firewall — Firewall de Aplicações Web) com dois conjuntos de novidades: as transformações de texto pré-parse para argumentos de consulta e dez novas transformações de texto disponíveis para qualquer declaração de regra. Ambas as funcionalidades têm o mesmo objetivo central: garantir que o AWS WAF inspecione as requisições da mesma forma que a sua aplicação as interpreta.

    Transformações pré-parse: o que são e por que importam

    Antes de o AWS WAF dividir uma query string (string de consulta) em pares de chave-valor, agora é possível aplicar transformações sobre o texto bruto dessa string. Isso fecha duas categorias importantes de brecha de segurança:

    • HTTP Parameter Pollution (Poluição de Parâmetros HTTP): técnica em que um atacante envia parâmetros duplicados para confundir a aplicação ou o WAF.
    • Parser differential evasion (Evasão por diferença de parser): quando o WAF e a aplicação interpretam a mesma string de formas diferentes, criando uma janela de evasão.

    Com as transformações pré-parse, é possível encadear até dez transformações em sequência — por exemplo, decodificação de URL, combinação de argumentos de consulta duplicados por vírgula e substituição de ponto e vírgula por &. Depois disso, ainda é possível empilhar as transformações pós-parse tradicionais dentro da mesma declaração de regra, tudo em uma única configuração.

    Dez novas transformações de texto

    Além das transformações pré-parse, a AWS também introduziu dez novas opções de normalização de conteúdo, disponíveis para uso em qualquer regra do WAF. Entre elas estão opções consideradas padrão do setor, como:

    • Uppercase — conversão para letras maiúsculas
    • Trim — remoção de espaços nas extremidades
    • Remove Whitespace — remoção de espaços em branco
    • SHA256 — geração de hash SHA256 do conteúdo

    O conjunto também inclui funções de decodificação de linha de comando com consciência de sistema operacional e decodificação de JavaScript, desenvolvidas pelo Amazon Threat Research Team (Equipe de Pesquisa de Ameaças da Amazon).

    Custo e disponibilidade

    Cada nova transformação consome 10 WCUs (Web ACL Capacity Units — Unidades de Capacidade de Web ACL). Não há cobrança adicional além do preço padrão do AWS WAF, e o recurso já está disponível em todas as regiões da AWS.

    Como começar

    Para quem quiser explorar as novidades, a AWS disponibilizou documentação detalhada sobre cada funcionalidade:

    Fonte

    AWS WAF adds pre-parse text transformations and new text transformations (https://aws.amazon.com/about-aws/whats-new/2026/07/aws-waf/)

  • AWS Glue adiciona suporte a VPC, filter pushdown e particionamento no conector REST API

    O que foi anunciado

    A AWS anunciou três novas capacidades para o conector de Interface de Programação de Aplicações REST (REST API) do AWS Glue: suporte a Nuvem Privada Virtual (VPC), filter pushdown e particionamento de dados. Juntas, essas melhorias tornam os pipelines de Extração, Transformação e Carga (ETL) com fontes REST muito mais seguros, eficientes e escaláveis — sem a necessidade de escrever código personalizado.

    Contexto: o conector REST API do AWS Glue

    O conector REST API do AWS Glue permite ingerir dados de qualquer fonte que exponha uma API baseada em REST, incluindo sistemas proprietários e plataformas emergentes que ainda não possuem conectores nativos no serviço. Com as novidades anunciadas, esse conector passa a cobrir três lacunas importantes que limitavam seu uso em ambientes corporativos mais exigentes.

    As três novas capacidades

    Suporte a VPC

    Com o suporte à VPC, o conector REST API agora consegue acessar fontes de dados hospedadas em sub-redes privadas ou conectadas via VPN ou AWS PrivateLink, sem expor o tráfego à internet pública. Isso é especialmente relevante para organizações que mantêm sistemas internos isolados por questões de segurança e conformidade, e que precisam integrá-los a pipelines de dados na AWS sem abrir brechas de rede.

    Filter Pushdown

    O filter pushdown traduz os predicados de consulta diretamente em parâmetros nativos da API, fazendo com que apenas os registros correspondentes ao filtro sejam transferidos da fonte. Na prática, isso significa menos dados trafegando pela rede, redução de custos de transferência e melhor desempenho geral dos jobs do Glue — já que o trabalho de filtragem acontece na origem, não após a ingestão.

    Suporte a Particionamento

    O particionamento divide grandes conjuntos de dados entre múltiplos workers do Spark, utilizando estratégias baseadas em campos ou contagem de registros. O resultado são leituras paralelas que reduzem significativamente o tempo de ingestão em APIs paginadas e de alto volume. Para quem lida com grandes volumes de dados via REST, essa funcionalidade pode representar uma mudança expressiva na performance dos pipelines.

    Disponibilidade

    Todas essas capacidades já estão disponíveis em todas as regiões comerciais da AWS onde o AWS Glue está presente. Para começar a utilizá-las, a AWS recomenda consultar a documentação oficial do conector REST API do AWS Glue.

    Fonte

    AWS Glue announces VPC support, filter pushdown, and partition support for the REST API connector (https://aws.amazon.com/about-aws/whats-new/2026/07/aws-glue-rest-connector-filtering-partitioning-vpc)

  • Como proteger atualizações de pacotes npm e pip no Amazon Linux

    O problema: os primeiros momentos após a publicação são os mais arriscados

    Quem trabalha com desenvolvimento em Amazon Linux e utiliza pacotes do npm ou do PyPI precisa estar atento a um risco específico: o período logo após a publicação de um pacote é, de longe, o mais perigoso do ponto de vista de segurança na cadeia de suprimentos.

    Diferente dos pacotes oficiais do Amazon Linux — que passam por revisão dos mantenedores antes do lançamento —, os registros npm e PyPI têm publicação aberta. Qualquer pessoa pode enviar um pacote sem passar por revisão humana obrigatória. Isso abre espaço para que pacotes maliciosos sejam publicados por meio de credenciais roubadas ou ataques de impersonação.

    O padrão observado nesses incidentes é sempre parecido: um autor publica um pacote ou versão inesperada e aguarda que sistemas automatizados e usuários o instalem. Pesquisadores de segurança e scanners automatizados geralmente detectam e removem esses pacotes em questão de horas — mas, nesse intervalo, muitos ambientes já foram expostos.

    O relatório State of DevSecOps 2026 da Datadog revelou que 54% das aplicações JavaScript instalam ao menos uma dependência dentro de um dia após seu lançamento. Esse é exatamente o janela de maior risco. Veja alguns exemplos reais de eventos recentes e seus tempos de exposição:

    • Nx s1ngularity (ago/2025): 4–5 horas
    • axios (mar/2026): 2–3 horas
    • Bitwarden CLI (abr/2026): 93 minutos
    • TanStack (mai/2026): 30 minutos
    • node-ipc (mai/2026): menos de 24 horas

    Um detalhe importante: vários desses eventos geraram atestados de proveniência válidos e passaram em verificações de build. Ou seja, os mecanismos de autorização tradicionais não foram suficientes para bloqueá-los.

    A tensão entre dois tipos de risco

    Existe uma tensão natural entre dois riscos que puxam em direções opostas. Por um lado, manter pacotes desatualizados significa acumular vulnerabilidades conhecidas que nunca foram corrigidas. Por outro, instalar versões recém-publicadas significa correr o risco de incluir código malicioso que ainda não foi detectado.

    Figura 1: Risco de software ao longo do tempo. O risco de vulnerabilidades não corrigidas cresce com o tempo, enquanto o risco de ataques à cadeia de suprimentos é mais alto logo após a publicação — Imagem original — fonte: Aws

    A melhor abordagem, portanto, é se manter atualizado sem adotar versões imediatamente após o lançamento, aplicando correções de segurança recomendadas conforme necessário. É exatamente esse equilíbrio que a solução de cooldown de dependência busca oferecer.

    A solução: cooldown de dependência com uma linha de configuração

    A AWS apresentou uma solução direta: configurar um cooldown de dependência nos gerenciadores de pacotes npm e pip. Essa configuração instrui o gerenciador a ignorar versões publicadas há menos de 24 horas. Se um pacote não existia no registro pelo tempo configurado, ele simplesmente não será instalado — dando à comunidade de segurança tempo suficiente para identificar e remover versões problemáticas.

    Um cooldown de 1 dia teria bloqueado todos os eventos listados na tabela acima. E, ao contrário dos mecanismos de autorização, o cooldown funciona de forma independente: ele bloqueia por idade, não por confiança.

    Tanto o npm (versão 11.10.0 ou superior) quanto o pip (versão 26.1 ou superior) já suportam essa funcionalidade. O Amazon Linux 2023 inclui esses pacotes a partir do NodeJS 24 e Python 3.14, disponíveis desde a versão 2023.11.20260608.

    Observação importante: se você utiliza instalações baseadas em lockfile — como npm ci ou pip install -r requirements.txt com versões fixadas — o cooldown não se aplica. Esses comandos instalam exatamente o que o lockfile especifica, independentemente da idade do pacote. O cooldown afeta apenas a resolução de pacotes novos ou atualizados.

    Pré-requisitos

    • Node.js 24 com npm 11.10.0 ou superior (em nodejs24-24.14.1-1.amzn2023.0.1 ou posterior)
    • Python 3.14 com pip 26.1 (em python3.14-pip-26.1.1-1.amzn2023.0.1 ou posterior)
    • pip-audit (ferramenta para escanear pacotes Python com defeitos conhecidos). Instale com: python3.14 -m pip install pip-audit

    Como configurar o cooldown no npm

    Crie o diretório de configuração global conforme a versão do NodeJS:

    sudo mkdir -p /usr/lib/nodejs24/etc

    Adicione a configuração de cooldown:

    sudo npm-24 config set min-release-age 1 --location=global

    Verifique se o cooldown está ativo:

    npm-24 config list

    A saída mostrará before = "<timestamp de 24 horas atrás>", confirmando que o npm converteu o cooldown de 1 dia em um filtro de data. Consulte a documentação do npm min-release-age para mais detalhes.

    Como configurar o cooldown no pip

    Crie o arquivo de configuração global do pip com o cooldown:

    sudo python3.14 -m pip config set --global global.uploaded-prior-to P1D

    Verifique a configuração:

    python3.14 -m pip config list

    A saída mostrará global.uploaded-prior-to='P1D'. Essa configuração pode ser aplicada imediatamente com segurança, pois versões mais antigas do pip (25.x) simplesmente ignoram o parâmetro sem causar erros.

    Sobrescrevendo o cooldown para aplicar correções de segurança urgentes

    O cooldown não precisa ser desativado completamente para aplicar correções de segurança. A recomendação da AWS é identificar os pacotes com vulnerabilidades conhecidas por meio das ferramentas de auditoria e sobrescrever o cooldown apenas para esses pacotes específicos.

    Para identificar pacotes que precisam de atualização urgente, execute:

    npm auditor
    python3.14 -m pip_audit

    Para pacotes npm

    Instale um pacote específico ignorando o cooldown:

    npm-24 install <package-name> --min-release-age=0

    Para atualizar automaticamente todos os pacotes npm com vulnerabilidades conhecidas:

    npm audit --json | python3 -c "
    import json, sys, subprocess
    data = json.load(sys.stdin)
    for pkg in data.get('vulnerabilities', {}):
        subprocess.run(['npm-24', 'install', f'{pkg}@latest', '--min-release-age=0'])
    "

    Para pacotes pip

    Instale um pacote específico ignorando o cooldown:

    python3.14 -m pip install <package-name> --uploaded-prior-to="P0D"

    Para atualizar automaticamente todos os pacotes pip com vulnerabilidades conhecidas:

    python3.14 -m pip_audit --format=json | python3 -c "
    import json, sys, subprocess
    data = json.load(sys.stdin)
    for vuln in data:
        pkg = vuln['name']
        fix = vuln.get('fix_versions', ['latest'])[0]
        subprocess.run(['python3.14', '-m', 'pip', 'install', f'{pkg}=={fix}', '--uploaded-prior-to=\"P0D\"'])
    "

    Importante: os scripts acima demonstram o conceito. Para uso em produção, adicione tratamento de erros, logging e testes adequados. Revise os pacotes antes de atualizá-los em pipelines automatizados.

    Adoção da indústria: cooldowns já são tendência

    A estratégia de cooldown de dependência já está sendo adotada por ferramentas e empresas relevantes do ecossistema. A partir de maio de 2026, diversas ferramentas populares passaram a incluir esse recurso:

    • pnpm 11: já vem com minimumReleaseAge habilitado por padrão — um dos primeiros gerenciadores de pacotes a tornar o cooldown opt-out em vez de opt-in.
    • Renovate: o preset config best-practices inclui um cooldown de 3 dias para npm desde 2025, amplamente adotado em empresas.
    • StepSecurity Secure Registry: oferece período de cooldown configurável para clientes corporativos, com recomendação padrão de 10 dias.

    Como a AWS contribui para a segurança da cadeia de suprimentos open source

    A AWS também atua de forma proativa no monitoramento dos registros de pacotes. O Amazon Inspector, serviço de gerenciamento de segurança que escaneia continuamente cargas de trabalho em busca de vulnerabilidades e exposições de rede, utiliza regras de detecção assistidas por Inteligência Artificial (IA) para monitorar registros upstream de pacotes.

    Em 2025, pesquisadores do Amazon Inspector identificaram mais de 150.000 pacotes npm inesperados vinculados a uma campanha de mineração de tokens. A equipe de segurança da AWS também publicou orientações detalhadas de resposta ao worm Shai-Hulud e ao evento do axios.

    Além disso, a AWS contribui com a Open Source Security Foundation (OpenSSF) por meio de um grant de US$ 12,5 milhões para segurança open source, financiando infraestrutura de escaneamento proativo que beneficia todo o ecossistema.

    Pacotes inesperados normalmente são detectados em poucas horas após a publicação. Um cooldown de 1 dia garante que você não os instale durante essa janela de detecção.

    Recomendações práticas

    Para proteger seu ambiente Amazon Linux 2023, a AWS recomenda:

    • Configure um cooldown de 1 dia para npm e pip conforme os passos descritos acima. Registros externos não têm revisão humana — dê tempo aos defensores para identificar problemas.
    • Sobrescreva o cooldown quando necessário para aplicar correções de segurança urgentes, usando as flags por comando.
    • Execute npm audit ou pip_audit regularmente para identificar pacotes que precisam de atenção imediata.

    Recursos adicionais

    Fonte

    Secure your npm and pip package updates in Amazon Linux (https://aws.amazon.com/blogs/security/secure-your-npm-and-pip-package-updates-in-amazon-linux/)

  • A Amazon identifica grupo norte-coreano por trás de ataques à cadeia de suprimentos de software open source

    Um grupo, múltiplos alvos: a conexão que ninguém havia feito antes

    A Amazon divulgou uma pesquisa inédita revelando que vários comprometimentos recentes de pacotes populares do Gerenciador de Pacotes Node (NPM — Node Package Manager) foram conduzidos pelo mesmo grupo de ameaças vinculado à Coreia do Norte — o país oficialmente conhecido como República Popular Democrática da Coreia (RPDC). A conexão entre esses incidentes não havia sido reportada publicamente até agora.

    O grupo em questão é rastreado pela comunidade de segurança sob vários nomes: SAPPHIRE SLEET, STARDUST CHOLLIMA, BlueNoroff, CageyChameleon e Alluring Pisces. Segundo a análise da Amazon Threat Intelligence, esse ator de ameaças está por trás dos comprometimentos das bibliotecas axios, debug, chalk e typo-crypto — pacotes amplamente utilizados no ecossistema JavaScript.

    O relatório também aborda como a IA generativa já está mudando a aparência de pacotes maliciosos e como atores de ameaças estão começando a sondar sistemas de revisão de código baseados em IA.

    A linha do tempo dos ataques

    A sequência de comprometimentos documentada pela Amazon Threat Intelligence revela uma operação metódica e progressiva:

    • Março de 2025: comprometimento do pacote typo-crypto — considerado um teste inicial de técnicas.
    • Setembro de 2025: o mesmo ator compromete os pacotes debug e chalk.
    • Março de 2026: o mesmo manual operacional reaparece no comprometimento do axios, uma das bibliotecas JavaScript mais usadas no mundo, com mais de 100 milhões de downloads semanais.

    Em todos os casos, o grupo obteve acesso por meio de engenharia social contra mantenedores confiáveis dos pacotes, publicando em seguida uma atualização contendo código malicioso. Qualquer organização que atualizasse automaticamente para a versão mais recente recebia o pacote comprometido.

    Embora o comprometimento do axios já tivesse sido atribuído publicamente a esse ator, os incidentes com typo-crypto, debug e chalk nunca haviam sido conectados a ele. A Amazon Threat Intelligence identificou Táticas, Técnicas e Procedimentos (TTPs — Tactics, Techniques and Procedures) compartilhados entre as campanhas, incluindo pacotes NPM trojanizados, uso de hooks pós-instalação e reuso de código.

    A motivação é financeira: ao comprometer um número pequeno de pacotes altamente populares, o grupo obtém acesso potencial a milhares de ambientes downstream simultaneamente — muito mais eficiente do que atacar organizações uma a uma. Segundo dados da Wiz Research citados no relatório, cerca de 1 em cada 10 ambientes de nuvem foram afetados pelo evento das bibliotecas debug e chalk em uma janela de apenas duas horas.

    A campanha menor que veio antes

    Durante a análise de indicadores relacionados ao caso do axios, a Amazon Threat Intelligence identificou uma conexão com um domínio registrado em 2025, o que levou a uma investigação mais ampla. Essa investigação revelou que o mesmo ator havia inserido um arquivo trojanizado no pacote typo-crypto em março de 2025.

    O arquivo malicioso, chamado core.js, se disfarça como o legítimo pacote core-js dentro do repositório do typo-crypto. Dado o baixo volume de downloads observado, a Amazon Threat Intelligence avalia que essa campanha foi de pequena escala — provavelmente um campo de testes para as operações maiores que viriam depois.

    O comportamento técnico do malware é detalhado no relatório:

    • O arquivo trojanizado é executado quando recebe um hash iniciando com o valor 0098273.
    • Quando ativado, baixa um payload de segundo estágio de um servidor de Comando e Controle (C2) hardcoded.
    • Executa o payload de acordo com o sistema operacional da vítima: Windows, macOS ou Linux.
    • Implementa persistência baseada em arquivos com rotação de payload.
    • Usa ofuscação em múltiplas camadas, combinando texto codificado em base64 com cifra XOR com chave 01042025.

    Os indicadores de comprometimento (IoCs) associados incluem:

    • Domínio: npmjs[.]store
    • Endereço IP: 216[.]74[.]123[.]126
    • Pacote NPM: typo-crypto (SHA256: 24604384b0e748ada07923630b3d037489e696284a98c4409fb9b6763565571f)
    • Arquivo trojanizado: core.js (SHA256: 2014d09c7ded74d89c885b5f11693865224116f1b25df9330e61fe528f419d73)

    O malware foi reportado ao banco de dados de Vulnerabilidades Open Source (Vulnerabilidades Open Source), onde é rastreado como MAL‑2026‑3400.

    Como as técnicas de ataque estão evoluindo

    A Amazon Threat Intelligence e o Amazon Inspector documentaram uma série de mudanças nas táticas usadas para atacar bibliotecas open source. Cada padrão foi projetado para explorar a lacuna entre o momento em que uma dependência é inspecionada e o momento em que ela efetivamente executa.

    De ataques por pacote para ataques por fragmento

    Antes, um pacote malicioso concentrava todo o comportamento suspeito em si mesmo. Agora, os atacantes estão dividindo um único fluxo malicioso em vários pacotes de aparência inofensiva: um armazena um blob criptografado disfarçado de configuração; outro contém a lógica de descriptografia; um terceiro, publicado depois, busca e executa o payload. Analisado individualmente, cada pacote parece benigno. O comportamento malicioso só emerge quando os componentes são usados juntos na sequência correta.

    Campanhas de longo prazo que investem em confiança

    Em vez de publicar malware óbvio, os atacantes publicam algo genuinamente útil e o mantêm por semanas ou meses — corrigindo bugs, adicionando funcionalidades, acumulando dependentes. Em alguns casos, o objetivo nem é lançar um novo pacote, mas se tornar um contribuidor de um projeto existente. Esse foi o fio condutor do backdoor do XZ Utils até os comprometimentos dos mantenedores do debug, chalk e axios: o adversário trata a legitimidade como um ativo a ser gasto uma única vez, no momento de acesso máximo.

    Desacoplando o pacote do seu comportamento

    Em muitos casos recentes, uma biblioteca está limpa no registro público, mas ainda é perigosa — porque seu comportamento real depende de recursos controlados pelo atacante em outro lugar: scripts buscados de repositórios externos em tempo de execução, arquivos de configuração que ativam certos comportamentos, ou endpoints remotos consultados na inicialização. Enquanto esses recursos externos permanecem benignos, revisões de código passam e varreduras automatizadas retornam resultados limpos. Quando o atacante “arma” o endpoint, cada cópia instalada pode se tornar maliciosa de uma vez, sem nenhuma nova versão do pacote.

    Da ofuscação básica à criptografia real

    Onde antes os atacantes usavam minificação ou base64 simples, hoje se observam payloads em múltiplos estágios com técnicas criptográficas mais robustas: blobs criptografados com AES‑GCM, arrays de strings no estilo RC4, XOR em camadas sobre base64, e loaders nativos que mantêm o próximo estágio como campo criptografado descriptografado apenas em memória. O design comum é que a chave de descriptografia nunca está armazenada no pacote — ela é derivada do contexto de execução, buscada de um servidor ou fornecida como uma chave de licença.

    Payloads que evitam detonar em sandboxes

    À medida que os defensores escalaram a análise automatizada em sandboxes de nuvem, os atacantes tornaram seu código mais consciente do ambiente. O payload verifica se está sendo analisado antes de agir: terminais interativos, nomes de usuário e hostnames realistas, participação em domínio, uptime plausível, histórico de arquivos locais, sistemas operacionais específicos e metadados de nuvem que distinguem infraestrutura de análise de cargas de trabalho normais. Alguns servidores de entrega também adaptam o que servem com base no cliente — um decoy benigno vai para requisições genéricas, enquanto o payload real só aparece para o user agent exato usado pelo malware.

    Como a IA generativa está mudando o cenário

    A IA generativa está alterando tanto o que os atacantes conseguem produzir quanto o que os defensores podem confiar como sinal de detecção.

    Historicamente, muitos pacotes maliciosos eram detectados porque pareciam errados: linguagem quebrada, documentação rasa, cópia e cola óbvios, ou funções reutilizadas entre amostras. A IA generativa apaga muitos desses sinais. Atacantes podem agora produzir milhares de linhas de código coerente e idiomático, bem comentado, com documentação convincente, históricos de commits plausíveis e identidades sintéticas de mantenedores — tudo envolvendo um backdoor. Como cada variante pode ser mutada, renomeada, reestruturada e re-criptografada, não há assinatura estável para corresponder.

    A IA também está criando novos vetores de acesso inicial. Uma técnica emergente é o slopsquatting: atacantes registram nomes de pacotes que existem apenas porque um assistente de codificação com IA os alucineu. Quando um desenvolvedor — ou um agente autônomo — pede ajuda e o modelo recomenda com confiança um pacote inexistente, o atacante pode ter pré-registrado esse nome e estar esperando. A próxima pessoa que seguir a recomendação pode receber malware, sem ter digitado nada errado ou visitado um site malicioso.

    Mais significativamente: atacantes não estão mais apenas escrevendo malware para humanos deixarem passar. Estão escrevendo malware para sistemas de IA aprovarem. À medida que organizações dependem de IA para revisar código e triar pacotes, esses sistemas de IA se tornam parte da superfície de ataque. A Amazon espera que a injeção indireta de prompt — uma técnica onde instruções ocultas manipulam um sistema de IA a tomar ações não intencionais — seja cada vez mais incorporada em pacotes maliciosos para enganar scanners baseados em IA. Essas instruções podem estar escondidas em comentários de código, arquivos README, docstrings ou fixtures de teste.

    O que a AWS está fazendo a respeito

    A Amazon Web Services (AWS) afirma estar investindo em Amazon Threat Intelligence e Amazon Inspector para ajudar clientes a se adaptarem a esse cenário em constante mudança.

    Após descobrir a campanha, a Amazon Threat Intelligence trabalhou com o Amazon Inspector para que o pacote malicioso fosse rastreado, mitigado e compartilhado com a comunidade pelo banco de dados OSV. Os indicadores observados também foram compartilhados com o Amazon GuardDuty para alertar clientes sobre essa atividade.

    O Amazon Inspector usa esses insights para refinar a lógica de detecção, ampliar a cobertura em registros de pacotes e priorizar sinais que refletem as mudanças de técnica descritas no relatório. A empresa também está colaborando com parceiros do setor, como registros de pacotes e a Open Source Security Foundation (OpenSSF).

    Em 2026, a AWS se juntou à Linux Foundation e outros líderes do setor para lançar o Akrites, uma iniciativa colaborativa para defender software open source crítico contra ameaças cibernéticas habilitadas por IA. A AWS também co-investiu US$ 12,5 milhões junto a outras organizações para defender o ecossistema open source de ataques impulsionados por IA.

    O que isso significa para equipes de segurança

    O relatório da Amazon deixa claro que a segurança da cadeia de suprimentos de software open source exige uma mudança de mentalidade. Não basta escanear pacotes individualmente: é preciso raciocinar sobre como eles interagem em um grafo de dependências real. Um pacote que não mostra comportamento malicioso hoje não é o mesmo que um pacote seguro por design.

    A paciência dos atacantes — investindo meses em construir confiança antes de agir — e a capacidade de usar IA para gerar malware convincente tornam as abordagens tradicionais de detecção cada vez menos eficazes. O setor como um todo, e não apenas os provedores de nuvem, precisa adaptar suas defesas a esse novo cenário.

    Fonte

    Amazon identifies North Korean hacker group behind open-source supply chain attacks (https://aws.amazon.com/blogs/security/amazon-identifies-north-korean-hacker-group-behind-open-source-supply-chain-attacks/)

  • Agentes de vigilância de mercado com LangGraph e Strands no AgentCore

    Por que sistemas com um único agente não são suficientes

    À medida que aplicações de IA avançam além dos chatbots tradicionais, as equipes de engenharia se deparam com um problema concreto: fluxos de trabalho corporativos complexos exigem expertise especializada, decisões dinâmicas e mecanismos robustos de recuperação de falhas — e um único agente raramente dá conta de tudo isso.

    O setor financeiro é um exemplo claro. Sistemas de vigilância de mercado precisam coordenar múltiplos agentes especializados para analisar padrões de negociação, investigar atividades suspeitas e produzir relatórios completos, tudo dentro de padrões rígidos de conformidade. Para esse cenário, a AWS publicou um guia técnico detalhando como arquitetar e implantar um sistema multi-agente usando LangGraph e Strands sobre a infraestrutura AWS. O código completo está disponível no GitHub.

    A divisão de responsabilidades entre LangGraph e Strands

    A arquitetura proposta separa claramente as responsabilidades entre os dois frameworks. O LangGraph cuida da orquestração macro: gerencia o estado compartilhado, define o grafo direcionado de execução e garante a confiabilidade do fluxo. O Strands atua como motor de raciocínio dentro de cada nó individual, executando o loop de análise com o LLM e chamando ferramentas externas conforme necessário.

    O LangGraph se destaca no controle granular de execução e no gerenciamento de estado entre agentes. Sua camada de persistência via checkpoints viabiliza recursos críticos para produção, como recuperação de falhas e interações com humano no loop. Já o Strands é agnóstico de modelo — integra-se com diferentes provedores de LLMs — e oferece observabilidade abrangente sobre cada etapa de raciocínio.

    Com o lançamento do Amazon Bedrock AgentCore, colocar essa solução em produção ficou consideravelmente mais simples. A combinação dos três forma uma base sólida para sistemas agênticos prontos para ambientes corporativos.

    Como o Strands executa o raciocínio nos nós

    O Strands Agent opera em um loop de raciocínio que avalia continuamente as saídas das ferramentas e toma decisões com base nos resultados intermediários. Ele inclui gerenciamento de sessão e estado, além de mecanismos para evitar que a janela de contexto estoure.

    No agente de vigilância de mercado, a descoberta de dados é separada da recuperação para evitar alucinações e fortalecer a solução contra ataques de injeção de SQL. Ferramentas como get_report_list e get_report_schema localizam os relatórios disponíveis, enquanto run_report constrói a consulta SQL com parâmetros validados e a executa — o LLM nunca escreve SQL diretamente. Veja a definição do agente security_monitor:

    from strands import Agent, tool
    from strands.models.bedrock import BedrockModel
    
    model = BedrockModel(
        model_id="us.anthropic.claude-sonnet-4-6",
        region_name="us-east-1",
        max_tokens=16000,
        additional_request_fields={
            "thinking": {"type": "adaptive", "budget_tokens": 8000},
        },
        cache_prompt="default",
    )
    
    @tool
    def get_report_list(agent_name: str) -> str:
        """Load the list of available reports for a specific agent.
    
        Args:
            agent_name: Name of the agent (e.g. 'security_monitor').
    
        Returns:
            str: JSON array of report objects with name and description.
        """
        reports_data = load_agent_reports(agent_name)
        return json.dumps(reports_data["reports"], indent=2)
    
    @tool
    def get_report_schema(report_name: str, query_intent: str) -> str:
        """Load column definitions for a report so you can build queries.
    
        Args:
            report_name: Name of the report (e.g. 'TradeActivity').
            query_intent: Description of what data to extract.
    
        Returns:
            str: JSON object with parameters and column definitions.
        """
        return json.dumps(load_json_report_definition(report_name), indent=2)
    
    @tool
    def run_report(
        report_name: str,
        filters: Dict[str, Any],
        limit: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Run a predefined report. The tool validates every filter against the report's
        schema and builds a parameterised SQL query. The LLM never writes raw SQL,
        so filter values cannot be injected into the query.
    
        Args:
            report_name: A report from `get_report_list` (e.g. 'TradeActivity').
            filters: Equality filters keyed by column name,
                     e.g. {"symbol": "AAPL", "date": "2024-03-15"}.
            limit: Optional row cap (1..10000).
    
        Returns:
            dict: {'success': bool, 'data': str (CSV), 'error': str or None}
        """
        schema = load_json_report_definition(report_name)
        allowed_columns = {c["name"] for c in schema["columns"]}
    
        # Reject any filter field that is not in the report's allowed list of columns.
        unknown = set(filters) - allowed_columns
        if unknown:
            raise ValueError(
                f"Unknown filter field(s) {sorted(unknown)} for {report_name}. "
                f"Allowed: {sorted(allowed_columns)}"
            )
    
        # Build SQL with named bind parameters.
        where = " AND ".join(f"{field} = :{field}" for field in filters)
        sql = f"SELECT * FROM {schema['reportName']}"
        if where:
            sql += f" WHERE {where}"
        if limit is not None:
            if not isinstance(limit, int) or not 1 <= limit <= 10_000:
                raise ValueError("limit must be an integer in [1, 10000]")
            sql += f" LIMIT {limit}"
    
        return query_market_data(report_name=report_name, sql=sql, bind=filters)
    
    security_monitor = Agent(
        model=model,
        system_prompt=SECURITY_MONITOR_PROMPT,
        tools=[get_report_list, get_report_schema, run_report],
        name="security_monitor",
    )

    Como o LangGraph orquestra o fluxo completo

    O LangGraph sustenta a orquestração de nível de produção por meio de três pilares:

    • Máquinas de estado baseadas em grafos: fluxos de trabalho são modelados como grafos direcionados — nós representam a lógica de cada agente e arestas determinam o caminho de execução, com suporte a ramificação condicional, execução paralela e roteamento dinâmico.
    • Persistência de estado via checkpoints: após cada nó executado, o estado completo do fluxo é salvo automaticamente. Isso viabiliza recuperação de falhas, conversas de múltiplos turnos e investigações de longa duração.
    • Confiabilidade em produção: o framework inclui estratégias de retry com backoff exponencial e observabilidade via OpenTelemetry, compatível com a maioria das ferramentas de monitoramento.

    O trecho abaixo define o grafo de orquestração completo: estado compartilhado, orquestrador que seleciona os agentes especialistas, roteamento condicional entre eles e checkpoints para recuperação:

    from typing import TypedDict, Optional, List, Dict, Any
    from langgraph.graph import END, StateGraph
    from langgraph_checkpoint_aws import AgentCoreMemorySaver
    
    class AgentState(TypedDict):
        query_text: str
        session_id: Optional[str]
        agent_task_map: Optional[Dict[str, str]]
        required_agents: Optional[List[str]]
        current_agent_index: Optional[int]
        # Each specialist writes its insights here
        security_monitor_insights: Optional[Dict[str, Any]]
        broker_monitor_insights: Optional[Dict[str, Any]]
        risk_monitor_insights: Optional[Dict[str, Any]]
        intel_analyst_insights: Optional[Dict[str, Any]]
        synthesizer_insights: Optional[str]
    
    SPECIALIST_NODES = {
        "security_monitor": security_monitor_node,
        "broker_monitor": broker_monitor_node,
        "risk_monitor": risk_monitor_node,
        "intel_analyst": intel_analyst_node,
    }
    
    def route_analysts(state: AgentState) -> str:
        """Dynamic routing --- walk the required_agents list by index."""
        required = state.get("required_agents", [])
        index = state.get("current_agent_index", 0)
        if not required:
            return END
        if index < len(required):
            return required[index]
        return "synthesizer"
    
    # Build the graph
    workflow = StateGraph(AgentState)
    workflow.add_node("orchestrator", orchestrator_node)
    for name, node_fn in SPECIALIST_NODES.items():
        workflow.add_node(name, node_fn)
    workflow.add_node("synthesizer", synthesizer_node)
    workflow.set_entry_point("orchestrator")
    
    # Conditional edges --- the orchestrator and every specialist route through
    # route_analysts, which can hand off to any specialist or the synthesizer.
    ALL_TARGETS = {name: name for name in SPECIALIST_NODES} | {
        "synthesizer": "synthesizer",
        END: END,
    }
    workflow.add_conditional_edges("orchestrator", route_analysts, ALL_TARGETS)
    for name in SPECIALIST_NODES:
        workflow.add_conditional_edges(name, route_analysts, ALL_TARGETS)
    workflow.add_edge("synthesizer", END)
    
    # AgentCoreMemorySaver checkpoints the state after every node
    checkpointer = AgentCoreMemorySaver(MEMORY_ID, region_name=REGION)
    graph = workflow.compile(checkpointer=checkpointer)
    Imagem original — fonte: Aws

    Por que usar os dois frameworks juntos

    Muitos processos corporativos precisam de fluxos rígidos e previsíveis. Depender exclusivamente do raciocínio não determinístico de um LLM para executar cada passo é um risco real. Ao mesmo tempo, etapas específicas dentro desses fluxos exigem a inteligência e a flexibilidade que só um LLM oferece. A combinação de LangGraph e Strands resolve exatamente essa tensão.

    • Raciocínio localizado: o LangGraph define a orquestração de alto nível. Os agentes Strands ficam posicionados nos nós onde o fluxo realmente precisa de análise via LLM — o raciocínio autônomo é aplicado apenas onde é estritamente necessário.
    • Contexto isolado por agente: agentes monolíticos perdem facilmente o fio das instruções. Ao posicionar um agente Strands em cada nó separado, a memória fica compartimentalizada. Cada agente gerencia seu próprio contexto, enquanto o LangGraph mantém o estado de sessão estruturado acessível a todos.
    • Ecossistema completo: embutir o Strands no LangGraph conecta ao grafo as integrações nativas com o Protocolo de Contexto de Modelo (MCP), controles de direção, guardrails de segurança e avaliação — tudo junto com o roteamento robusto do LangGraph.

    Na prática, cada especialista é um nó do LangGraph. O nó instancia um agente Strands com seu próprio prompt de sistema, ferramentas e contexto isolado, executa a tarefa atribuída pelo orquestrador e retorna uma atualização parcial de estado. O LangGraph mescla essa atualização no estado compartilhado que os outros nós leem. Veja o nó do monitor de segurança:

    async def security_monitor_node(state: AgentState) -> AgentState:
        """
        Single-day activity analyst agent that assesses price, volume and tick-level trades
        """
        agent = Agent(
            name="security_monitor",
            model=analyst_model,
            system_prompt=SECURITY_MONITOR_PROMPT,
            tools=[get_report_list, get_report_schema, run_report],
            callback_handler=None,
        )
    
        # Pull this node's task from the shared state the orchestrator populated.
        task = state.get("agent_task_map", {}).get("security_monitor", state["query_text"])
    
        # Strands runs its own reasoning + tool loop; collect the agent's final text.
        chunks = []
        async for event in agent.stream_async(task):
            if "data" in event:
                chunks.append(event["data"])
        result = "".join(chunks)
    
        # Return shared state updates
        return {
            "security_monitor_insights": {"task": task, "business_insights": result},
            "current_agent_index": state.get("current_agent_index", 0) + 1,
        }

    Implantação e infraestrutura com o AgentCore

    O Amazon Bedrock AgentCore oferece um serviço totalmente gerenciado para implantar e operar agentes em escala, eliminando a complexidade de gerenciar infraestrutura enquanto entrega capacidades de nível de produção.

    Runtime gerenciado

    O AgentCore Runtime transforma código local de agentes em implantações nativas de nuvem com configuração mínima. O serviço é agnóstico de framework, funciona nativamente com LangGraph e Strands, e cuida do trabalho pesado de orquestração de contêineres, escalabilidade automática e gerenciamento de sessões. Veja como implantar o orquestrador usando o SDK Python do AgentCore:

    # api.py --- AgentCore runtime entry point
    from bedrock_agentcore.runtime import BedrockAgentCoreApp
    from src.agents import Workflow
    
    app = BedrockAgentCoreApp()
    workflow = Workflow()
    
    @app.entrypoint
    async def market_surveillance_workflow(payload):
        """Invoked by AgentCore for each request. Yields streaming chunks."""
        prompt = payload.get("prompt")
        session_id = payload.get("session_id", "default-session")
        actor_id = payload.get("actor_id", "default-actor")
    
        async for chunk in workflow.stream_query(
            session_id=session_id,
            prompt=prompt,
            actor_id=actor_id
        ):
            yield chunk
    
    if __name__ == "__main__":
        app.run()
    
    # Deploy with the AgentCore starter toolkit
    from bedrock_agentcore_starter_toolkit import Runtime
    
    runtime = Runtime()
    runtime.configure(
        entrypoint="api.py",
        auto_create_execution_role=True,
        auto_create_ecr=True,
        requirements_file="requirements.txt",
        region="us-east-1",
        agent_name="market_surveillance_workflow",
    )
    result = runtime.launch()
    print(f"Agent ARN: {result.agent_arn}")
    
    # Invoke the deployed agent
    import boto3, json
    
    client = boto3.client("bedrock-agentcore", region_name="us-east-1")
    response = client.invoke_agent_runtime(
        agentRuntimeArn=result.agent_arn,
        qualifier="DEFAULT",
        payload=json.dumps({
            "prompt": "What caused the AAPL price spike at 11:00 AM on March 15, 2024?",
            "session_id": "session-001",
            "actor_id": "analyst-jane",
        }),
    )
    
    # AgentCore returns a server-sent-events stream. Parse it:
    for raw in response["response"].iter_lines():
        if not raw:
            continue
        line = raw.decode("utf-8") if isinstance(raw, bytes) else raw
        if not line.startswith("data: "):
            continue
        try:
            chunk = json.loads(line[6:])
            if isinstance(chunk, str) and chunk.startswith("data: "):
                chunk = json.loads(chunk[6:])
        except json.JSONDecodeError:
            continue  # malformed chunk --- skip, don't crash
        if isinstance(chunk, dict) and chunk.get("type") == "text":
            print(chunk["content"], end="")

    Memória de curto e longo prazo

    O LangGraph se integra com a memória do AgentCore via pacote langgraph-checkpoint-aws. A classe AgentCoreMemorySaver gerencia checkpoints contendo mensagens do usuário, respostas da IA, estado de execução do grafo e metadados — tudo salvo automaticamente após cada nó, sem necessidade de gerenciar tabelas do Amazon DynamoDB ou lógica de serialização customizada.

    Já a classe AgentCoreMemoryStore oferece memória inteligente de longo prazo: o AgentCore extrai automaticamente insights, resumos e preferências das conversas, e os agentes podem consultar essas memórias em interações futuras. Isso resolve o problema fundamental da ausência de estado — cada nova interação se baseia no conhecimento acumulado, em vez de começar do zero.

    import boto3, time
    
    REGION = "us-east-1"
    control_client = boto3.client("bedrock-agentcore-control", region_name=REGION)
    
    response = control_client.create_memory(
        name="MarketSurveillanceMemory",
        description="Memory for market surveillance multi-agent workflow.",
        eventExpiryDuration=90,  # days
    )
    MEMORY_ID = response["memory"]["id"]
    print(f"Memory ID: {MEMORY_ID}")
    
    # Wait for ACTIVE, with a 10-minute deadline. Creation normally takes 1-3 min.
    deadline = time.time() + 600
    while True:
        status = control_client.get_memory(memoryId=MEMORY_ID)["memory"]["status"]
        if status == "ACTIVE":
            break
        if status == "FAILED" or time.time() >= deadline:
            raise RuntimeError(f"Memory {MEMORY_ID} is {status!r} (expected ACTIVE)")
        time.sleep(10)
    
    # On graph build:
    checkpointer = AgentCoreMemorySaver(MEMORY_ID, region_name=REGION)
    graph = workflow.compile(checkpointer=checkpointer)
    
    # On invocation, pass thread_id and actor_id to the agent.
    # These are unique identifiers for the user and session:
    config = {
        "configurable": {
            "thread_id": "surveillance-session-001",
            "actor_id": "analyst-jane",
        }
    }
    response = await graph.ainvoke(
        {"query_text": "Which brokers were most active?"},
        config=config,
    )

    Observabilidade integrada

    O AgentCore inclui observabilidade nativa via Amazon CloudWatch e AWS X-Ray, capturando traces de execução dos agentes, invocações de ferramentas e métricas de desempenho. Combinado com os eventos OpenTelemetry do LangGraph, é possível ter visibilidade completa — desde a orquestração macro do fluxo até chamadas individuais de LLM e etapas de raciocínio.

    Conclusão

    A arquitetura apresentada pela AWS combina a orquestração determinística do LangGraph com o raciocínio inteligente do Strands, implantados no AgentCore. O LangGraph cuida da coordenação de agentes, persistência de estado e recuperação de fluxo. O Strands fornece o motor de análise dentro de cada nó. Essa separação de responsabilidades permite construir sistemas sofisticados que lidam com processos corporativos complexos mantendo confiabilidade em produção.

    O padrão pode ser estendido para outros cenários — pipelines de processamento de documentos, automação de atendimento ao cliente ou monitoramento de conformidade. A natureza agnóstica de modelo do Strands combinada com o gerenciamento de estado do LangGraph torna essa arquitetura especialmente valiosa para aplicações que exigem tanto flexibilidade quanto previsibilidade. Para explorar os detalhes técnicos e construir um agente de análise de mercado, acesse o repositório no GitHub.

    Fonte

    Market surveillance agent with LangGraph and Strands on AgentCore (https://aws.amazon.com/blogs/machine-learning/market-surveillance-agent-with-langgraph-and-strands-on-agentcore/)