← All case files

02 · Production · Agent · 2026

An agent that cannot leak another tenant's data

Natural-language search over a graph of candidates for a specialist staffing platform. One tool-calling loop, and between the model and the database sits a deterministic gate.

TypeScriptLangGraphNeo4jFastifyGeminiZod

System flow

  1. Questionplain language
  2. Pre-filterno model call
  3. Agent loopone tool-calling loop
  4. Safety gatedeterministic code
  5. Read-only graphscoped session
  6. Answerwith references

The problem

  • People ask in plain language, for example “chief engineers with tanker experience, available soon”. The answer has to be grounded in data and scoped to the asker's organisation.

Constraints

  • Multi-tenant: a leak across organisations is the worst possible failure.
  • The model can be manipulated, so it cannot be the security boundary.
  • Every question costs money, so unnecessary model calls are waste.

Decisions.

  1. The model never sees the tenant id.

    It comes from the verified token and is injected by the gate. The model only ever writes a placeholder.

  2. Fail closed.

    A query that cannot be proven to be scoped to the tenant is rejected, not executed. Write clauses are blocked and row limits capped in plain code. The gate is the only path from model to database.

  3. Don't call the model for what code can answer.

    A deterministic pre-filter handles social filler, cheap meta questions and injection attempts with zero model calls.

  4. A thin graph around one loop.

    The LangGraph shell is four steps: load context, pre-filter, loop, persist. The loop streams reasoning, tool calls and text, so a frontend can render it without translation.

  5. Audit the failures before blaming the agent.

    When I hand-checked every miss on a labelled question set, several were upstream data-pipeline bugs rather than reasoning errors. Fixing the ETL moved the score more than another round of prompt work.

What it gave me

  • Scope is enforced in code that can be tested, not in a prompt that can be argued with.
  • Quotas are checked per organisation before any model call.
  • Each failure on the question set is classified as agent, data or question before anything is tuned.

In hindsight

  • I would widen the question set with real, anonymised queries before trusting any single headline number.
Next case file · 03

Forecasts that admit how wrong they can be