Skip to content

[AAASM-3540] ✨ (adapters): Add Haystack framework adapter#160

Merged
Chisanan232 merged 4 commits into
masterfrom
v0.0.1/AAASM-3540/feat/haystack_support
Jun 22, 2026
Merged

[AAASM-3540] ✨ (adapters): Add Haystack framework adapter#160
Chisanan232 merged 4 commits into
masterfrom
v0.0.1/AAASM-3540/feat/haystack_support

Conversation

@Chisanan232

Copy link
Copy Markdown
Contributor

Description

Adds full Python SDK governance support for deepset Haystack (pip install haystack-ai, imported as haystack).

The adapter intercepts tool execution at haystack.tools.Tool.invoke(**kwargs) — the single execution chokepoint in Haystack 2.x. Both the bare Tool.invoke() path and the agentic AgentToolInvoker tool-call loop ultimately call tool.invoke(**final_args) (via ToolInvoker._make_context_bound_invoke), so patching Tool.invoke governs every tool execution from one place.

Governance behavior mirrors the CrewAI / Pydantic AI tool-call adapters: a check_tool_start pre-execution allow/deny/pending gate, an optional wait_for_tool_approval pending flow, and post-execution record_result / on_tool_end auditing. Unknown / malformed verdicts fail closed under the enforce posture (AAASM-3107).

HaystackAdapter is registered in the builtin registry and priority map, so init_assembly() auto-detects and hooks Haystack whenever it is importable.

Type of Change

  • ✨ New feature

Breaking Changes

  • No

Related Issues

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

Testing

  • Unit tests added/updated

test/unit/adapters/haystack/test_patch.py (24 tests). Proves real governance, not a no-op (AAASM-3528 lesson):

  • test_real_haystack_tool_is_genuinely_governed — drives a real haystack.tools.Tool; on deny the wrapped function never runs (side_effects == []) and a [BLOCKED by governance policy] string is returned; after revert() the same tool runs normally. This is the negative control — it fails if the patch is a pass-through.
  • test_real_haystack_tool_allow_runs_and_records — real Tool runs on allow and the result is recorded.
  • deny/allow/pending/timeout flows, idempotent apply, clean revert, and AAASM-3107 fail-closed parametrized cases.

Validated locally: full suite pytest test/603 passed, 13 skipped; ruff check clean on new files; mypy agent_assembly clean for the new module (only pre-existing _core/grpc-stub errors remain); pre-commit (black/isort/autoflake/mypy) green.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Comments added for complex logic
  • Documentation updated if needed (README + docs/compatibility/frameworks.md)
  • All tests passing

🤖 Generated with Claude Code

Chisanan232 and others added 4 commits June 22, 2026 14:12
Govern deepset Haystack 2.x agents by patching haystack.tools.Tool.invoke,
the single execution chokepoint through which both direct Tool.invoke() calls
and the Agent/ToolInvoker tool-call loop flow. Pre-execution allow/deny/pending
gate plus post-execution result recording; unknown verdicts fail closed under
enforce (AAASM-3107).

Refs AAASM-3540

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add HaystackAdapter to the builtin adapter list and priority map so
init_assembly() auto-detects and hooks Haystack when it is importable.

Refs AAASM-3540

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Prove real governance, not a no-op: deny blocks the underlying tool function
and returns a policy string; allow runs and records; pending waits for approval;
unknown verdicts fail closed under enforce. The negative-control tests drive a
real haystack.tools.Tool and assert the wrapped function never executes on deny.

Refs AAASM-3540

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Haystack to the framework-compatibility tables in the README and the
authoritative docs/compatibility/frameworks.md (supported range >=2.0.0,<3.0,
tested 2.30.x, Tool.invoke hook point).

Refs AAASM-3540

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 93.78882% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agent_assembly/adapters/haystack/adapter.py 64.70% 6 Missing ⚠️
agent_assembly/adapters/haystack/patch.py 97.14% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
7.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@Chisanan232

Copy link
Copy Markdown
Contributor Author

Claude Code — review result

✅ Real CI green. Only SonarCloud fails — acceptance gate, ignored per standing rule.

  • Adapter: hooks haystack.tools.Tool.invoke (the single tool-execution chokepoint in Haystack 2.x; ToolInvoker routes through it). Registered, get_supported_versions() = >=2.0.0,<3.0.
  • Governance proven: real Tool through a real ToolInvoker — on deny the body never runs; negative-control test fails if the patch is a no-op (AAASM-3528 lesson). ✔
  • Shared files (registry.py, README.md, docs/compatibility/frameworks.md): trivial keep-all overlap with the 4 sibling framework PRs — distinct registry key, no semantic collision. I'll rebase onto master (keep-all) after siblings merge.

Ready to merge. Merge before the examples PR #149 + a python-sdk release (the example import resolves only after b5 is on PyPI). Full cross-repo review on AAASM-3535.

@Chisanan232

Copy link
Copy Markdown
Contributor Author

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

New-code pass: 0 issues — no new Security / Reliability / Maintainability / Hotspot / Coverage findings.

The quality gate is red solely on new_duplicated_lines_density = 7.7% (> 3%). This is the Haystack adapter mirroring the established CrewAI adapter's decision/format plumbing — intentional template parity across the framework adapters (operator decision: not worth a cross-adapter refactor of proven code). Per the standing rule, this acceptance-dimension gate can be overridden at merge.

✅ Ready to merge (modulo the trivial keep-all rebase as siblings land).

@Chisanan232 Chisanan232 merged commit b4d3b62 into master Jun 22, 2026
22 of 23 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-3540/feat/haystack_support branch June 22, 2026 07:34
Chisanan232 added a commit that referenced this pull request Jun 22, 2026
Resolve the registry + README overlaps after py #160 (Haystack) merged:
keep both the Haystack (now on master) and Smolagents registry entries,
adapter imports, builtin-list entries, and the combined README adapter
list. frameworks.md auto-merged (both rows present).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chisanan232 added a commit that referenced this pull request Jun 22, 2026
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>
Chisanan232 added a commit that referenced this pull request Jun 22, 2026
Resolve registry + README + frameworks.md overlaps after py #160
(Haystack) merged: keep both frameworks' entries/imports/builtins/rows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chisanan232 added a commit that referenced this pull request Jun 22, 2026
Resolve registry + README overlaps after py #160 (Haystack) merged:
keep both frameworks' entries/imports/builtins. frameworks.md + compat
table auto-merged (both rows present).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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