Skip to content

[AAASM-193] ♻️ adapters: Reconcile hook architecture into single canonical path#16

Merged
Chisanan232 merged 23 commits into
masterfrom
v0.0.0/AAASM-193/reconcile_hook_architecture
May 1, 2026
Merged

[AAASM-193] ♻️ adapters: Reconcile hook architecture into single canonical path#16
Chisanan232 merged 23 commits into
masterfrom
v0.0.0/AAASM-193/reconcile_hook_architecture

Conversation

@Chisanan232
Copy link
Copy Markdown
Contributor

Description

Reconciles the Python SDK's hook architecture by creating real FrameworkAdapter subclasses for all six frameworks and routing init_assembly() through AdapterRegistry as the single detection path. Documents the canonical architecture in ADR-0001.

What changed

  • ADR-0001: Documents the canonical hook architecture decision — Python owns hooks/detection, Rust owns IPC transport. Includes integration path status table for all six adapters.
  • FrameworkAdapter subclasses: Created LangChainAdapter, LangGraphAdapter, CrewAIAdapter, PydanticAIAdapter, OpenAIAgentsAdapter, and MCPAdapter — each wrapping its corresponding RuntimePatch class.
  • AdapterRegistry: Replaced _BuiltinPlaceholderAdapter stubs with real adapter classes. Added priority ordering (get_available_adapters_by_priority()) with LangChain first (callback handler threading) and MCP last (fallback).
  • init_assembly(): Refactored to use _register_adapters() which goes through AdapterRegistry — eliminating the parallel detection path (_build_patch_plan, _is_installed, _has_agents_sdk). AssemblyContext.patches renamed to AssemblyContext.adapters.
  • Tests: Updated test_assembly.py, test_registry.py, and test_runtime.py to match the new adapter-based architecture.

Why

AAASM-193 (Epic AAASM-5) identified a naming inconsistency between the public adapter API (register_hooks/unregister_hooks) and the internal patch mechanism (apply/revert), plus a dual detection path where init_assembly() bypassed AdapterRegistry. This PR resolves both by making the registry the single canonical detection path and adding docstrings that clarify the two-level naming convention.

Type of Change

  • Refactoring (no behavior change)
  • Documentation (ADR)

Breaking Changes

  • AssemblyContext.patches renamed to AssemblyContext.adapters (internal API, not public)
  • Removed internal helpers: _build_patch_plan, _is_installed, _has_agents_sdk, _apply_runtime_patches, _revert_patches

Related Issues

Closes AAASM-193 (Epic: AAASM-5)

Testing

  • 117 passed, 7 skipped, 0 failed
  • All unit and integration tests updated for new adapter-based architecture
  • Full test suite verified with no regressions

Checklist

  • Tests pass locally
  • No new dependencies introduced
  • ADR documents architecture decision
  • All six adapters verified end-to-end in integration path audit

Chisanan232 and others added 23 commits May 1, 2026 17:20
Documents the canonical hook architecture: Python owns monkey-patching
and hook installation, Rust owns IPC transport. Architecture B
(Rust-side hook dispatch) was superseded by AAASM-162.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… adapter contract

Explains the two-level naming: register_hooks()/unregister_hooks() is
the public API, apply()/revert() is the internal RuntimePatch mechanism.
References ADR-0001.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mechanism role

Explains that RuntimePatch with apply()/revert() is the internal
monkey-patch mechanism, distinct from the public FrameworkAdapter API.
References ADR-0001.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing LangChainPatch with the public FrameworkAdapter API.
register_hooks() creates and applies the patch, unregister_hooks()
reverts it. Exposes get_callback_handler() for downstream adapters.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing LangGraphPatch with the public FrameworkAdapter API.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing CrewAIPatch with the public FrameworkAdapter API.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing PydanticAIPatch with the public FrameworkAdapter API.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing OpenAIAgentsPatch with the public FrameworkAdapter API.
Overrides is_available() to check for openai.agents module specifically.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing MCPClientPatch with the public FrameworkAdapter API.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lasses

Swap placeholder stubs for LangChainAdapter, LangGraphAdapter,
CrewAIAdapter, and PydanticAIAdapter in AdapterRegistry.__init__().

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…adapters

Previously missing from registry — now all 6 framework adapters are
registered as builtins.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s_by_priority

LangChain must be first (callback handler threading), MCP must be last
(fallback). New method returns available adapters in priority order
without calling register_hooks() — init_assembly() handles that.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows init_assembly() to propagate the agent ID to adapters that need
it without knowing which adapters require it. No-op for adapters
without a process_agent_id property.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tection path

Replace _build_patch_plan() with AdapterRegistry.get_available_adapters_by_priority().
AssemblyContext now holds adapters instead of patches. Shutdown calls
adapter.unregister_hooks() instead of patch.revert(). Remove dead code:
_build_patch_plan, _is_installed, _has_agents_sdk, _apply_runtime_patches,
_revert_patches, _replace_callback_targets.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ter classes

All six adapter packages now export their FrameworkAdapter subclass
alongside the existing patch class.

Refs AAASM-193

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all references to removed functions (_apply_runtime_patches,
_revert_patches, _build_patch_plan) with new adapter-based equivalents.
Change context.patches to context.adapters throughout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
find_spec("openai.agents") raises ModuleNotFoundError when the
openai package is not installed at all.  Catch the exception so
is_available() returns False gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename test to reflect that builtin registry keys now match
get_framework_name() directly, since real adapter classes replaced
placeholder stubs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace monkeypatched _is_installed with _register_adapters to match
the new adapter-based init_assembly flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the end-to-end integration status for all six framework
adapters, confirming each is fully wired through the canonical
FrameworkAdapter → RuntimePatch → interceptor path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-formatted by pre-commit hooks: import reordering and style
adjustments across adapters, tests, and examples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The import is used as a monkeypatch target by tests — add noqa to
prevent ruff from removing it again.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unused type: ignore comment in base.py, add type annotations
to test_runtime.py monkeypatch parameters, apply remaining linter
formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

@Chisanan232 Chisanan232 merged commit c6f6033 into master May 1, 2026
26 of 27 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.0/AAASM-193/reconcile_hook_architecture branch May 1, 2026 09:54
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