Home
7 min read
#Agent Evals#Verifiable Systems#LLM Production#Banking#MCP

What Bank-Grade Key Management Teaches You About Agent Eval Harnesses

Five banking disciplines for LLM evals: durable state, deterministic recovery, dual control, audit trails, and recovery playbooks.

Why this matters

Many agent systems I see are evaluated like demos: a human reads a transcript, accepts the result, and ships. In regulated domains — banking, fintech, compliance, insurance — I would not ship that pattern. The useful question is not "does the agent sound right?" It is: "can I prove, after the fact, why it did what it did — and rerun the same inputs to reproduce it?"

Before 2024, I worked mainly on wallet architectures, Lightning UI prototypes, and custodial solutions for banks. The principle I carried forward was not "cryptography for its own sake". It was systems designed so that any claim can be verified by someone who doesn't trust you. That model maps closely to production LLM agents. It is also a gap I often see in teams coming from web-app engineering.

Below are five disciplines I carry over, with the agent-system mapping.

1. Durable state, not transient context

Banking: a key never lives only in memory. It exists in an HSM, a backup HSM, an encrypted shard set, and an audit log that records every time it was touched. I do not treat ephemeral state as trusted state.

Agent parallel: I persist agent state before any tool call that has side effects, not after. LangGraph's checkpointer is a practical baseline. Without durable state, I cannot answer "what did the agent know at step N?" — a question I often see in post-incident reviews.

# Not this:
result = agent.invoke(input)  # state only in RAM

# This:
checkpoint = graph.invoke(
    input,
    config={"configurable": {"thread_id": session_id}},  # persisted
)

Cost: added latency and storage per step. Benefit: I can audit and debug each recorded trajectory.

2. Deterministic failure modes

Banking: key operations either succeed or fail cleanly. I do not want a partial success path. Depending on the system, I treat a partial signature as a security incident or investigate it as one.

Agent parallel: I make every tool contract expose typed, exhaustive failure modes. No except Exception: pass. No "just let the LLM retry" without explicit termination. I use Pydantic schemas for every tool I/O, with union types for failure cases the LLM is expected to handle:

from pydantic import BaseModel, Field


class SearchResult(BaseModel):
    status: Literal["ok", "rate_limited", "empty", "auth_error"]
    hits: list[Hit] = Field(default_factory=list)
    retry_after_s: int | None = None

The LLM can reason about status: rate_limited → wait. An LLM should not be expected to handle an unstructured exception trace reliably.

3. Dual control for high-stakes actions

Banking: moving money above a threshold requires two authorizations. No single key, and no single human, can do it alone.

Agent parallel: I treat any action with financial, legal, or customer-facing impact as requiring a human-in-the-loop checkpoint or a separate validation agent with fixed rules — not the same agent that proposed it. I often see this gap in enterprise agent deployments. Teams ship agents that auto-send email, auto-commit code, or auto-file tickets without independent approval.

LangGraph's interrupt primitive is the mechanism I use. I use it for external communications, writes to systems of record, and anything that affects external systems or customer-visible state.

4. Audit trails as evidence, not logs

Banking: every action produces evidence that would be useful in a regulator review. That means signed, timestamped, and tamper-evident — not just "there are logs".

Agent parallel: I want the eval harness and the production trace store to share the same schema and evidence model over time. I want every agent run to write: input, prompt template hash, model name + version, tool invocations with arguments and returns, final output, and a timestamped record. A timestamp alone is not chain-of-custody evidence; provenance and tamper protection need their own controls. I have used OpenTelemetry + LangSmith in some teams as a workable baseline. I have also found a Postgres table with jsonb columns and an append-only constraint workable in narrower setups. I do not treat Slack transcripts as a reliable evidence store.

Why it matters: regressions in LLM systems can be hard to see in aggregate metrics but visible in specific traces. Without replayable evidence, I am left with guesswork during diagnosis.

5. Recovery playbooks for failure, not just success

Banking: mature custodial services should have a runbook for key compromise, key loss, and operator compromise. I want the playbook written before the incident, not after.

Agent parallel: before I ship, I write down the failure modes I expect to see in production and the recovery action for each:

  • Model deprecated / rate-limited → fallback model routing
  • Tool returning malformed output → circuit breaker + escalation
  • Prompt injection detected → trajectory abort + audit entry
  • State store unavailable → read-only mode, not silent degradation

If I cannot name three plausible failure modes with written recovery paths, I would not ship the system.

The term I use

I call this verifiable agent systems for regulated domains. It is not "evals" (Hamel Husain has covered evals extensively, and I recommend his work). It is narrower: agent systems engineered from day one around constraints that banking custody also imposes — durability, determinism, dual control, evidentiary audit, recovery.

I expect some enterprise LLM work to move into this category as horizontal platforms cover more lower-risk use cases, such as customer support bots and internal knowledge Q&A. For workflows where errors have material impact, I change the evaluation question from "does it sound right" to "can I prove why it did what it did".

If you're evaluating an agent system against those five disciplines and finding gaps, write to me.

FAQ

Why persist agent state before side-effecting tool calls?

I persist agent state before any tool call that has side effects because otherwise I cannot answer what the agent knew at step N. Durable state adds latency and storage per step, but it makes replay, audit, and trajectory debugging possible after an incident.

How should tool failures be represented for an LLM agent?

I make every tool contract expose typed, exhaustive failure modes instead of unstructured exceptions or silent catches. With a schema such as a status field for ok, rate_limited, empty, or auth_error, I give the LLM expected cases it can handle, such as waiting after rate limiting.

When should an agent require human-in-the-loop approval?

I require a human-in-the-loop checkpoint or a separate validation agent with fixed rules for actions with financial, legal, or customer-facing impact. For me, that includes external communications, writes to systems of record, and anything that affects external systems or customer-visible state.

What evidence should an agent run record for auditability?

I want every run to record the input, prompt template hash, model name and version, tool invocations with arguments and returns, final output, and a timestamped record. I do not rely on logs alone; I want the trace to support replayable evidence for diagnosis.

What recovery paths should exist before production release?

Before I ship, I write down plausible production failure modes and the recovery action for each. Examples include fallback model routing for deprecation or rate limits, a circuit breaker and escalation for malformed tool output, trajectory abort on prompt injection, and read-only mode when the state store is unavailable.

Share this article

Related articles

  • Is Saying an LLM Doesn't Think Like Saying a Calculator Can't Do Numbers?

    Where the calculator analogy for LLMs holds and where it breaks: what interpretability, chain-of-thought and philosophy of mind say about thinking.

    Jul 2, 202616 min read
    #LLM#AI Reasoning#Interpretability#Philosophy of Mind
  • AI Workflow Engines for Durable, Auditable Systems

    My first LLM workflow worked in manual tests and fell apart on restart. What a durable, auditable engine actually has to own.

    Aug 17, 202612 min read
    #AI workflows#Durable State#Retries#Audit Trails#Evals#Orchestration
  • mklang: The Document Is the Program

    A declarative .mkl file for LLM-driven state machines. Models generate. The machine decides what happens next. What the language guarantees and does not.

    Oct 2, 20267 min read
    #mklang#LLM#DSL#State-Machine#Agents