Skip to content

[AAASM-3537] ✨ (adapters): Add Agno framework adapter#162

Merged
Chisanan232 merged 11 commits into
masterfrom
v0.0.1/AAASM-3537/feat/agno_support
Jun 22, 2026
Merged

[AAASM-3537] ✨ (adapters): Add Agno framework adapter#162
Chisanan232 merged 11 commits into
masterfrom
v0.0.1/AAASM-3537/feat/agno_support

Conversation

@Chisanan232

Copy link
Copy Markdown
Contributor

Description

Adds a full framework adapter for Agno (pip agno, formerly Phidata) so the
Python SDK genuinely governs Agno agents at the in-process SDK layer.

Agno runs every function-tool body through a single chokepoint:
agno.tools.function.FunctionCall.execute (sync) and FunctionCall.aexecute
(async). An Agent builds a FunctionCall from the model's tool-call request and
invokes that method, which runs the user's tool entrypoint and wraps the return in
a FunctionExecutionResult. The adapter patches that one method:

  • deny short-circuits the body entirely (the tool never runs) and returns a
    FunctionExecutionResult(status="failure", ...) carrying the block message;
  • pending waits for approval, then allows or returns an approval-rejected result;
  • allow runs the body and records the result.

Decision normalization, fail-closed-under-enforce (AAASM-3107), and the approval
helpers are reused from the CrewAI adapter so posture is identical across adapters.

Type of Change

  • ✨ New feature

Breaking Changes

  • No

Related Issues

  • Related JIRA ticket: AAASM-3537 (parent AAASM-3535)

Testing

  • Unit tests added (fake-framework: allow/deny/pending/record, unknown-verdict
    fail-closed, async path, idempotent apply+revert)
  • Integration tests added — real Agno FunctionCall driven through the
    patched execute() as a negative control: a deny must short-circuit the real
    tool body (the test fails if the patch is ever a no-op), an allow runs and records
    it, revert restores unguarded execution, and the registry auto-detects the adapter.
  • agno>=2.0.0 added to the test dependency group so the integration test runs
    in CI rather than being skipped.

Verified locally: pytest test/unit (537 passed, 1 native-only skip), the new
unit + integration suite (17 passed), ruff check clean on new files, mypy
clean. Negative control confirmed: neutering the patch makes the deny test fail
(body executes [1000]); restoring it passes.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Documentation updated (README + docs/compatibility/frameworks.md)
  • All tests passing

Refs AAASM-3537

🤖 Generated with Claude Code

Chisanan232 and others added 7 commits June 22, 2026 14:16
Agno (pip agno, formerly Phidata) runs every function-tool body through
FunctionCall.execute (sync) / aexecute (async). Patch that chokepoint with a
pre-execution allow/deny: deny short-circuits the body and returns a failure
FunctionExecutionResult; allow runs it and records the result. Reuses the shared
fail-closed decision/approval helpers from the crewai adapter.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AgnoAdapter advertises framework name "agno" and supported range >=2.0.0, and
installs/reverts the AgnoPatch governance hooks.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add AgnoAdapter to the registry's built-in list and priority map so
init_assembly() auto-detects and hooks Agno whenever the framework is installed.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…vert

Drive a fake agno.tools.function module to cover the allow/deny/pending/record
branches, fail-closed-under-enforce on unknown verdicts, the async aexecute
path, and idempotent apply+revert — without importing the real framework.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…trol)

Drive a real agno FunctionCall through the patched execute() to prove a deny
short-circuits the actual tool body (fails if the patch is ever a no-op), an
allow runs and records it, revert restores unguarded execution, and the registry
auto-detects the installed adapter. importorskip-guarded on agno.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dev/test-only (NOT a runtime dependency). Installing agno lets the
importorskip-guarded integration test drive a real FunctionCall, so the
negative-control deny test fails on a regression instead of being silently
skipped.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Agno to the README and the authoritative Python framework-compatibility
matrix, with a section explaining the FunctionCall.execute/aexecute hook point
and the >=2.0.0 supported / 2.6.x tested lines.

Refs AAASM-3537

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.50350% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agent_assembly/adapters/agno/patch.py 95.90% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Chisanan232

Copy link
Copy Markdown
Contributor Author

Claude Code — review result

✅ Real CI green (SonarCloud not blocking).

  • Adapter: hooks agno.tools.function.FunctionCall.execute + .aexecute (verified against agno==2.6.18; the single chokepoint every Agno function-tool runs through). Registered (priority 6), get_supported_versions() = >=2.0.0.
  • Governance proven: negative control — neutering AgnoPatch.apply() makes the deny test fail (body executes); restored, denied body never runs. Live allow + audit verified against a real aa-runtime. ✔
  • Note from the agent (non-blocking): init_assembly() auto-detects Agno and installs the patch with the registry's no-op interceptor; the patch is idempotent, so a later policy-backed AgnoPatch.apply() no-ops unless the no-op hook is reverted first. The example handles this (revert then re-apply). Worth keeping in mind for any "swap interceptor after init" path.
  • Shared files: trivial keep-all overlap with siblings.

Ready to merge. Merge before examples #151 + a python-sdk release. Full cross-repo review on AAASM-3535.

The helper always returned the constant True (early idempotency guard +
end-of-body), which Sonar flags as S3516 "method always returns the same
value". Convert it to a void procedure — it installs the patch as a side
effect — and have apply() return True explicitly after calling it. The
apply() contract (True when patched, False when the framework is absent)
is unchanged; the idempotency tests still pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Chisanan232

Copy link
Copy Markdown
Contributor Author

Claude Code — SonarCloud new-code review (round 2)

Deep new-code pass found 1 finding here, now fixed:

  • S3516 BLOCKER agno/patch.py:178_apply_execute_patch always returned the constant True. Converted it to a void procedure (it installs the patch as a side effect); apply() now returns True explicitly. The apply() is True/False contract and idempotency tests are unchanged. Validated: ruff + mypy clean, 13 agno unit tests pass (commit 49696c8).

Quality gate now OK; 0 new-code issues (Security / Reliability / Maintainability / Hotspots / Coverage all clean).

Chisanan232 and others added 3 commits June 22, 2026 15:45
Resolve registry + README overlaps after py #160 (Haystack) merged:
keep both the Haystack (master) and Agno entries/imports/builtins and the
combined README adapter list. frameworks.md + compat table auto-merged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eat/agno_support

# Conflicts:
#	README.md
#	agent_assembly/adapters/registry.py
#	docs/compatibility/frameworks.md
#	pyproject.toml
The conflict resolution bumped smolagents 6->7 and set agno=8, which would silently change master's smolagents priority on merge and re-conflict with the llamaindex/MS branches. Match master + siblings: haystack/smolagents/agno all at priority 6 (disjoint frameworks; relative order among them is irrelevant).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@Chisanan232 Chisanan232 merged commit 664ee49 into master Jun 22, 2026
26 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-3537/feat/agno_support branch June 22, 2026 08:31
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