AutoGen Integration
Use Attestd as an AutoGen FunctionTool to give agents real-time CVE risk and supply chain integrity data. These patterns target autogen-agentchat 0.7.5, the current stable release.
In multi-agent workflows, a compromised dependency approved by one agent propagates to every downstream agent that trusts its output. The most important correctness concern: outside_coverage is not a safety signal. Catch AttestdUnsupportedProductError and return an explicit unknown-risk response.
Install
Pin autogen-agentchat to 0.7.5. You also need a model client from autogen-ext (OpenAI shown below).
pip install "autogen-agentchat==0.7.5" autogen-core autogen-ext[openai] attestdFunctionTool definition
Wrap the Attestd check in FunctionTool from autogen_core.tools. Instantiate attestd.Client once at module level and capture it in the closure.
import os
import attestd
from autogen_core.tools import FunctionTool
from attestd import AttestdUnsupportedProductError
# Instantiate once — captured in closure. Never instantiate inside the tool function.
_client = attestd.Client(api_key=os.environ["ATTESTD_API_KEY"])
def check_package_vulnerability(product: str, version: str) -> dict:
"""Check whether a software package version has known CVE vulnerabilities
or supply chain compromise. Use before deploying or recommending any
software dependency. outside_coverage=True means no data. Treat as
unknown risk, not safe."""
try:
result = _client.check(product, version)
return {
"outside_coverage": False,
"risk_state": result.risk_state,
"actively_exploited": result.actively_exploited,
"patch_available": result.patch_available,
"fixed_version": result.fixed_version,
"supply_chain_compromised": (
result.supply_chain.compromised
if result.supply_chain is not None
else False
),
}
except AttestdUnsupportedProductError:
return {
"outside_coverage": True,
"risk_state": None,
"message": f"No Attestd coverage for '{product}'. Treat as unknown risk.",
}
attestd_tool = FunctionTool(
check_package_vulnerability,
description=(
"Check CVE risk and supply chain integrity for a software dependency. "
"outside_coverage=True means unknown risk, not safe."
),
)Single-agent pattern
One AssistantAgent with the Attestd tool in a RoundRobinGroupChat. Use TextMentionTermination with sources= so termination only fires on agent output, not the initial user task.
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from attestd_tool import attestd_tool
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
security_agent = AssistantAgent(
name="security_agent",
model_client=model_client,
tools=[attestd_tool],
system_message=(
"You are a security-aware deployment assistant. "
"Before approving any software dependency, call check_package_vulnerability. "
"Block if risk_state is 'critical' or 'high', or if supply_chain_compromised is True. "
"If outside_coverage is True, state that explicitly. Do not treat it as safe. "
"End with APPROVED or BLOCKED and your reasoning."
),
)
termination = TextMentionTermination("APPROVED", sources=["security_agent"]) | TextMentionTermination(
"BLOCKED", sources=["security_agent"]
)
team = RoundRobinGroupChat([security_agent], termination_condition=termination)
async def main() -> None:
await Console(
team.run_stream(
task="Is it safe to deploy with runc 1.0.0 and litellm 1.82.7?"
)
)
asyncio.run(main())Multi-agent safety gate
A dedicated security_gate agent runs Attestd checks before a deployment_agent can proceed. Combine termination conditions with | so the team stops on either APPROVED or BLOCKED from the security gate.
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from attestd_tool import attestd_tool
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
security_gate = AssistantAgent(
name="security_gate",
model_client=model_client,
tools=[attestd_tool],
system_message=(
"You are a security gate agent. Before any software dependency is "
"deployed or recommended, check it with check_package_vulnerability. "
"Block if risk_state is 'critical' or 'high', or if "
"supply_chain_compromised is True. "
"If outside_coverage is True, state that explicitly. Do not treat it as safe. "
"Respond with APPROVED or BLOCKED with your reasoning."
),
)
deployment_agent = AssistantAgent(
name="deployment_agent",
model_client=model_client,
system_message=(
"You handle deployment tasks. Wait for security_gate to approve "
"all dependencies before proceeding."
),
)
termination = TextMentionTermination("APPROVED", sources=["security_gate"]) | TextMentionTermination(
"BLOCKED", sources=["security_gate"]
)
team = RoundRobinGroupChat(
[security_gate, deployment_agent],
termination_condition=termination,
)
async def main() -> None:
await Console(
team.run_stream(
task=(
"Deploy a stack with runc 1.0.0, litellm 1.82.7, "
"node-ipc 9.1.6, and nginx 1.27.4."
)
)
)
asyncio.run(main())Return fields
The tool returns these fields. Design agent branching logic around them.
| Field | Semantics |
|---|---|
outside_coverage | true if Attestd has no data for this product. Not a safety signal — treat as unknown risk. |
risk_state | "critical" | "high" | "elevated" | "low" | "none" | null (when outside_coverage). Block on critical or high. |
actively_exploited | true if in the CISA KEV catalog. Block regardless of risk_state if true. |
patch_available | true if a fixed version is known. Use with fixed_version to tell the agent what to recommend. |
fixed_version | The earliest clean version, or null if no patch exists yet. |
supply_chain_compromised | true if a malicious publish or security yank was detected on PyPI. Block immediately. |
- → LangChain Integration (StructuredTool definition, same agent policy for Python LangChain)
- → MCP Server (hosted at mcp.attestd.io for Claude Code and Cursor)
- → AI Agent Integration (generic function tool, OpenAI function calling, outside-coverage policy)
- → Python SDK Reference (AsyncClient, error types, attestd.testing mock transports)
- → Response Field Reference (full semantics for every field returned by /v1/check)