Skip to content

Add xaidr integration - #595

Open
ownerdelphisecurity wants to merge 4 commits into
deepset-ai:mainfrom
ownerdelphisecurity:add-xaidr
Open

ownerdelphisecurity wants to merge 4 commits into
deepset-ai:mainfrom
ownerdelphisecurity:add-xaidr

Conversation

@ownerdelphisecurity

Copy link
Copy Markdown

Adds xaidr, an open source runtime security sensor for AI agents. It hooks Haystack's Agent hook points to scan model input, tool calls, and model output, and can block a tool call before it executes.

PyPI: https://pypi.org/project/xaidr/
Repo: https://github.com/delphisecurity/xaidr

Every example on the page was executed against haystack-ai 3.1.1.

Signed-off-by: Anirudh Kotaru <anirudh@delphisecurity.ai>
@ownerdelphisecurity
ownerdelphisecurity requested a review from a team as a code owner September 5, 2026 19:25
@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

@ownerdelphisecurity is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

Signed-off-by: Anirudh Kotaru <anirudh@delphisecurity.ai>
Signed-off-by: Anirudh Kotaru <anirudh@delphisecurity.ai>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Moderate issues remain around Haystack compatibility metadata and handling scan verdicts.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds documentation for integrating xaidr with Haystack Agents for runtime security scanning.

Changes:

  • Documents installation and hook-based usage.
  • Adds monitoring, blocking, composition, and serialization examples.
  • Describes coverage boundaries and licensing.
File summaries
File Summary
integrations/xaidr.md New xaidr integration documentation and examples; compatibility metadata and tool-result handling require updates.
Review details
  • Files reviewed: 1/2 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread integrations/xaidr.md Outdated
type: Monitoring Tool
report_issue: https://github.com/delphisecurity/xaidr/issues
logo: /logos/xaidr.png
version: Haystack 2.0
Comment thread integrations/xaidr.md Outdated
def scan_tool_results(state):
for message in state.data.get("messages", []):
if message.is_from("tool"):
sensor.scan(message.tool_call_result.result, direction="input")
Comment thread integrations/xaidr.md

[xaidr](https://github.com/delphisecurity/xaidr) is a local-first security sensor
for AI agents. It scans for prompt injection, jailbreak and role-override
attempts, destructive tool calls, and secrets leaving in a response — and returns
Comment thread integrations/xaidr.md
Comment on lines +234 to +235
from haystack.core.serialization import allow_deserialization_module

- frontmatter: version Haystack 2.0 -> 3.0. The page installs haystack-ai>=3.0
  because the Agent hooks= API landed in 3.0, so a 2.x reader cannot follow it.
  Matches integrations/voyage.md, the repo's existing 3.x-only entry.

- tool results: rewrite the section as audit-only. The old hook called
  sensor.scan() and discarded the verdict, while the prose framed it as a seam
  you "can close yourself" - it closed nothing. It also failed at decoration
  time under haystack-ai 3.1.1: @hook requires the parameter be annotated
  State. The section now says plainly that the hook records what a tool
  returned and does not stop it reaching the model, and notes that acting on
  the verdict means replacing the message in state. No blocking example, since
  none has been run.

- serialization: add the missing `from haystack import Pipeline` import.

- router example: add the missing `from haystack.dataclasses import ChatMessage`
  import - same defect as the serialization block, found by running it.

- replace the `chat_generator=...` / `tools=[...]` Ellipsis placeholders in two
  examples, which raise AttributeError as copied.

Every code block on the page was run against real haystack-ai 3.1.1 and
xaidr 1.17.0.

Signed-off-by: Anirudh Kotaru <anirudh@delphisecurity.ai>
@anirudhraokotaru

Copy link
Copy Markdown

Thanks, all three substantive points were right. Addressed in fc46081.

1. Version metadata. version: Haystack 2.0 to Haystack 3.0. Checked the repo first: integrations/voyage.md is the existing 3.x-only entry and uses exactly version: Haystack 3.0, so I matched that string. Confirmed the xaidr[haystack] extra resolves to haystack-ai>=3.0.

2. Tool-results hook. Rewritten as audit-only. It was worse than discarding the verdict: the block failed at decoration time under haystack-ai 3.1.1, because @hook requires the parameter be annotated State. It raised ValueError: Hook function 'scan_tool_results' must take a single parameter annotated with State, so it never blocked anything because it never loaded.

With that fixed, I ran it end to end against a tool returning an injected payload in enforcement_mode="block". The scan fires "action":"blocked","category":"prompt_injection" and the payload still reaches the model verbatim, confirming your read. The section now states that the hook records what a tool returned and does not stop it reaching the model, and notes that acting on the verdict means replacing the message in state, which the hook API supports but this page does not document.

3. Serialization example. Pipeline import added. Ran the whole block against a real dumped pipeline: it loads, and agent_id and enforcement_mode round-trip with no live Sensor, as the prose claims. Also confirmed the opt-in is genuinely required: without it, deserialization refuses on xaidr.integrations.haystack specifically.

4. Wording. Leaving "secrets leaving in a response" as is. It names the egress direction that scan_output covers and distinguishes it from secrets appearing in a prompt.

Ran every other block against haystack-ai 3.1.1 and xaidr 1.17.0. Two more failed as copied and are fixed:

  • The ConditionalRouter example used ChatMessage without importing it, the same defect you caught in the serialization block. Import added.
  • Two examples used chat_generator=... placeholders, which raise AttributeError: 'ellipsis' object has no attribute 'run'. Replaced with the page's own OpenAIChatGenerator() and run_shell. Happy to revert if you prefer the placeholder style.

Every block on the page now runs as copied.

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.

3 participants