About Portfolio Cases Services Blog Contact 🎙 Talk to AI
EN DE RU
🎙 Talk to AI
November 10, 2026 · 5 min read

Your AI agent keeps hallucinating and breaking the repo? How to give Claude Code memory, data access, and safe guardrails

I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and at DennisCraft AI Studio I ship production AI systems for DACH B2B clients using Claude, Supabase, n8n, Doppler, and self-hosted Postgres. The failure mode I see most often is not “the model made a small mistake.” It is an AI agent confidently editing the wrong file, inventing a table column, and pushing a patch that looks plausible until your tests, or worse your users, prove otherwise. If Claude C

Denis Shokhirev
Denis Shokhirev
Agentic AI Systems Architect
Telegram LinkedIn

I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and at DennisCraft AI Studio I ship production AI systems for DACH B2B clients using Claude, Supabase, n8n, Doppler, and self-hosted Postgres. The failure mode I see most often is not “the model made a small mistake.” It is an AI agent confidently editing the wrong file, inventing a table column, and pushing a patch that looks plausible until your tests, or worse your users, prove otherwise.

If Claude Code has no memory of your codebase, no access to live facts, and no enforced reflexes before risky actions, it behaves like a smart junior engineer working from fragments. The fix is not a better pep talk in the system prompt. The fix is the execution environment around the model.

Why agents hallucinate in codebases they can already “see”

In production, I usually find 3 root causes. First, the agent lacks project memory: conventions, service boundaries, migration rules, naming patterns, and known traps. Second, it cannot verify facts against live systems: database schema, existing API responses, or current environment constraints. Third, there is no executable safety layer between “generate” and “apply.”

OWASP’s Top 10 for LLM Applications calls out prompt injection, insecure output handling, and excessive agency as recurring risks. That list matters because most repo-breaking agent failures are not abstract model issues. They are architecture issues around what the model is allowed to believe and do. Source: OWASP Top 10 for Large Language Model Applications, 2025, https://owasp.org/www-project-top-10-for-large-language-model-applications/.

What “memory” should mean here

I do not mean vague long-term memory claims. For Claude Code, memory should be explicit and inspectable: an agent context file, a repository index, service summaries, dependency notes, allowed commands, and a short record of past mistakes. Without that, every run starts with inference where it should start with facts.

#!/usr/bin/env bash
set -euo pipefail

cat > AGENT_CONTEXT.md <<'EOF'
Project: payments-ops
Rules:
- Never edit generated files
- Database access only through repository layer
- Migrations require human approval
- Secrets only from environment variables
- Before commit run: pytest -q, semgrep --config p/ci
EOF

git ls-files > .agent_file_index.txt

Memory without data access still produces fiction

The next layer is live system access, but only for facts. If the agent cannot inspect the current Postgres schema, it will invent columns. If it cannot read a real API payload, it will parse fields that do not exist. If it does not know which tables hold personal data, it can easily violate your own internal privacy rules.

In DACH B2B work, I separate access into 2 paths: read-only introspection for facts and a narrow controlled write path for changes. In Supabase or self-hosted Postgres, an agent almost never needs direct write access. It needs answers to questions like: which tables exist, which foreign keys are active, which migrations have already been applied?

import os
import psycopg
from psycopg.rows import dict_row

dsn = os.environ["READONLY_DATABASE_URL"]

with psycopg.connect(dsn, row_factory=dict_row) as conn:
    with conn.cursor() as cur:
        cur.execute("""
            select table_name, column_name, data_type
            from information_schema.columns
            where table_schema = 'public'
            order by table_name, ordinal_position
        """)
        rows = cur.fetchall()

for row in rows[:20]:
    print(f"{row['table_name']}.{row['column_name']} -> {row['data_type']}")

Expose this through a tool wrapper rather than direct free-form SQL if possible. Then every lookup is logged, rate-limited, and constrained by an allowlist.

Anthropic’s tool use guidance is aligned with this pattern: the model should call tools when it needs external facts instead of guessing. Source: Anthropic documentation, Tool Use, 2024–2025, https://docs.anthropic.com/.

Guardrails must execute, not just advise

The most common mistake I see is treating safety as a prompt-writing problem. A prompt can reduce some classes of failure, but it cannot stop a dangerous commit, prevent a secret from being added to source control, or reliably catch insecure string-built SQL. If you want stable behavior, guardrails must run in code.

For Python-heavy repos, my usual starting stack is semgrep, bandit, and gitleaks. They are not theoretical controls. They catch exactly the kinds of mistakes autonomous coding agents repeat under time pressure.

ControlCatchesWhen to run it
semgrepinsecure code patterns, risky SQL, validation bypassesbefore commit and in CI
banditcommon Python security issuesbefore merge
gitleakstokens, secrets, and accidental credentialson every push
human approvalmigrations, file deletions, permission changesbefore execution
name: agent-guardrails
on: [push, pull_request]
jobs:
  checks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: returntocorp/semgrep-action@v1
        with:
          config: p/ci
      - run: pip install bandit
      - run: bandit -r .
      - uses: gitleaks/gitleaks-action@v2

A production pattern for Claude Code

1. Give the agent operational memory

At minimum: AGENT_CONTEXT.md, service map, migration rules, allowed commands, and known failure patterns. Keep it in the repo. If it lives in a stale wiki, the model will learn the wrong facts.

2. Grant tools for verification, not imagination

Read-only Postgres introspection, repository search, test execution, and access to an internal API catalog are usually enough to start. Avoid broad shell access until you have good logs and clear policy boundaries.

3. Split generation from execution

Claude Code can propose a patch or plan first. A separate step applies changes. Another step creates a commit. This separation makes failures observable and approval gates practical.

4. Log reasoning inputs, not just outputs

Do not only record “file changed.” Record which facts the agent used: schema lookup, file references, test outputs, and policy checks. That is how you debug whether the issue was missing data access, stale memory, or weak controls.

type Action = "read" | "patch" | "commit";

function requireApproval(action: Action, path: string) {
  const sensitive = path.includes("migrations") || path.includes(".github");
  if ((action === "patch" || action === "commit") && sensitive) {
    throw new Error(`Human approval required for ${action} on ${path}`);
  }
}

requireApproval("patch", "db/migrations/20261110_add_users.sql");

What actually works in regulated European markets

In logistics, fintech, and industrial automation, autonomy only increases after traceability improves. Teams are willing to let an agent do more once they can see which data it accessed, which checks it passed, and where human approval is still required. That is especially true when personal data, auditability, or change-control obligations are in scope.

The OpenAI Cookbook has repeated the same practical advice in multiple examples: use retrieval and tools when factual accuracy matters instead of asking the model to answer from internal memory alone. Source: OpenAI Cookbook, 2024, https://cookbook.openai.com/. In production, this is not a philosophical preference. It is cheaper than incident analysis after a bad autonomous change lands.

FAQ

Is a strong system prompt enough?

No. A good system prompt helps, but it does not replace tool access or executable checks. Repo work depends on current facts, and prompts alone cannot supply them reliably.

Do I need RAG for Claude Code?

Not always. Many teams can get far with a repository index, AGENT_CONTEXT.md, and read-only schema access. RAG becomes useful when you have many services, long internal docs, and standards that change often.

Should an agent get direct Postgres access?

Start with a read-only role and narrow wrappers. In production, direct write access from the coding agent to the database is rarely justified.

Which checks should I add first?

semgrep, bandit, and gitleaks cover a large share of repeat mistakes. After that, add approval gates for migrations, CI changes, and destructive file operations.

How do I know the agent’s memory is stale?

If it keeps patching non-existent modules, referencing old tables, or repeating a previously fixed mistake, your context layer is out of sync. Memory should update in the same workflow as the repo itself.

Which stage in your LLM pipeline catches the most issues in production today: static analysis, runtime sandboxing, or human review before risky actions? I’d genuinely like to compare that with what I see across DACH B2B systems.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.

For your business

I build agents like this for businesses in Germany and the EU.

Tell me in two sentences what eats your team’s time – reply within 24 hours.

Custom AI agents (German page) →
Continue reading
Why one agent is no longer enough: orchestrating Claude Code, Codex, and Kiro without tmux chaos
Claude Code can leak into Slack, WordPress, and .env in production: 10 guardrails to enable before first run
Stop giving AI agents production keys: new control planes and approval gates for irreversible actions
Your AI agent hits a wall without web access: why teams need one MCP gateway instead of 20 fragile integrations
All articles →
Where this is applied
Services — what we build
Talk to the voice agent
Case studies
Ready to build?

Turn your process into an AI system

Production quality. DACH B2B focus.

Start a project → ← All articles