Expose STACK proxy calls as AutoGen AgentChat tools. Each tool uses one agent's Passport, so STACK can apply that agent's service grant, scope, and revocation state.
pip install -U "autogen-agentchat" "autogen-ext[openai]" getstack
npx -y @getstackrun/cli auth loginfrom getstack import Stack
stack = Stack()
agent_record = stack.agents.register(
name="autogen-github-triage",
description="Triage issues in one GitHub repository",
accountability_mode="logged",
key_mode="customer_managed",
)
github = next(
connection
for connection in stack.services.list()
if connection["provider"] == "github"
)
stack.services.grant_agent_access(
agent_id=agent_record.id,
service_connection_id=github["id"],
scopes=github["scopes"],
)Connect GitHub first at Connect. Grant only the scopes that the AutoGen agent needs. Customer-managed key mode lets the runtime in the next step authenticate as this agent instead of carrying the operator API key.
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def main() -> None:
agent_stack = Stack(agent_id=agent_record.id)
with agent_stack.passports.mission(
agent_id=agent_record.id,
intent="Triage issues in acme/sandbox",
services=["github"],
checkpoint_interval="5m",
) as mission:
def create_github_issue(title: str, body: str) -> dict:
"""Create an 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 returned {response.status}")
return response.body
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
assistant = AssistantAgent(
name="github_triage",
model_client=model_client,
tools=[create_github_issue],
system_message="Triage acme/sandbox. Use the tool only when an issue is needed.",
)
await Console(assistant.run_stream(
task="Create an issue for the title typo we confirmed."
))
await model_client.close()
asyncio.run(main())AutoGen uses the function signature and docstring as the tool schema. The function routes the action through STACK. A direct call to GitHub would bypass STACK controls.
For a durable non-GET job, pass on_operation_id to mission.proxy() and persist the ID before network I/O. Reuse it only for the unchanged request; use agent_stack.proxy.get_operation() after response loss. See Proxy operation recovery.
The SDK method named passports.mission() manages a Passport lifecycle context. It is separate from the Mission resource.