integrations / autogen

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.

installation

Install

Pin autogen-agentchat to 0.7.5. You also need a model client from autogen-ext (OpenAI shown below).

bash
pip install "autogen-agentchat==0.7.5" autogen-core autogen-ext[openai] attestd
tool definition

FunctionTool definition

Wrap the Attestd check in FunctionTool from autogen_core.tools. Instantiate attestd.Client once at module level and capture it in the closure.

attestd_tool.py
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

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.

single_agent.py
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 pattern

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.

multi_agent.py
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())
fields

Return fields

The tool returns these fields. Design agent branching logic around them.

FieldSemantics
outside_coveragetrue 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_exploitedtrue if in the CISA KEV catalog. Block regardless of risk_state if true.
patch_availabletrue if a fixed version is known. Use with fixed_version to tell the agent what to recommend.
fixed_versionThe earliest clean version, or null if no patch exists yet.
supply_chain_compromisedtrue if a malicious publish or security yank was detected on PyPI. Block immediately.
see also