AutoGen integration

Five-minute path to wiring STACK into Microsoft AutoGen agents. AutoGen's function-calling pattern maps cleanly to STACK: every function the agent can invoke goes through the credential proxy with a passport-bound scope, and every call lands in the audit log.

Examples below use AutoGen 0.2 (PyPI package pyautogen) — the version with the AssistantAgent / UserProxyAgent / register_function pattern. Microsoft is shipping a successor under autogen-agentchat (0.4+); the STACK wiring concept is identical but the AutoGen-side imports differ.

1. Install

bash
pip install pyautogen getstack

STACK's Python SDK ships on PyPI as getstack.

2. Connect a service

Connect at least one upstream service at getstack.run/services. For this example, connect GitHub.

3. Register the agent + open a mission

python
import os
from getstack import Stack

stack = Stack(api_key=os.environ["STACK_API_KEY"])

agent = stack.agents.register(
    name="autogen-assistant",
    description="GitHub triage bot",
    accountability_mode="enforced",
)

mission_cm = stack.passports.mission(
    agent_id=agent.id,
    intent="Triage open issues in acme/sandbox",
    services=["github"],
    checkpoint_interval="5m",
)

mission_cm is a context manager. We keep a reference to it so the AutoGen functions defined below can capture mission in closure scope once we enter the block.

4. STACK-proxied functions

python
def make_github_functions(mission):
    """Define AutoGen-callable functions that proxy through STACK."""

    def create_github_issue(title: str, body: str) -> dict:
        """Create a GitHub issue in acme/sandbox."""
        response = mission.proxy(
            service="github",
            url="https://api.github.com/repos/acme/sandbox/issues",
            method="POST",
            body={"title": title, "body": body},
        )
        if not response.ok():
            raise RuntimeError(f"GitHub API failed: {response.status}")
        return response.body

    def list_github_issues(state: str = "open") -> list[dict]:
        """List GitHub issues in acme/sandbox."""
        response = mission.proxy(
            service="github",
            url="https://api.github.com/repos/acme/sandbox/issues",
            method="GET",
            query={"state": state},
        )
        if not response.ok():
            raise RuntimeError(f"GitHub API failed: {response.status}")
        return response.body

    return create_github_issue, list_github_issues

mission.proxy(...) attaches the passport JWT, logs the tool call into the mission's checkpoint buffer, and validates the URL. Pass full URLs — the proxy rejects relative paths.

5. Wire into AutoGen

python
from autogen import AssistantAgent, UserProxyAgent, register_function

with mission_cm as mission:
    create_github_issue, list_github_issues = make_github_functions(mission)

    llm_config = {"model": "gpt-4o-mini", "api_key": os.environ["OPENAI_API_KEY"]}

    assistant = AssistantAgent(
        name="github_helper",
        system_message=(
            "You triage GitHub issues for acme/sandbox. You can list and "
            "create issues. Your scope is bound to that one repo."
        ),
        llm_config=llm_config,
    )

    user_proxy = UserProxyAgent(
        name="user",
        human_input_mode="NEVER",
        code_execution_config=False,
    )

    register_function(
        create_github_issue,
        caller=assistant,
        executor=user_proxy,
        description="Create a GitHub issue in acme/sandbox",
    )
    register_function(
        list_github_issues,
        caller=assistant,
        executor=user_proxy,
        description="List GitHub issues in acme/sandbox",
    )

    user_proxy.initiate_chat(
        assistant,
        message="List open issues, then file one for the title-typo bug we discussed.",
    )

# Mission auto-checks-out here. Post-hoc detectors run on the trajectory.

6. What happens when the agent goes off-script

If the LLM hallucinates a call to a different repo or a different provider, the proxy denies it (passport scope is bound to github service for this agent) and the credential_outside_scope detector fires. In enforced mode the passport is auto-revoked; subsequent function calls raise. The trace surfaces in the dashboard /activity feed and /audit.

7. Kill switch

If you need to revoke during the run (e.g. the LLM's output looks adversarial), call:

python
stack.passports.revoke(mission.passport.jti, reason="off-script")

Propagation is sub-60-second. Subsequent mission.proxy(...) calls fail closed.

Full SDK reference: /docs/sdk/python. For multi-agent AutoGen flows where one agent hands off to another, register each as a separate STACK agent (one passport each, scope per role) — see the CrewAI guide for the same per-agent pattern.

Why bother

  • AutoGen functions are LLM-routed; STACK puts a hard fence around what each function can actually call
  • Scope is enforced server-side — the LLM cannot fabricate its way past it
  • Detectors catch wrong-repo / overrunning action volume / drift from the original intent
  • Hash-chained audit log of every function call, exportable for compliance review
stack | docs