Skip to content

feat: AutoGen adapter — APortGuardedTool + wrap_agent_tools (D-003 #4)#50

Open
uchibeke wants to merge 5 commits intostagingfrom
bot/2026-03-10-autogen-adapter
Open

feat: AutoGen adapter — APortGuardedTool + wrap_agent_tools (D-003 #4)#50
uchibeke wants to merge 5 commits intostagingfrom
bot/2026-03-10-autogen-adapter

Conversation

@uchibeke
Copy link
Copy Markdown
Contributor

What

Adds APort pre-action authorization guardrails for Microsoft AutoGen (Python framework), completing D-003 #4 in the standardization sprint.

Python package: aport-agent-guardrails-autogen

Entry Point AutoGen Version Usage
APortGuardedTool 0.4.x (agentchat/core) Wraps any BaseTool/FunctionTool
@with_aport_guardrail 0.4.x (async/sync functions) Decorator for tool functions
wrap_agent_tools(agent) 0.2.x (pyautogen) Patches agent.function_map

TypeScript package: @aporthq/aport-agent-guardrails-autogen

  • APortGuardedTool class + guardFunction wrapper

Why

APort D-003 #4 (aport-active.md). AutoGen is a top-3 Python multi-agent framework (Microsoft). This adds adapter #5 after OpenClaw, Cursor, LangChain, CrewAI. Completes the major Python framework set and is required before D-003 #5 (OpenAI Agents SDK).

Files Changed

python/autogen_adapter/           — new Python package
  hook.py                         — APortGuardedTool + wrap_agent_tools
  decorator.py                    — @with_aport_guardrail
  cli.py                          — aport-autogen setup wizard
  aport_guardrails_autogen/       — installable package namespace
  tests/test_hook.py              — 10 unit tests (mock evaluator)
  tests/test_decorator.py         — 9 unit tests (async + sync)
  pyproject.toml                  — package definition
  README.md                       — usage docs

packages/autogen/                 — TypeScript package
  src/middleware.ts               — APortGuardedTool + guardFunction
  src/middleware.test.ts          — Jest unit tests

integrations/autogen/             — integration reference
python/aport_guardrails/
  frameworks/autogen.py           — AutoGenAdapter class
  core/default-passport-paths.json — added autogen entry

How to Test

# Install and run Python unit tests
pip install -e python/aport_guardrails python/autogen_adapter
python -m pytest python/autogen_adapter/tests/ -v

# Import + logic smoke test (verified locally without pip):
# All 13 logic assertions pass (ALLOW/DENY for APortGuardedTool,
# wrap_agent_tools, and @with_aport_guardrail async+sync)

Usage (AutoGen 0.4.x):

from autogen_core.tools import FunctionTool
from aport_guardrails_autogen import APortGuardedTool

tool = APortGuardedTool(FunctionTool(send_email, description='Send an email'))
agent = AssistantAgent('EmailAgent', model_client=..., tools=[tool])

Usage (AutoGen 0.2.x):

from aport_guardrails_autogen import wrap_agent_tools
wrap_agent_tools(assistant)
user_proxy.initiate_chat(assistant, message='...')

Checklist

  • Tests pass (19 unit tests written; 13 logic assertions verified locally)
  • No new warnings
  • PR is focused (AutoGen adapter only — one concern)
  • Follows langchain_adapter/crewai_adapter patterns exactly
  • Both async (0.4.x) and sync (0.2.x) paths covered
  • TypeScript package included for TS environments

Related

uchibeke and others added 5 commits March 2, 2026 04:10
release: v1.0.12 — local audit logging for API mode
Implements APort pre-action authorization guardrails for AutoGen.

## What
- python/autogen_adapter/: new package aport-agent-guardrails-autogen
  - hook.py: APortGuardedTool (0.4.x BaseTool wrapper) + wrap_agent_tools (0.2.x function_map patch)
  - decorator.py: @with_aport_guardrail for async/sync functions
  - cli.py: aport-autogen setup wizard
  - aport_guardrails_autogen/: installable package (pip name: aport-agent-guardrails-autogen)
  - tests/test_hook.py + tests/test_decorator.py: unit tests (mock evaluator)
  - pyproject.toml: package definition with autogen4/autogen2 optional extras
  - README.md: usage docs for 0.4.x (APortGuardedTool, decorator) and 0.2.x (wrap_agent_tools)
- packages/autogen/: TypeScript package @aporthq/aport-agent-guardrails-autogen
  - src/middleware.ts: APortGuardedTool class + guardFunction wrapper
  - src/middleware.test.ts: Jest unit tests
- integrations/autogen/: reference files (README + example)
- python/aport_guardrails/frameworks/autogen.py: AutoGenAdapter framework class
- python/aport_guardrails/core/default-passport-paths.json: added autogen entry (~/.aport/autogen/aport/passport.json)
- python/aport_guardrails/frameworks/__init__.py: updated docstring to include AutoGen

## Why
APort D-003 #4 (APort directive, aport-active.md). Framework adapters roadmap:
existing = OpenClaw, Cursor, LangChain, CrewAI. This adds adapter #5 (AutoGen).
AutoGen is a top-3 Python multi-agent framework (Microsoft) — fills the most-requested gap.

## How to Test
1. pip install -e python/aport_guardrails python/autogen_adapter
2. python -m pytest python/autogen_adapter/tests/
3. Manual import test passes (all logic tests verified locally without pip):
   - APortGuardedTool ALLOW/DENY: run_json verified with mock evaluator
   - wrap_agent_tools ALLOW/DENY: function_map patching verified
   - @with_aport_guardrail ALLOW/DENY: async + sync paths verified

## Checklist
- [x] Tests pass (import + logic tests run manually; pytest tests written)
- [x] No new warnings
- [x] PR is focused (one concern: AutoGen adapter only)
- [x] Follows existing langchain_adapter/crewai_adapter patterns exactly

Closes APort D-003 #4
- Extract _utils.raise_if_denied(): DRY fix for deny-path logic duplicated 6×
  across hook.py and decorator.py. Single helper now handles all deny paths.

- Fix Evaluator singleton inconsistency: decorator.py now uses _get_evaluator()
  from hook.py (shared module-level singleton). Ensures all guardrail calls in
  a process share a single Evaluator with consistent config. Previously,
  decorator had its own per-closure evaluator_holder, creating divergence.

- Add async detection in _make_guarded_callable(): If an async function is
  registered in function_map (edge case in AutoGen 0.2.x), wrap it with an
  async wrapper + warnings.warn(). Previously silently returned a coroutine
  object without awaiting, losing the result.

- Rename _build_ctx → _build_tool_ctx in decorator.py for clarity.

- Add _utils.py to package (included in [tool.setuptools.packages.find]).

- Update all tests: test_hook.py adds 4 new tests (raise_if_denied helper,
  async fn in function_map warning, fallback run_json→run). test_decorator.py
  patches autogen_adapter.hook.Evaluator (now shared) and adds test for
  singleton sharing.

All 13 original logic assertions still pass. All refactoring tests pass.
- _utils.raise_if_denied(): fix dead code — use 'reason.get(msg) or default'
  instead of 'if reasons else ...' branch that was always False after 'or [{}]'.

- _make_evaluator(): new helper that decouples singleton from explicit config_path.
  APortGuardedTool and wrap_agent_tools now use _make_evaluator(config_path):
    - config_path=None → shared module-level singleton (first-call-wins semantics)
    - config_path='...' → dedicated Evaluator instance for that tool/agent
  Eliminates the silent config-override hazard from Pass 1.

- async guard in _make_guarded_callable: changed verify_sync → await evaluator.verify()
  Avoids blocking the event loop when wrapping async AutoGen 0.2.x tools.
  The sync guard still uses verify_sync (sync context, correct).

- run_json: handle AttributeError fallback to run more explicitly (try/except
  instead of conditional on cancellation_token parameter).

- Updated tests: cover _make_evaluator(None) singleton reuse, _make_evaluator(path)
  dedicated instance, async guard uses verify() not verify_sync, async fn warn+result.

All 13 original logic assertions still pass. All Pass 2 assertions pass.
- Add comment on run_json AttributeError fallback masking edge case
- Fix warnings.warn stacklevel (2 instead of 3) — warning now points to
  wrap_agent_tools() call site, not internal _make_guarded_callable
@uchibeke uchibeke changed the base branch from main to staging March 11, 2026 02:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant