In this article
Criando um resumo de notícias de segurança com um agente de IA do CrewAI
Acompanhar tantas fontes de notícias de segurança e bancos de dados de vulnerabilidades dá trabalho. Mas, com o avanço dos fluxos de trabalho de IA agentiva, podemos delegar essa tarefa a um LLM. Neste artigo, mostramos como usar o framework de código aberto CrewAI para criar um agente de IA que seleciona notícias de segurança.
Agentes de IA para selecionar notícias de segurança
Na aplicação que vamos criar, o foco será selecionar novas vulnerabilidades de segurança do Snyk Vulnerability Database para compor um feed de notícias de segurança.
Nosso agente de IA será uma ferramenta de linha de comando que abre a página do Snyk Vulnerability Database para determinado ecossistema (usaremos o ecossistema JavaScript do npm) e seleciona os três relatórios de CVE mais relevantes, que considerar mais importantes.
Primeiros passos com o CrewAI
Na primeira etapa, vamos criar a estrutura de um novo projeto em um diretório à sua escolha no ambiente de desenvolvimento local e inicializar o framework CrewAI.
Você vai precisar de:
O gerenciador de pacotes uv instalado e disponível localmente
Um ambiente de execução Python >= 3.x (pode ser instalado com
uv)
No diretório escolhido, vamos começar instalando a biblioteca e as ferramentas crewai:
uv tool install crewaiEm seguida, adicione o CrewAI ao ambiente do shell em uso para que possamos executar o comando crewai como um executável global:
uv tool update-shellAgora, vamos criar a estrutura de um novo projeto crewai:
crewai create crew <your_project_name>Depois, instale as dependências do projeto executando este comando:
crewai installA estrutura do projeto criado deve ficar assim:

Em linhas gerais, o CrewAI tem um arquivo crew.py que define os agentes e as tarefas:
@agent
def researcher(self) -> Agent:
return Agent(
config=self.agents_config['researcher'], # type: ignore[index]
verbose=True
)
@agent
def reporting_analyst(self) -> Agent:
return Agent(
config=self.agents_config['reporting_analyst'], # type: ignore[index]
verbose=True
)
Esse mesmo arquivo também inclui as tarefas que queremos executar com esses agentes:
@task
def research_task(self) -> Task:
return Task(
config=self.tasks_config['research_task'], # type: ignore[index]
)
@task
def reporting_task(self) -> Task:
return Task(
config=self.tasks_config['reporting_task'], # type: ignore[index]
output_file='report.md'
)O arquivo main.py exporta várias funções, como run(), train() e outras, que acionam os agentes e fornecem as entradas necessárias para que realizem o trabalho.
Veja como funciona o fluxo de inicialização dos agentes no arquivo principal do Python:
def run():
"""
Run the crew.
"""
inputs = {
'topic': 'AI LLMs',
'current_year': str(datetime.now().year)
}
try:
SecurityNewsSummary().crew().kickoff(inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while running the crew: {e}")Tudo isso descreve a estrutura padrão de diretórios de exemplo que o CrewAI cria para o projeto. Mas vamos fazer alterações, definir nossos próprios agentes e tarefas e criar uma ferramenta personalizada para eles usarem.
Criando fluxos de trabalho agentivos personalizados com o CrewAI
Vamos alterar três partes principais da estrutura criada para o projeto CrewAI:
Alterações nos agentes em
config/agents.yamlAlterações nas tarefas em
config/tasks.yamlAlterações no programa Python principal CrewAI, em crew.py
Além disso, vamos criar uma ferramenta personalizada no diretório tools/ para extrair o HTML de uma página da Web usando a popular biblioteca Python BeautifulSoup.
Agentes de IA
Uma boa regra para criar agentes de IA é dividir as tarefas em etapas tão pequenas quanto possível. Assim como na engenharia e no design de software, dividir problemas grandes em partes menores ajuda bastante.
Seguindo essa recomendação, vamos definir dois agentes:
Um curador de CVEs, cuja função é encontrar na página da Web links para as CVEs que considerar mais importantes.
Um pesquisador de CVEs, cuja função é acessar cada link de CVE (página da Web) e extrair os dados.
Abra config/agents.yaml e substitua a definição de agentes criada pelo CrewAI pelo seguinte:
1cve_curator:
2 role: >
3 Senior Security Analyst
4 goal: >
5 Find the links to the top most interesting CVEs reported in {security_vulnerabilities_url}.
6 backstory: >
7 You're a seasoned web scraper with a knack for parsing HTML pages and extracting the most relevant information.
8
9cve_researcher:
10 role: >
11 Senior Security Researcher
12 goal: >
13 Summarize and format the CVE information found by the CVE curator.
14 backstory: >
15 You're a meticulous security researcher with a keen eye for detail. You're known for
16 your ability to turn complex data into clear and concise reports, making
17 it easy for others to understand and act on the information you provide.Tarefas
Em seguida, precisamos definir as tarefas dos agentes:
A tarefa inicial é extrair os links das CVEs do diretório do banco de dados de vulnerabilidades (a página principal da Web com os resultados da busca e a lista de vulnerabilidades).
Na tarefa seguinte, o agente pesquisador de CVEs deve extrair os dados da vulnerabilidade de cada CVE na respectiva página de informações.
Abra o arquivo config/tasks.yaml e substitua o conteúdo criado pela biblioteca CrewAI pelo seguinte:
cve_curation_task:
description: >
Parse the HTML page to find the top most interesting CVEs reported in {security_vulnerabilities_url}.
You need to select 3 CVEs from the page and extract the link to their vulnerability page.
For example, the link to the vulnerability for the package @trpc/server is: https://security.snyk.io/vuln/SNYK-JS-TRPCSERVER-10060256
You should de-prioritize choosing CVEs for malicious packages. Instead, you should prioritize CVEs for popular packages and those that are likely
to have a high impact on the open-source ecosystem.
expected_output: >
A total of 3 CVEs, each formatted as a bullet point in the following markdown format
```
- https://security.snyk.io/vuln/SNYK-JS-TRPCSERVER-10060256
```
agent: cve_curator
cve_research_task:
description: >
For each of the CVE you should extract information by visiting the link to the vulnerability and extracting the information from the page.
For example, the link to the vulnerability for the package @trpc/server is: https://security.snyk.io/vuln/SNYK-JS-TRPCSERVER-10060256
Once you have the link, visit the page and extract the following information:
1) CVE ID (example: CVE-2025-12345)
2) Type of Vulnerability (example: RCE, SQL Injection, etc.)
3) CVE Publication Date (example: 2025-01-01)
4) Link to the CVE vulnerability page (example: https://security.snyk.io/vuln/SNYK-JS-KIBANA-10339388). The link exists as the href attribute of the anchor tag in the HTML page, set on the name of the vulnerability.
5) Package name that was found vulnerable (example: kibana)
expected_output: >
A total of 3 CVEs, each formatted as a bullet point in the following markdown format (strict markdown formatting for example links should not have space between the [] and () chars):
```
**@trpc/server** found vulnerable to CVE-2025-43855 [Uncaught Exception](https://security.snyk.io/vuln/SNYK-JS-TRPCSERVER-10060256), 24 Apr 2025
```
agent: cve_researcherRepare como as tarefas foram redigidas cuidadosamente para que nossos agentes de IA consigam interpretá-las e executá-las, com um exemplo do resultado esperado e regras a seguir.
Ferramentas personalizadas
Para a primeira tarefa e o primeiro agente, o curador de CVEs, precisamos criar nossa própria ferramenta em Python. Isso é necessário porque a ferramenta integrada ScrapeWebsiteTool do CrewAI só extrai o texto de uma página da Web e não consegue analisar o código-fonte HTML para encontrar os elementos âncora (<a href>) com links para os dados de cada CVE na página.
Para começar a criar uma ferramenta personalizada que nossos agentes possam usar, abra o arquivo tools/__init__.py e atualize-o para exportar uma nova TableScraperTool, desta forma:
from .custom_tool import MyCustomTool
from .table_scraper import TableScraperTool
__all__ = ['MyCustomTool', 'TableScraperTool']Observação: o MyCustomTool já fazia parte da estrutura de exemplo de projeto criada pelo CrewAI.
Em seguida, precisamos criar a TableScraperTool. Para isso, crie um arquivo em tools/table_scraper.py e adicione o seguinte código Python:
from typing import List, Dict, Any
from bs4 import BeautifulSoup
import requests
from crewai.tools import BaseTool
class TableScraperTool(BaseTool):
name: str = "table_scraper"
description: str = "Scrapes table data from a webpage, extracting rows, links, and other relevant information"
def _run(self, url: str) -> List[Dict[str, Any]]:
"""
Scrapes table data from the given URL.
Args:
url: The URL to scrape
Returns:
List of dictionaries containing table row data
"""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Find all table rows
rows = soup.find_all('tr', class_='table__row')
table_data = []
for row in rows:
row_data = {}
# Extract severity
severity_elem = row.find('li', class_='severity__item')
if severity_elem:
row_data['severity'] = severity_elem.get('class', [''])[0].replace('severity__item--', '')
# Extract vulnerability title and link
title_link = row.find('a', class_='anchor--underline')
if title_link:
row_data['title'] = title_link.text.strip()
row_data['vuln_link'] = title_link.get('href', '')
# Extract package name and link
package_link = row.find('a', attrs={'data-snyk-test-package-manager': True})
if package_link:
row_data['package_name'] = package_link.text.strip()
row_data['package_link'] = package_link.get('href', '')
# Extract version ranges
version_spans = row.find_all('span', class_='vulns-table__semver')
if version_spans:
row_data['version_ranges'] = [span.text.strip() for span in version_spans]
# Extract package manager and date
package_manager = row.find('span', attrs={'type': True})
if package_manager:
row_data['package_manager'] = package_manager.get('type', '')
row_data['published_date'] = package_manager.get('published', '')
if row_data: # Only add if we found some data
table_data.append(row_data)
return table_data
except Exception as e:
return [{"error": f"Failed to scrape table data: {str(e)}"}]
async def _arun(self, url: str) -> List[Dict[str, Any]]:
"""Async implementation of the tool"""
return self._run(url)Por fim, também precisamos incluir e atualizar a biblioteca Python BeautifulSoup no projeto. Para isso, atualize a lista de dependencies em myproject.toml, desta forma:
dependencies = [
...
"beautifulsoup4>=4.12.0"Em seguida, aplique as alterações com este comando:
uv pip install -e .Arquivo principal de execução do CrewAI
Agora, vamos nos concentrar no arquivo principal crew.py, que deve estar em src/security_news_summary ou no diretório escolhido para criar a estrutura do projeto CrewAI.
Edite o arquivo e, primeiro, faça as seguintes alterações nas importações (vamos incluir nossa ferramenta personalizada TableScraperTool):
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
from crewai_tools import ScrapeWebsiteTool
from typing import List
from .tools import TableScraperToolEm seguida, role a página até encontrar as funções anotadas como agentes (com a anotação @agent) e tarefas (com a anotação @task) e atualize-as para usar os agentes e as tarefas que acabamos de definir:
@agent
def cve_curator(self) -> Agent:
return Agent(
config=self.agents_config['cve_curator'], # type: ignore[index]
verbose=True,
tools=[ScrapeWebsiteTool(), TableScraperTool()]
)
@agent
def cve_researcher(self) -> Agent:
return Agent(
config=self.agents_config['cve_researcher'], # type: ignore[index]
verbose=True,
tools=[ScrapeWebsiteTool()]
)
# To learn more about structured task outputs,
# task dependencies, and task callbacks, check out the documentation:
# https://docs.crewai.com/concepts/tasks#overview-of-a-task
@task
def cve_curation_task(self) -> Task:
return Task(
config=self.tasks_config['cve_curation_task'], # type: ignore[index]
output_file='cves.md'
)
@task
def cve_research_task(self) -> Task:
return Task(
config=self.tasks_config['cve_research_task'], # type: ignore[index]
output_file='cves.md'
)Executando agentes de IA com o CrewAI
Pronto. Agora podemos executar nossos agentes de IA para selecionar novas vulnerabilidades de segurança usando o Snyk Vulnerability Database como fonte de dados.
Para iniciar os agentes CrewAI, basta executar este comando no terminal:
crewai runOs agentes de IA começam a trabalhar:

E as tarefas são informadas conforme o progresso avança:

Sobre segurança de IA e fluxos de trabalho agentivos
Criar agentes de IA parece mágica. Quando tudo funciona, a execução é surpreendentemente eficiente, e a biblioteca CrewAI para orquestração de agentes é muito fácil de usar.
Como os fluxos de trabalho de programação com IA e IA agentiva evoluem tão rapidamente, é importante ficar de olho na confiabilidade da IA e estabelecer barreiras de segurança para evitar riscos e problemas como implantações inseguras de servidores MCP, ataques de injeção de prompt e outras vulnerabilidades na superfície de ataque da IA.
Recomendo estes recursos:
Confira os guardrails de código de IA da Snyk
Programação segura com IA usando a Snyk (e servidores MCP)
Entenda a injeção de prompt: técnicas, desafios e riscos.
Desenvolva com IA com segurança desde o início
Aprenda a integrar a segurança em cada etapa do seu fluxo de desenvolvimento com IA — com dicas práticas de implementação de especialistas.