Haystack adapter
For deepset Haystack. Returns haystack.tools.Tool instances ready for any tool-aware generator (OpenAIChatGenerator, AnthropicChatGenerator, etc.).
Parameters schema is required
Unlike the other adapters, Haystack's Tool dataclass requires an explicit parameters JSON Schema for each registered tool — the generator serialises it into the OpenAI/Anthropic tool spec sent to the model. Omit it and only no-arg tools will work.
Install
pip install kitelogik haystack-aihaystack-ai is not a hard dependency — only imported when you call haystack_tools().
Setup
from kitelogik import OPAClient, PolicyGate, SessionContext
from kitelogik.adapters.haystack import HaystackAdapter
gate = PolicyGate(opa_client=OPAClient())
context = SessionContext(
session_id="sess_001",
user_role="analyst",
session_scopes=["read_customer"],
)
adapter = HaystackAdapter(gate=gate, context=context)Register tools (with parameters schema)
register(name, fn, description="", action=None, parameters=None).
def get_customer(customer_id: str) -> str:
return f"Customer {customer_id}: Acme Corp"
adapter.register(
"get_customer",
get_customer,
description="Look up a customer by ID",
parameters={
"type": "object",
"properties": {"customer_id": {"type": "string"}},
"required": ["customer_id"],
},
)If you omit parameters, the adapter falls back to {"type": "object", "properties": {}} — a no-arg schema that only works for tools the model calls without arguments.
Pass governed tools to a generator
from haystack.components.generators.chat import OpenAIChatGenerator
generator = OpenAIChatGenerator(
model="gpt-4o",
tools=adapter.haystack_tools(),
)
# In a Haystack pipeline, wire `generator` like any other tool-aware generator.What happens on a deny
Denied calls return a JSON string {"blocked": true, "reason": "..."} from the tool — the generator surfaces it to the model in the next turn.
To customise, pass deny_message= to the adapter constructor.
Constructor parameters
HaystackAdapter extends BaseGovernedAdapter:
HaystackAdapter(
gate: PolicyGate,
context: SessionContext,
sanitize: bool = True,
deny_message: str | None = None,
)| Param | Default | Purpose |
|---|---|---|
sanitize | True | Run prompt-injection sanitiser on string return values |
deny_message | "Action blocked by governance policy." | Surfaced to the model on deny |
Source
kitelogik/adapters/haystack.py on GitHub.