Skip to content

Haystack

angelatgithub edited this page Sep 19, 2026 · 1 revision

Haystack — haystack-algenta

create_algenta_tools — a governed haystack.tools.toolset.Toolset on Haystack's own real MCPToolset (the separate mcp-haystack package), plus build_algenta_governance_hooks, an Agent after_tool hook raising typed AlgentaToolDenied for execute_decision's synchronous denials.

PyPI

Install

pip install haystack-algenta

Depends on haystack-ai + mcp-haystack (both real, non-optional); deliberately no algenta-sdk.

Quickstart

from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack_algenta import create_algenta_tools

toolset = create_algenta_tools(base_url="http://localhost:8000/mcp", profile="observe")
agent = Agent(chat_generator=OpenAIChatGenerator(), tools=toolset)
result = agent.run(messages=[ChatMessage.from_user("What's the expected value of scenario X?")])
print(result["messages"][-1].text)
toolset.close()  # tears down the MCP connection

Everything here is synchronous — MCPToolset's real public API is synchronous (it bridges its async client internally), so create_algenta_tools is a plain function, unlike the four other Python siblings. Needs OPENAI_API_KEY and a running engine.

Profiles

All four, per the contract: observe (default) · govern · execute · full (opt-in). Filtering is native — MCPToolset(tool_names=...) at construction, so excluded tools are never even seen. For full, pairing with Haystack's SearchableToolset is the documented mitigation for dumping ~100+ schemas into context.

Notes

  • Why the denial lives in an after_tool hook: verified live — Tool.invoke() has a bare except Exception that rewraps everything into ToolInvocationError, and Agent's default raise_on_tool_invocation_failure=False then swallows it into an error ChatMessage. The after_tool hook seam is the only place a custom exception survives agent.run() intact (grep-verified: no try/except around the hook call). Wire it with Agent(..., hooks=build_algenta_governance_hooks()).
  • Pipelines get no hook: hooks are an Agent-loop concept. For a Pipeline or direct Tool.invoke(), call extract_execution_outcome_from_tool_result(raw) yourself and branch on ExecutionBlocked — an honest capability, not a fabricated pause mechanism.
  • Pre-call confirmation still available: Haystack's real ConfirmationHook can gate the model's request to call execute_decision — proven live in the test suite — but the package doesn't wire it for you, since the engine has no approval state to bridge to.
  • Tests: real stub server (own background thread) + scripted chat generator — uv run pytest haystack-algenta -v.

Full reference: package README (version-verified denial mapping, double-JSON unwrap, hook composition).

Clone this wiki locally