From f96eca1f9b4287e0e55e6a316f644ebaa974fbab Mon Sep 17 00:00:00 2001 From: Naga Satish Chilakamarti Date: Wed, 17 Jun 2026 23:15:03 +0530 Subject: [PATCH 1/3] Add tutorial for securing pipelines with TealTiger This tutorial covers securing multi-agent pipelines against runaway costs and PII leaks using TealTiger governance. It includes steps for building a RAG pipeline, installing dependencies, and implementing governance checks. --- ..._Against_Runaway_Costs_and_PII_Leaks.ipynb | 479 ++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb diff --git a/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb b/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb new file mode 100644 index 00000000..cbd7cf36 --- /dev/null +++ b/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb @@ -0,0 +1,479 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial: Secure Multi-Agent Pipelines Against Runaway Costs and PII Leaks\n", + "\n", + "- **Level**: Intermediate\n", + "- **Time to complete**: 20 min\n", + "- **Components Used**: [`OpenAIChatGenerator`](https://docs.haystack.deepset.ai/docs/openaichatgenerator), [`Agent`](https://docs.haystack.deepset.ai/docs/agent), [`Pipeline`](https://docs.haystack.deepset.ai/docs/pipeline)\n", + "- **Prerequisites**: OpenAI API key\n", + "- **Goal**: After completing this tutorial, you will have learned how to add deterministic governance to Haystack pipelines using TealTiger, preventing PII leaks, secret exposure, and runaway LLM costs -- all without adding another LLM to the governance path." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "Haystack makes it straightforward to build RAG pipelines and multi-agent systems. But once agents can call tools, query databases, or generate code, new risks appear:\n", + "\n", + "- **PII leaks**: An agent retrieves documents containing SSNs or credit card numbers and passes them to the LLM.\n", + "- **Secret exposure**: A code-generating agent embeds API keys in its output.\n", + "- **Cost runaway**: A research loop keeps calling the LLM indefinitely, burning through budget.\n", + "\n", + "[TealTiger](https://github.com/agentguard-ai/tealtiger) is a deterministic governance SDK that intercepts these problems *before* they reach the LLM or the user. No LLM in the governance path, under 5ms overhead, and structured audit evidence for every decision.\n", + "\n", + "In this tutorial, you will:\n", + "1. Build a simple RAG pipeline with Haystack\n", + "2. Add TealTiger governance to detect PII and secrets before they reach the model\n", + "3. Enforce a per-session cost budget\n", + "4. Inspect the governance audit trail" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Installing Dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "pip install haystack-ai tealtiger" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setting Up the Environment\n", + "\n", + "You need an OpenAI API key to run this tutorial. Enter it when prompted below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "\n", + "if \"OPENAI_API_KEY\" not in os.environ:\n", + " os.environ[\"OPENAI_API_KEY\"] = getpass(\"Enter your OpenAI API key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding the Problem: Ungoverned Pipelines\n", + "\n", + "Let's first see what happens in a pipeline *without* governance. Imagine a document store that contains records with personally identifiable information:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from haystack import Document\n", + "\n", + "# Simulated documents that contain sensitive data\n", + "documents = [\n", + " Document(\n", + " content=\"Customer John Smith, SSN: 123-45-6789, has an outstanding balance of $4,200.\",\n", + " meta={\"source\": \"customer_records\"},\n", + " ),\n", + " Document(\n", + " content=\"The database connection uses password: sk-prod-8f2a9b4c1d3e5f6a7b8c9d0e and connects to prod-db.internal.company.com.\",\n", + " meta={\"source\": \"internal_docs\"},\n", + " ),\n", + " Document(\n", + " content=\"Q4 revenue reached $12.3M, a 15% increase year-over-year. The engineering team expanded to 45 members.\",\n", + " meta={\"source\": \"earnings_report\"},\n", + " ),\n", + "]\n", + "\n", + "print(f\"Loaded {len(documents)} documents\")\n", + "print(f\"Document 1 contains SSN: {'123-45' in documents[0].content}\")\n", + "print(f\"Document 2 contains a secret: {'sk-prod' in documents[1].content}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In an ungoverned pipeline, all of this content flows directly to the LLM -- the SSN, the API key, everything. The model sees it, it may appear in logs, and there is no audit trail proving governance evaluated the content.\n", + "\n", + "## Adding TealTiger Governance\n", + "\n", + "TealTiger wraps LLM clients (like OpenAI) with a governance layer. It scans inputs and outputs for PII, secrets, and policy violations *before* they reach the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tealtiger import TealOpenAI, TealOpenAIConfig\n", + "from tealtiger.guardrails import PII_PATTERNS, SECRET_PATTERNS\n", + "\n", + "# Create a governed OpenAI client\n", + "governed_client = TealOpenAI(\n", + " config=TealOpenAIConfig(\n", + " api_key=os.environ[\"OPENAI_API_KEY\"],\n", + " guardrails={\n", + " \"pii_detection\": True, # Block SSN, credit cards, etc.\n", + " \"secret_detection\": True, # Block API keys, tokens\n", + " \"prompt_injection\": True, # Block injection attempts\n", + " },\n", + " budget={\n", + " \"max_cost_per_session\": 0.50, # Hard cap: $0.50 per session\n", + " },\n", + " )\n", + ")\n", + "\n", + "print(\"TealTiger governed client created.\")\n", + "print(f\" PII detection: enabled ({len(PII_PATTERNS)} patterns)\")\n", + "print(f\" Secret detection: enabled ({len(SECRET_PATTERNS)}+ patterns)\")\n", + "print(f\" Budget limit: $0.50/session\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Building a Governed RAG Pipeline\n", + "\n", + "Now let's build a Haystack RAG pipeline that uses the governed client. TealTiger integrates at the LLM client level, so it works transparently with any Haystack component that calls OpenAI." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from haystack import Pipeline\n", + "from haystack.components.builders import ChatPromptBuilder\n", + "from haystack.components.generators.chat import OpenAIChatGenerator\n", + "from haystack.dataclasses import ChatMessage\n", + "\n", + "# Build the RAG pipeline with TealTiger governance\n", + "rag_pipeline = Pipeline()\n", + "\n", + "# Use Haystack's OpenAIChatGenerator -- TealTiger governs at the API level\n", + "rag_pipeline.add_component(\n", + " \"prompt_builder\",\n", + " ChatPromptBuilder(\n", + " template=[\n", + " ChatMessage.from_user(\n", + " \"Based on the following context, answer the question.\\n\"\n", + " \"Context: {{context}}\\n\"\n", + " \"Question: {{question}}\"\n", + " )\n", + " ]\n", + " ),\n", + ")\n", + "\n", + "rag_pipeline.add_component(\n", + " \"llm\",\n", + " OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", + ")\n", + "\n", + "rag_pipeline.connect(\"prompt_builder\", \"llm\")\n", + "\n", + "print(\"RAG pipeline built successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing: Safe Document (No PII)\n", + "\n", + "Let's first query with the earnings report document -- this contains no sensitive data and should pass governance." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Query with clean document -- should pass governance\n", + "safe_context = documents[2].content # Earnings report\n", + "\n", + "result = rag_pipeline.run(\n", + " {\n", + " \"prompt_builder\": {\n", + " \"question\": \"What was the Q4 revenue?\",\n", + " \"context\": safe_context,\n", + " }\n", + " }\n", + ")\n", + "\n", + "print(\"Query: What was the Q4 revenue?\")\n", + "print(f\"Answer: {result['llm']['replies'][0].text}\")\n", + "print(\"\\nGovernance: ALLOWED (no PII or secrets detected)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing: PII Detection in Action\n", + "\n", + "Now let's use TealTiger's standalone scanning to show what happens when PII is present in the pipeline context. In a production setup, you would add a TealTiger pre-processing step before the LLM call." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tealtiger import TealGuard\n", + "\n", + "# Create a governance guard for content scanning\n", + "guard = TealGuard(\n", + " guardrails=[\"pii_detection\", \"secret_detection\"]\n", + ")\n", + "\n", + "# Scan the document with PII\n", + "pii_context = documents[0].content # Contains SSN\n", + "scan_result = guard.scan(pii_context)\n", + "\n", + "print(\"Scanning document with PII...\")\n", + "print(f\" Content: {pii_context[:50]}...\")\n", + "print(f\" Decision: {scan_result.action}\")\n", + "print(f\" Reason: {scan_result.reason_codes}\")\n", + "print(f\" Risk Score: {scan_result.risk_score}\")\n", + "print(f\" Latency: {scan_result.evaluation_time_ms:.2f}ms\")\n", + "print()\n", + "\n", + "# Scan the document with secrets\n", + "secret_context = documents[1].content # Contains API key\n", + "scan_result_2 = guard.scan(secret_context)\n", + "\n", + "print(\"Scanning document with secrets...\")\n", + "print(f\" Content: {secret_context[:50]}...\")\n", + "print(f\" Decision: {scan_result_2.action}\")\n", + "print(f\" Reason: {scan_result_2.reason_codes}\")\n", + "print(f\" Risk Score: {scan_result_2.risk_score}\")\n", + "print(f\" Latency: {scan_result_2.evaluation_time_ms:.2f}ms\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "TealTiger detected both the SSN and the API key pattern in under 5ms each -- deterministically, with no LLM call in the governance path.\n", + "\n", + "## Building a Governed Pre-Processing Component\n", + "\n", + "To integrate TealTiger directly into a Haystack pipeline, you can create a custom component that scans content before it reaches the LLM:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from haystack import component\n", + "from typing import List, Optional\n", + "\n", + "\n", + "@component\n", + "class TealTigerGovernanceFilter:\n", + " \"\"\"Haystack component that filters documents through TealTiger governance.\n", + "\n", + " Scans documents for PII, secrets, and policy violations before they\n", + " reach the LLM. Blocked documents are removed from the pipeline context.\n", + " \"\"\"\n", + "\n", + " def __init__(self, guardrails: Optional[List[str]] = None):\n", + " self.guard = TealGuard(\n", + " guardrails=guardrails or [\"pii_detection\", \"secret_detection\"]\n", + " )\n", + " self.blocked_count = 0\n", + " self.passed_count = 0\n", + "\n", + " @component.output_types(documents=List[Document], blocked=List[Document])\n", + " def run(self, documents: List[Document]):\n", + " passed = []\n", + " blocked = []\n", + "\n", + " for doc in documents:\n", + " result = self.guard.scan(doc.content)\n", + " if result.action == \"allow\":\n", + " passed.append(doc)\n", + " self.passed_count += 1\n", + " else:\n", + " blocked.append(doc)\n", + " self.blocked_count += 1\n", + "\n", + " return {\"documents\": passed, \"blocked\": blocked}\n", + "\n", + "\n", + "# Test the component\n", + "governance_filter = TealTigerGovernanceFilter()\n", + "filter_result = governance_filter.run(documents=documents)\n", + "\n", + "print(f\"Documents passed governance: {len(filter_result['documents'])}\")\n", + "print(f\"Documents blocked: {len(filter_result['blocked'])}\")\n", + "print()\n", + "for doc in filter_result[\"documents\"]:\n", + " print(f\" PASSED: {doc.content[:60]}...\")\n", + "for doc in filter_result[\"blocked\"]:\n", + " print(f\" BLOCKED: {doc.content[:60]}...\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Enforcing Cost Budgets\n", + "\n", + "TealTiger tracks LLM costs per session and enforces hard limits. This prevents infinite agent loops from burning through your API budget." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tealtiger import CostTracker, CostTrackerConfig, InMemoryCostStorage\n", + "\n", + "# Set up cost tracking with a $0.50 session budget\n", + "cost_tracker = CostTracker(\n", + " config=CostTrackerConfig(\n", + " storage=InMemoryCostStorage(),\n", + " budget_per_session=0.50,\n", + " budget_per_request=0.10,\n", + " )\n", + ")\n", + "\n", + "# Simulate tracking costs\n", + "cost_tracker.record(model=\"gpt-4o-mini\", input_tokens=500, output_tokens=200)\n", + "cost_tracker.record(model=\"gpt-4o-mini\", input_tokens=800, output_tokens=300)\n", + "\n", + "print(f\"Session cost so far: ${cost_tracker.session_cost:.4f}\")\n", + "print(f\"Budget remaining: ${cost_tracker.budget_remaining:.4f}\")\n", + "print(f\"Budget limit: ${cost_tracker.config.budget_per_session:.2f}\")\n", + "print(f\"Within budget: {cost_tracker.is_within_budget()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Inspecting the Governance Audit Trail\n", + "\n", + "Every TealTiger governance decision produces a structured receipt. These can be exported as SARIF (for security tools), JUnit XML (for CI/CD), or JSON (for dashboards)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "\n", + "# Get the governance audit trail from our earlier scans\n", + "audit_trail = guard.get_decisions()\n", + "\n", + "print(f\"Total governance decisions recorded: {len(audit_trail)}\")\n", + "print()\n", + "\n", + "for i, decision in enumerate(audit_trail, 1):\n", + " print(f\"Decision {i}:\")\n", + " print(f\" ID: {decision.decision_id}\")\n", + " print(f\" Action: {decision.action}\")\n", + " print(f\" Reason: {decision.reason_codes}\")\n", + " print(f\" Risk Score: {decision.risk_score}\")\n", + " print(f\" Latency: {decision.evaluation_time_ms:.2f}ms\")\n", + " print(f\" Timestamp: {decision.timestamp}\")\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Before and After Comparison\n", + "\n", + "| Concern | Without TealTiger | With TealTiger |\n", + "|---------|------------------|----------------|\n", + "| PII in context | Flows directly to LLM | Blocked before model sees it |\n", + "| Secrets in output | Returned to user | Detected and redacted |\n", + "| Cost control | No limit, infinite loops possible | Hard budget cap per session |\n", + "| Audit trail | None | Structured evidence for every decision |\n", + "| Governance overhead | N/A | <5ms deterministic, no LLM |\n", + "| Compliance evidence | Manual log review | SARIF/JUnit XML/JSON export |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What's next\n", + "\n", + "- Explore the [TealTiger documentation](https://docs.tealtiger.ai/) for advanced policy configuration.\n", + "- Check out [TealTiger's Haystack integration package](https://github.com/agentguard-ai/tealtiger/tree/main/packages/tealtiger-python) for deeper pipeline integration.\n", + "- Learn about [TealEngine policy modes](https://docs.tealtiger.ai/engine/) (ENFORCE, MONITOR, REPORT_ONLY) for gradual rollout.\n", + "- See [Tutorial 45: Creating a Multi-Agent System](https://haystack.deepset.ai/tutorials/45_creating_a_multi_agent_system) to combine agents with governance." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## About us\n", + "\n", + "\n", + "\ud83c\udf89 Congratulations! You've completed this tutorial!\n", + "\n", + "To stay up to date on the latest Haystack developments, you can [sign up for our newsletter](https://landing.deepset.ai/haystack-community-updates) or [join Haystack Discord community](https://discord.com/invite/xYvH6drSmA).\n", + "\n", + "Get in touch:\n", + "[X](https://x.com/Haystack_AI) | [LinkedIn](https://www.linkedin.com/showcase/haystack-ai-framework/) | [Discord](https://discord.com/invite/xYvH6drSmA) | [GitHub Discussions](https://github.com/deepset-ai/haystack/discussions) | [Haystack Website](https://haystack.deepset.ai)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.6 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.9.6" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 1c38dd63e313928de872a3ca4a4a5ae134625b10 Mon Sep 17 00:00:00 2001 From: Naga Satish Chilakamarti Date: Wed, 17 Jun 2026 23:16:54 +0530 Subject: [PATCH 2/3] Add tutorial for securing pipelines against costs and leaks Added a new tutorial entry for securing pipelines. --- index.toml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/index.toml b/index.toml index 2473a6f1..dc081738 100644 --- a/index.toml +++ b/index.toml @@ -260,4 +260,15 @@ completion_time = "20 min" created_at = 2026-03-30 dependencies = ["haystack-ai", "turboquant-vllm", "transformers-haystack"] featured = false -python_version = "3.12" \ No newline at end of file +python_version = "3.12" + +[[tutorial]] +title = "Securing Pipelines Against Runaway Costs and PII Leaks" +description = "Add deterministic governance to Haystack pipelines using TealTiger to prevent PII leaks, secret exposure, and runaway LLM costs" +level = "intermediate" +weight = 13 +notebook = "50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb" +aliases = [] +completion_time = "20 min" +created_at = 2026-06-17 +dependencies = ["tealtiger"] From 28fbf4f6aaab45ebba0985789b8967de16bd7fad Mon Sep 17 00:00:00 2001 From: NagaSatish Date: Sat, 11 Jul 2026 18:31:46 +0530 Subject: [PATCH 3/3] Rewrite tutorial to use tealtiger-haystack integration (TealTigerGovernanceComponent) Addresses reviewer feedback: - Use tealtiger-haystack package with TealTigerGovernanceComponent - Component properly wired into pipeline graph (not manual) - Fix title: remove 'Multi-Agent' (no Agent used) - Fix metadata: remove Agent from components list - Use obviously invalid PII placeholders (000-00-0000) - Remove fake sk- prefixed secrets - Remove unused json import - Fix premature governance claims - Show OBSERVE mode (zero-config) and ENFORCE mode (policies) - Demonstrate cost budget enforcement - Show structured audit trail inspection --- index.toml | 4 +- ..._Against_Runaway_Costs_and_PII_Leaks.ipynb | 457 +++++++----------- 2 files changed, 185 insertions(+), 276 deletions(-) diff --git a/index.toml b/index.toml index dc081738..565560ad 100644 --- a/index.toml +++ b/index.toml @@ -264,11 +264,11 @@ python_version = "3.12" [[tutorial]] title = "Securing Pipelines Against Runaway Costs and PII Leaks" -description = "Add deterministic governance to Haystack pipelines using TealTiger to prevent PII leaks, secret exposure, and runaway LLM costs" +description = "Add deterministic governance to Haystack pipelines using the tealtiger-haystack integration to prevent PII leaks, secret exposure, and runaway LLM costs" level = "intermediate" weight = 13 notebook = "50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb" aliases = [] completion_time = "20 min" created_at = 2026-06-17 -dependencies = ["tealtiger"] +dependencies = ["tealtiger-haystack"] diff --git a/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb b/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb index cbd7cf36..0e21fc97 100644 --- a/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb +++ b/tutorials/50_Securing_Pipelines_Against_Runaway_Costs_and_PII_Leaks.ipynb @@ -4,13 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tutorial: Secure Multi-Agent Pipelines Against Runaway Costs and PII Leaks\n", + "# Tutorial: Secure Haystack Pipelines Against Runaway Costs and PII Leaks\n", "\n", "- **Level**: Intermediate\n", "- **Time to complete**: 20 min\n", - "- **Components Used**: [`OpenAIChatGenerator`](https://docs.haystack.deepset.ai/docs/openaichatgenerator), [`Agent`](https://docs.haystack.deepset.ai/docs/agent), [`Pipeline`](https://docs.haystack.deepset.ai/docs/pipeline)\n", + "- **Components Used**: [`OpenAIChatGenerator`](https://docs.haystack.deepset.ai/docs/openaichatgenerator), [`Pipeline`](https://docs.haystack.deepset.ai/docs/pipeline), [`TealTigerGovernanceComponent`](https://haystack.deepset.ai/integrations/tealtiger)\n", "- **Prerequisites**: OpenAI API key\n", - "- **Goal**: After completing this tutorial, you will have learned how to add deterministic governance to Haystack pipelines using TealTiger, preventing PII leaks, secret exposure, and runaway LLM costs -- all without adding another LLM to the governance path." + "- **Goal**: After completing this tutorial, you will have learned how to add deterministic governance to Haystack pipelines using the `tealtiger-haystack` integration, preventing PII leaks, secret exposure, and runaway LLM costs — all without adding another LLM to the governance path." ] }, { @@ -19,26 +19,21 @@ "source": [ "## Overview\n", "\n", - "Haystack makes it straightforward to build RAG pipelines and multi-agent systems. But once agents can call tools, query databases, or generate code, new risks appear:\n", + "Once pipelines can query databases and call tools, new risks appear:\n", + "- **PII flowing to the model** — customer SSNs, credit card numbers in retrieved documents\n", + "- **Secrets in generated code** — API keys, passwords in context windows\n", + "- **Cost runaway** — infinite agent loops burning through budget\n", "\n", - "- **PII leaks**: An agent retrieves documents containing SSNs or credit card numbers and passes them to the LLM.\n", - "- **Secret exposure**: A code-generating agent embeds API keys in its output.\n", - "- **Cost runaway**: A research loop keeps calling the LLM indefinitely, burning through budget.\n", + "This tutorial shows how to prevent all three using the [`tealtiger-haystack`](https://pypi.org/project/tealtiger-haystack/) integration — a deterministic governance component that adds <2ms overhead and requires no additional LLM calls.\n", "\n", - "[TealTiger](https://github.com/agentguard-ai/tealtiger) is a deterministic governance SDK that intercepts these problems *before* they reach the LLM or the user. No LLM in the governance path, under 5ms overhead, and structured audit evidence for every decision.\n", - "\n", - "In this tutorial, you will:\n", - "1. Build a simple RAG pipeline with Haystack\n", - "2. Add TealTiger governance to detect PII and secrets before they reach the model\n", - "3. Enforce a per-session cost budget\n", - "4. Inspect the governance audit trail" + "We'll use the official `TealTigerGovernanceComponent` which plugs directly into Haystack pipelines as a first-class component." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Installing Dependencies" + "## Setup" ] }, { @@ -48,16 +43,7 @@ "outputs": [], "source": [ "%%bash\n", - "pip install haystack-ai tealtiger" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setting Up the Environment\n", - "\n", - "You need an OpenAI API key to run this tutorial. Enter it when prompted below." + "pip install tealtiger-haystack haystack-ai" ] }, { @@ -77,9 +63,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Understanding the Problem: Ungoverned Pipelines\n", + "## Part 1: Zero-Config Observe Mode\n", "\n", - "Let's first see what happens in a pipeline *without* governance. Imagine a document store that contains records with personally identifiable information:" + "The simplest way to add governance is **observe mode** — it allows everything through but tracks costs, detects PII, and produces structured audit entries. No policies needed." ] }, { @@ -88,38 +74,33 @@ "metadata": {}, "outputs": [], "source": [ - "from haystack import Document\n", - "\n", - "# Simulated documents that contain sensitive data\n", - "documents = [\n", - " Document(\n", - " content=\"Customer John Smith, SSN: 123-45-6789, has an outstanding balance of $4,200.\",\n", - " meta={\"source\": \"customer_records\"},\n", - " ),\n", - " Document(\n", - " content=\"The database connection uses password: sk-prod-8f2a9b4c1d3e5f6a7b8c9d0e and connects to prod-db.internal.company.com.\",\n", - " meta={\"source\": \"internal_docs\"},\n", - " ),\n", - " Document(\n", - " content=\"Q4 revenue reached $12.3M, a 15% increase year-over-year. The engineering team expanded to 45 members.\",\n", - " meta={\"source\": \"earnings_report\"},\n", - " ),\n", - "]\n", + "from haystack import Pipeline\n", + "from haystack.components.generators.chat import OpenAIChatGenerator\n", + "from haystack.components.builders import ChatPromptBuilder\n", + "from haystack.dataclasses import ChatMessage\n", + "from haystack_integrations.components.connectors.tealtiger import TealTigerGovernanceComponent\n", + "\n", + "# Create a pipeline with TealTiger governance in OBSERVE mode (default)\n", + "observe_pipeline = Pipeline()\n", "\n", - "print(f\"Loaded {len(documents)} documents\")\n", - "print(f\"Document 1 contains SSN: {'123-45' in documents[0].content}\")\n", - "print(f\"Document 2 contains a secret: {'sk-prod' in documents[1].content}\")" + "# Add the governance component — zero config, just add it\n", + "observe_pipeline.add_component(\"governance\", TealTigerGovernanceComponent())\n", + "observe_pipeline.add_component(\"llm\", OpenAIChatGenerator(model=\"gpt-4o-mini\"))\n", + "\n", + "# Connect governance output to LLM input\n", + "observe_pipeline.connect(\"governance.text\", \"llm.prompt\")\n", + "\n", + "print(\"Pipeline with TealTiger governance (OBSERVE mode) created.\")\n", + "print(\"All requests pass through, but cost + PII are tracked automatically.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In an ungoverned pipeline, all of this content flows directly to the LLM -- the SSN, the API key, everything. The model sees it, it may appear in logs, and there is no audit trail proving governance evaluated the content.\n", + "### Testing Observe Mode — Clean Input\n", "\n", - "## Adding TealTiger Governance\n", - "\n", - "TealTiger wraps LLM clients (like OpenAI) with a governance layer. It scans inputs and outputs for PII, secrets, and policy violations *before* they reach the model." + "A normal query with no PII passes through and gets tracked." ] }, { @@ -128,37 +109,26 @@ "metadata": {}, "outputs": [], "source": [ - "from tealtiger import TealOpenAI, TealOpenAIConfig\n", - "from tealtiger.guardrails import PII_PATTERNS, SECRET_PATTERNS\n", - "\n", - "# Create a governed OpenAI client\n", - "governed_client = TealOpenAI(\n", - " config=TealOpenAIConfig(\n", - " api_key=os.environ[\"OPENAI_API_KEY\"],\n", - " guardrails={\n", - " \"pii_detection\": True, # Block SSN, credit cards, etc.\n", - " \"secret_detection\": True, # Block API keys, tokens\n", - " \"prompt_injection\": True, # Block injection attempts\n", - " },\n", - " budget={\n", - " \"max_cost_per_session\": 0.50, # Hard cap: $0.50 per session\n", - " },\n", - " )\n", - ")\n", - "\n", - "print(\"TealTiger governed client created.\")\n", - "print(f\" PII detection: enabled ({len(PII_PATTERNS)} patterns)\")\n", - "print(f\" Secret detection: enabled ({len(SECRET_PATTERNS)}+ patterns)\")\n", - "print(f\" Budget limit: $0.50/session\")" + "result = observe_pipeline.run({\n", + " \"governance\": {\"text\": \"What was Apple's Q4 2024 revenue?\"}\n", + "})\n", + "\n", + "# The governance decision shows what was detected\n", + "decision = result[\"governance\"][\"decision\"]\n", + "print(f\"Action: {decision['action']}\")\n", + "print(f\"PII detected: {decision['pii_detected']}\")\n", + "print(f\"Cost tracked: ${decision['cost_tracked']:.6f}\")\n", + "print(f\"Evaluation time: {decision['evaluation_time_ms']:.2f}ms\")\n", + "print(f\"Correlation ID: {decision['correlation_id']}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Building a Governed RAG Pipeline\n", + "### Testing Observe Mode — Input with PII\n", "\n", - "Now let's build a Haystack RAG pipeline that uses the governed client. TealTiger integrates at the LLM client level, so it works transparently with any Haystack component that calls OpenAI." + "Even with PII present, observe mode **allows the request through** but records what was found." ] }, { @@ -167,45 +137,26 @@ "metadata": {}, "outputs": [], "source": [ - "from haystack import Pipeline\n", - "from haystack.components.builders import ChatPromptBuilder\n", - "from haystack.components.generators.chat import OpenAIChatGenerator\n", - "from haystack.dataclasses import ChatMessage\n", - "\n", - "# Build the RAG pipeline with TealTiger governance\n", - "rag_pipeline = Pipeline()\n", - "\n", - "# Use Haystack's OpenAIChatGenerator -- TealTiger governs at the API level\n", - "rag_pipeline.add_component(\n", - " \"prompt_builder\",\n", - " ChatPromptBuilder(\n", - " template=[\n", - " ChatMessage.from_user(\n", - " \"Based on the following context, answer the question.\\n\"\n", - " \"Context: {{context}}\\n\"\n", - " \"Question: {{question}}\"\n", - " )\n", - " ]\n", - " ),\n", - ")\n", - "\n", - "rag_pipeline.add_component(\n", - " \"llm\",\n", - " OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", - ")\n", - "\n", - "rag_pipeline.connect(\"prompt_builder\", \"llm\")\n", + "result = observe_pipeline.run({\n", + " \"governance\": {\n", + " \"text\": \"Customer John Smith, SSN: 000-00-0000, has a balance of $4,200. Summarize.\"\n", + " }\n", + "})\n", "\n", - "print(\"RAG pipeline built successfully.\")" + "decision = result[\"governance\"][\"decision\"]\n", + "print(f\"Action: {decision['action']}\") # Still ALLOW in observe mode\n", + "print(f\"PII detected: {decision['pii_detected']}\") # Shows SSN was found\n", + "print(f\"Cumulative cost: ${decision['cumulative_cost']:.6f}\")\n", + "print(\"\\nNote: In OBSERVE mode, PII is reported but never blocked.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Testing: Safe Document (No PII)\n", + "## Part 2: Enforce Mode — Blocking PII and Secrets\n", "\n", - "Let's first query with the earnings report document -- this contains no sensitive data and should pass governance." + "Now let's switch to **ENFORCE mode** with policies. This will actively block requests containing PII or secrets before they reach the LLM." ] }, { @@ -214,30 +165,33 @@ "metadata": {}, "outputs": [], "source": [ - "# Query with clean document -- should pass governance\n", - "safe_context = documents[2].content # Earnings report\n", - "\n", - "result = rag_pipeline.run(\n", - " {\n", - " \"prompt_builder\": {\n", - " \"question\": \"What was the Q4 revenue?\",\n", - " \"context\": safe_context,\n", - " }\n", - " }\n", + "from tealtiger import TealEngine\n", + "from haystack_integrations.components.connectors.tealtiger import TealTigerGovernanceComponent\n", + "from haystack_integrations.components.connectors.tealtiger.governance_component import GovernanceDenyError\n", + "\n", + "# Configure the governance engine with policies\n", + "engine = TealEngine(policies=[\n", + " {\"type\": \"pii_block\", \"categories\": [\"ssn\", \"credit_card\"]},\n", + " {\"type\": \"cost_limit\", \"max_per_session\": 5.00},\n", + "])\n", + "\n", + "# Create an enforcing pipeline\n", + "enforce_pipeline = Pipeline()\n", + "enforce_pipeline.add_component(\n", + " \"governance\",\n", + " TealTigerGovernanceComponent(engine=engine, mode=\"ENFORCE\", raise_on_deny=True),\n", ")\n", + "enforce_pipeline.add_component(\"llm\", OpenAIChatGenerator(model=\"gpt-4o-mini\"))\n", + "enforce_pipeline.connect(\"governance.text\", \"llm.prompt\")\n", "\n", - "print(\"Query: What was the Q4 revenue?\")\n", - "print(f\"Answer: {result['llm']['replies'][0].text}\")\n", - "print(\"\\nGovernance: ALLOWED (no PII or secrets detected)\")" + "print(\"Enforcing pipeline created with PII blocking + $5 cost limit.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Testing: PII Detection in Action\n", - "\n", - "Now let's use TealTiger's standalone scanning to show what happens when PII is present in the pipeline context. In a production setup, you would add a TealTiger pre-processing step before the LLM call." + "### Test: Clean Input Passes Through" ] }, { @@ -246,46 +200,21 @@ "metadata": {}, "outputs": [], "source": [ - "from tealtiger import TealGuard\n", - "\n", - "# Create a governance guard for content scanning\n", - "guard = TealGuard(\n", - " guardrails=[\"pii_detection\", \"secret_detection\"]\n", - ")\n", - "\n", - "# Scan the document with PII\n", - "pii_context = documents[0].content # Contains SSN\n", - "scan_result = guard.scan(pii_context)\n", - "\n", - "print(\"Scanning document with PII...\")\n", - "print(f\" Content: {pii_context[:50]}...\")\n", - "print(f\" Decision: {scan_result.action}\")\n", - "print(f\" Reason: {scan_result.reason_codes}\")\n", - "print(f\" Risk Score: {scan_result.risk_score}\")\n", - "print(f\" Latency: {scan_result.evaluation_time_ms:.2f}ms\")\n", - "print()\n", - "\n", - "# Scan the document with secrets\n", - "secret_context = documents[1].content # Contains API key\n", - "scan_result_2 = guard.scan(secret_context)\n", - "\n", - "print(\"Scanning document with secrets...\")\n", - "print(f\" Content: {secret_context[:50]}...\")\n", - "print(f\" Decision: {scan_result_2.action}\")\n", - "print(f\" Reason: {scan_result_2.reason_codes}\")\n", - "print(f\" Risk Score: {scan_result_2.risk_score}\")\n", - "print(f\" Latency: {scan_result_2.evaluation_time_ms:.2f}ms\")" + "result = enforce_pipeline.run({\n", + " \"governance\": {\"text\": \"What is the capital of France?\"}\n", + "})\n", + "\n", + "decision = result[\"governance\"][\"decision\"]\n", + "print(f\"Action: {decision['action']}\") # ALLOW\n", + "print(f\"PII detected: {decision['pii_detected']}\") # Empty\n", + "print(\"Clean input passed governance successfully.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "TealTiger detected both the SSN and the API key pattern in under 5ms each -- deterministically, with no LLM call in the governance path.\n", - "\n", - "## Building a Governed Pre-Processing Component\n", - "\n", - "To integrate TealTiger directly into a Haystack pipeline, you can create a custom component that scans content before it reaches the LLM:" + "### Test: PII is Blocked Before Reaching the LLM" ] }, { @@ -294,62 +223,25 @@ "metadata": {}, "outputs": [], "source": [ - "from haystack import component\n", - "from typing import List, Optional\n", - "\n", - "\n", - "@component\n", - "class TealTigerGovernanceFilter:\n", - " \"\"\"Haystack component that filters documents through TealTiger governance.\n", - "\n", - " Scans documents for PII, secrets, and policy violations before they\n", - " reach the LLM. Blocked documents are removed from the pipeline context.\n", - " \"\"\"\n", - "\n", - " def __init__(self, guardrails: Optional[List[str]] = None):\n", - " self.guard = TealGuard(\n", - " guardrails=guardrails or [\"pii_detection\", \"secret_detection\"]\n", - " )\n", - " self.blocked_count = 0\n", - " self.passed_count = 0\n", - "\n", - " @component.output_types(documents=List[Document], blocked=List[Document])\n", - " def run(self, documents: List[Document]):\n", - " passed = []\n", - " blocked = []\n", - "\n", - " for doc in documents:\n", - " result = self.guard.scan(doc.content)\n", - " if result.action == \"allow\":\n", - " passed.append(doc)\n", - " self.passed_count += 1\n", - " else:\n", - " blocked.append(doc)\n", - " self.blocked_count += 1\n", - "\n", - " return {\"documents\": passed, \"blocked\": blocked}\n", - "\n", - "\n", - "# Test the component\n", - "governance_filter = TealTigerGovernanceFilter()\n", - "filter_result = governance_filter.run(documents=documents)\n", - "\n", - "print(f\"Documents passed governance: {len(filter_result['documents'])}\")\n", - "print(f\"Documents blocked: {len(filter_result['blocked'])}\")\n", - "print()\n", - "for doc in filter_result[\"documents\"]:\n", - " print(f\" PASSED: {doc.content[:60]}...\")\n", - "for doc in filter_result[\"blocked\"]:\n", - " print(f\" BLOCKED: {doc.content[:60]}...\")" + "try:\n", + " result = enforce_pipeline.run({\n", + " \"governance\": {\n", + " \"text\": \"Customer SSN: 000-00-0000, credit card: 4111-1111-1111-1111. Process refund.\"\n", + " }\n", + " })\n", + " print(\"ERROR: Should have been blocked!\")\n", + "except GovernanceDenyError as e:\n", + " print(f\"BLOCKED by governance.\")\n", + " print(f\"Reason: {e.decision['reason']}\")\n", + " print(f\"Reason codes: {e.decision['reason_codes']}\")\n", + " print(f\"\\nThe LLM never saw this data — blocked at the governance layer.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Enforcing Cost Budgets\n", - "\n", - "TealTiger tracks LLM costs per session and enforces hard limits. This prevents infinite agent loops from burning through your API budget." + "### Test: Secrets are Blocked" ] }, { @@ -358,34 +250,25 @@ "metadata": {}, "outputs": [], "source": [ - "from tealtiger import CostTracker, CostTrackerConfig, InMemoryCostStorage\n", - "\n", - "# Set up cost tracking with a $0.50 session budget\n", - "cost_tracker = CostTracker(\n", - " config=CostTrackerConfig(\n", - " storage=InMemoryCostStorage(),\n", - " budget_per_session=0.50,\n", - " budget_per_request=0.10,\n", - " )\n", - ")\n", - "\n", - "# Simulate tracking costs\n", - "cost_tracker.record(model=\"gpt-4o-mini\", input_tokens=500, output_tokens=200)\n", - "cost_tracker.record(model=\"gpt-4o-mini\", input_tokens=800, output_tokens=300)\n", - "\n", - "print(f\"Session cost so far: ${cost_tracker.session_cost:.4f}\")\n", - "print(f\"Budget remaining: ${cost_tracker.budget_remaining:.4f}\")\n", - "print(f\"Budget limit: ${cost_tracker.config.budget_per_session:.2f}\")\n", - "print(f\"Within budget: {cost_tracker.is_within_budget()}\")" + "try:\n", + " result = enforce_pipeline.run({\n", + " \"governance\": {\n", + " \"text\": \"The database uses password: EXAMPLE_SECRET_TOKEN_12345 and connects to db.internal.example.com.\"\n", + " }\n", + " })\n", + " print(\"ERROR: Should have been blocked!\")\n", + "except GovernanceDenyError as e:\n", + " print(f\"BLOCKED: {e.decision['reason']}\")\n", + " print(f\"Secrets never reach the LLM context window.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Inspecting the Governance Audit Trail\n", + "## Part 3: Cost Tracking and Budget Enforcement\n", "\n", - "Every TealTiger governance decision produces a structured receipt. These can be exported as SARIF (for security tools), JUnit XML (for CI/CD), or JSON (for dashboards)." + "TealTiger tracks cumulative cost per session. When the budget limit is exceeded, requests are blocked before incurring more spend." ] }, { @@ -394,86 +277,112 @@ "metadata": {}, "outputs": [], "source": [ - "import json\n", - "\n", - "# Get the governance audit trail from our earlier scans\n", - "audit_trail = guard.get_decisions()\n", - "\n", - "print(f\"Total governance decisions recorded: {len(audit_trail)}\")\n", - "print()\n", - "\n", - "for i, decision in enumerate(audit_trail, 1):\n", - " print(f\"Decision {i}:\")\n", - " print(f\" ID: {decision.decision_id}\")\n", - " print(f\" Action: {decision.action}\")\n", - " print(f\" Reason: {decision.reason_codes}\")\n", - " print(f\" Risk Score: {decision.risk_score}\")\n", - " print(f\" Latency: {decision.evaluation_time_ms:.2f}ms\")\n", - " print(f\" Timestamp: {decision.timestamp}\")\n", - " print()" + "# Create a pipeline with a very low budget to demonstrate cost blocking\n", + "tight_budget_engine = TealEngine(policies=[\n", + " {\"type\": \"cost_limit\", \"max_per_session\": 0.001}, # $0.001 budget\n", + "])\n", + "\n", + "budget_pipeline = Pipeline()\n", + "budget_pipeline.add_component(\n", + " \"governance\",\n", + " TealTigerGovernanceComponent(engine=tight_budget_engine, mode=\"ENFORCE\"),\n", + ")\n", + "budget_pipeline.add_component(\"llm\", OpenAIChatGenerator(model=\"gpt-4o-mini\"))\n", + "budget_pipeline.connect(\"governance.text\", \"llm.prompt\")\n", + "\n", + "# First request may pass (under budget)\n", + "result = budget_pipeline.run({\"governance\": {\"text\": \"Hello\"}})\n", + "print(f\"Request 1 — Cost so far: ${result['governance']['decision']['cumulative_cost']:.6f}\")\n", + "\n", + "# Subsequent requests will be blocked once budget is exhausted\n", + "try:\n", + " for i in range(5):\n", + " result = budget_pipeline.run({\"governance\": {\"text\": f\"Request {i+2}\"}})\n", + "except GovernanceDenyError as e:\n", + " print(f\"\\nBUDGET EXCEEDED — blocked at request.\")\n", + " print(f\"Reason: {e.decision['reason']}\")\n", + " print(\"\\nThis prevents infinite agent loops from burning through your budget.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Before and After Comparison\n", - "\n", - "| Concern | Without TealTiger | With TealTiger |\n", - "|---------|------------------|----------------|\n", - "| PII in context | Flows directly to LLM | Blocked before model sees it |\n", - "| Secrets in output | Returned to user | Detected and redacted |\n", - "| Cost control | No limit, infinite loops possible | Hard budget cap per session |\n", - "| Audit trail | None | Structured evidence for every decision |\n", - "| Governance overhead | N/A | <5ms deterministic, no LLM |\n", - "| Compliance evidence | Manual log review | SARIF/JUnit XML/JSON export |" + "## Part 4: Inspecting the Audit Trail\n", + "\n", + "Every governance evaluation produces a structured audit entry with correlation IDs, timestamps, and findings — useful for compliance and debugging." ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "## What's next\n", + "# Run a few requests through observe mode to build up audit history\n", + "audit_pipeline = Pipeline()\n", + "governance_component = TealTigerGovernanceComponent()\n", + "audit_pipeline.add_component(\"governance\", governance_component)\n", + "audit_pipeline.add_component(\"llm\", OpenAIChatGenerator(model=\"gpt-4o-mini\"))\n", + "audit_pipeline.connect(\"governance.text\", \"llm.prompt\")\n", + "\n", + "# Process several requests\n", + "test_inputs = [\n", + " \"What is machine learning?\",\n", + " \"Customer email: test@example.com needs help with billing.\",\n", + " \"Normal technical question about Python async.\",\n", + "]\n", + "\n", + "for text in test_inputs:\n", + " result = audit_pipeline.run({\"governance\": {\"text\": text}})\n", "\n", - "- Explore the [TealTiger documentation](https://docs.tealtiger.ai/) for advanced policy configuration.\n", - "- Check out [TealTiger's Haystack integration package](https://github.com/agentguard-ai/tealtiger/tree/main/packages/tealtiger-python) for deeper pipeline integration.\n", - "- Learn about [TealEngine policy modes](https://docs.tealtiger.ai/engine/) (ENFORCE, MONITOR, REPORT_ONLY) for gradual rollout.\n", - "- See [Tutorial 45: Creating a Multi-Agent System](https://haystack.deepset.ai/tutorials/45_creating_a_multi_agent_system) to combine agents with governance." + "# Get the full audit trail\n", + "audit_trail = governance_component.get_decisions()\n", + "\n", + "print(f\"Total governance evaluations: {len(audit_trail)}\")\n", + "print(\"\\n--- Audit Trail ---\")\n", + "for i, entry in enumerate(audit_trail):\n", + " print(f\"\\n[{i+1}] Correlation ID: {entry['correlation_id'][:8]}...\")\n", + " print(f\" Action: {entry['action']}\")\n", + " print(f\" PII found: {len(entry['pii_detected'])} items\")\n", + " print(f\" Cost: ${entry['cost_tracked']:.6f}\")\n", + " print(f\" Eval time: {entry['evaluation_time_ms']:.2f}ms\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## About us\n", + "## Summary\n", + "\n", + "In this tutorial, you learned how to:\n", "\n", + "1. **Add zero-config governance** using `TealTigerGovernanceComponent()` in OBSERVE mode\n", + "2. **Block PII and secrets** before they reach the LLM using ENFORCE mode with policies\n", + "3. **Enforce cost budgets** to prevent runaway agent loops\n", + "4. **Inspect structured audit trails** with correlation IDs for compliance\n", "\n", - "\ud83c\udf89 Congratulations! You've completed this tutorial!\n", + "All governance is **deterministic** (no LLM in the decision path), adds **<2ms latency**, and works entirely **in-process** with no external service dependencies.\n", "\n", - "To stay up to date on the latest Haystack developments, you can [sign up for our newsletter](https://landing.deepset.ai/haystack-community-updates) or [join Haystack Discord community](https://discord.com/invite/xYvH6drSmA).\n", + "### Next Steps\n", "\n", - "Get in touch:\n", - "[X](https://x.com/Haystack_AI) | [LinkedIn](https://www.linkedin.com/showcase/haystack-ai-framework/) | [Discord](https://discord.com/invite/xYvH6drSmA) | [GitHub Discussions](https://github.com/deepset-ai/haystack/discussions) | [Haystack Website](https://haystack.deepset.ai)\n" + "- [TealTiger Haystack Integration](https://haystack.deepset.ai/integrations/tealtiger) — Full integration docs\n", + "- [tealtiger-haystack on PyPI](https://pypi.org/project/tealtiger-haystack/) — Package reference\n", + "- [TealTiger GitHub](https://github.com/agentguard-ai/tealtiger) — Source code and examples" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3.9.6 64-bit", + "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", - "version": "3.9.6" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" - } + "version": "3.11.0" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 }