{"slug": "finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with", "title": "Finding the Bugs I Built an AI Agent to Prevent: Building Deterministic Guardrails with LangGraph & Python", "summary": "A developer built Ahmad-AI, a local LangGraph/Python/Ollama agent with live SQL and Islamic knowledge base access, and hardened it with deterministic Python guardrails after six rounds of adversarial testing exposed fabrication bugs. The agent invented fake item IDs and stock levels alongside an honest \"no results\" message, and cited a real but irrelevant Quran verse (5:51) because the citation guard's regex didn't match the model's output format. The system now ships with a 22-test unit suite, a live end-to-end harness, a pre-verified citation whitelist, and bounded tool rounds.", "body_md": "``\n\nA real debugging log: fabrication bugs, deployment gaps, and false test passes found and closed across 6 rounds of adversarial testing.\n\nSystem prompts are a leash, not a lobotomy. A system prompt can be ignored, misread, or drift under pressure. Deterministic code cannot.\n\nWhen I built Ahmad-AI — a local AI agent using LangGraph, Python, and Ollama with access to live SQL databases and Islamic knowledge bases — I established one non-negotiable design rule:\n\nIt must never state a specific citation or data claim unless that claim is independently verified. Verified, or it says nothing.\n\nBecause general-purpose LLMs fabricate citations confidently and often, \"confidently wrong\" is worse than \"honestly uncertain.\" I spent weeks trying to prove the system would break its own rule anyway.\n\nIt did. Repeatedly. Here is what I learned across six rounds of adversarial testing against a live agent.\n\nI ran a set of test questions against the live agent — empty database queries, Quran & Hadith citation requests, and ambiguous sorting queries.\n\nTwo critical bugs immediately surfaced:\n\nWhen querying a table with no matching rows, the agent correctly output: \"The query did not return any results.\" In the exact same sentence, it invented two fake item IDs with fake stock levels.\n\nWhen asked about usury (riba), the agent cited verse 5:51 (a real Quran verse, but entirely about interfaith alliances). My citation guard failed to fire because its regex expected Surah [name] X:Y, while the model wrote (Quran X:Y). A safety mechanism that doesn't match the shape of the output is functionally non-existent.\n\nMy first instinct was to strengthen the system prompt. I resisted. Instead of writing tighter rules for the LLM, I built a deterministic backstop in Python that overrides the model’s prose when known failure patterns appear in state:\n\n``python`\n\npython:\n\ndef apply_tool_result_guards(state, response):\n\n    \"\"\"\n\n    Deterministic backstop: if the last DB query came back empty or hard-errored, \n\n    override entirely with a fixed, honest message regardless of what the model wrote.\n\n    \"\"\"\n\n    if is_no_data(last_tool_message):\n\n        return \"No matching data was found for that query. The data may not exist yet.\"\n\nALLOWED_CITATIONS = {\"20:114\"} # Pre-verified whitelist\n\ndef enforce_citation_guard(text):\n\n    for match in CITATION_PATTERN.finditer(text):\n\n        if not any(allowed in match.group(0) for allowed in ALLOWED_CITATIONS):\n\n            return SAFE_ISLAMIC_FALLBACK  # Blocked even if the citation is real\n\n    return text\n\n`` ` ``\n\nManually retyping test prompts in a terminal doesn't scale. To keep the agent honest, I split automated testing into two distinct layers:\n\nUnit Tests (22 tests): Direct execution of Python guard functions against synthetic inputs (fast, no live LLM required).\n\nEnd-to-End Evaluation Harness: Drives the live LangGraph execution against Ollama and Postgres.\n\nTreating fuzzy model outputs as binary pass/fail either hides real regressions behind noisy false failures or downgrades hard security checks to \"close enough.\"\n\nA whitelist beats a correctness checker: Verifying \"is this citation accurate?\" is hard. Checking \"is this citation on the pre-approved whitelist?\" is simple and reliable.\n\nPrint a Build Stamp at Startup: A version stamp printed at agent startup costs nothing and prevents testing against stale code.\n\nDistinguish Transient from Permanent Errors: Retrying a connection drop makes sense. Retrying a bad SQL column name is just a slower way to fail.\n\nDon't ask LLMs to do arithmetic or row matching: Stating query answers explicitly in tool outputs prevents models from misreading JSON rows.\n\nRead the Full Engineering Log\n\nThis architecture is live, tested against a 22-unit-test suite and a 5/5 E2E hard check harness.\n\nFor the complete technical breakdown — including deployment gap fixes, bounded execution limits (MAX_TOOL_ROUNDS), and verbatim adversarial outputs:\n\n📖 Read the full interactive log on my portfolio:\n\n👉  [Engineering Log 01: Guardrails & Hallucination Prevention](https://emadaed.github.io/digisuite/engineering-log.html)\n\nMuhammad Ahmad is an AI Agent Engineer and Digital Supply Chain Architect (PMP®, RMP®) with 15+ years of operational leadership experience.", "url": "https://wpnews.pro/news/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with", "canonical_source": "https://dev.to/emadaed/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-guardrails-with-langgraph--agf", "published_at": "2026-10-17 18:28:21+00:00", "updated_at": "2026-10-17 18:36:17.207393+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "large-language-models", "ai-tools", "developer-tools"], "entities": ["Ahmad-AI", "LangGraph", "Ollama", "Python", "Postgres"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with", "markdown": "https://wpnews.pro/news/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with.md", "text": "https://wpnews.pro/news/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with.txt", "jsonld": "https://wpnews.pro/news/finding-the-bugs-i-built-an-ai-agent-to-prevent-building-deterministic-with.jsonld"}}