Wink Pings

After Agents Go to Production, the Most Expensive Bug Isn’t in the Model

LangChain community spotlight recommended Soba Labs’ Simon Budziak’s production experience: two live Agent systems survived thanks to five controls. Explicit state machine, per-turn trace, evaluation gate, idempotent side effects, and low-confidence handoff to humans. Data, code, and one double CRM write are all in the article.

LangChain’s community spotlight featured an article by Soba Labs’ Simon Budziak about five controls needed to put LangGraph Agents into production. Getting an Agent working in a demo can take an afternoon; in production, a single timeout can write two CRM records.

LangChain 社区内容聚光灯海报,主题为 Five controls for agents in production

The article comes from two systems already in production: Open Loyalty’s AI SDR, which qualifies leads, answers product questions, and writes results into the CRM; and Shen.ai’s patient education assistant, which explains test results using approved medical knowledge. Both systems use LangGraph and LangSmith. LangGraph is a low-level orchestration framework that provides primitives such as state, checkpoints, interrupts, and conditional edges; it does not automatically make an Agent reliable. LangSmith handles tracing and evaluation. Simon Budziak’s conclusion is that five controls kept the systems alive.

First, some background data. LangChain’s State of Agent Engineering survey polled 1,340 people: 57.3% already run Agents in production, and 30.4% are building them. 32% cite quality as the top barrier to production, while latency is 20%. Models can usually produce an answer, but the system does not notice when the answer is wrong.

Control 1: Write the Agent as an explicit state machine

A production Agent must be debugged in sequence, not just by looking at the final answer. Open Loyalty’s AI SDR splits conversation state into stages such as intro, qualification, retrieval, sales brief, and CRM write. States are typed, and conditional edges are readable.

class SDRState(MessagesState):
    lead_id: str
    lead: dict
    score: int
    next_action: str
    kb_context: list[Document]
    thread_id: str

graph = StateGraph(SDRState)
graph.add_edge("intro", "qualify")
graph.add_conditional_edges("qualify", needs_product_qa)
graph.add_edge("retrieve_kb", "sales_brief")
graph.add_edge("sales_brief", "crm_write")
graph.add_edge("crm_write", END)

If lead routing goes wrong, the state can show which stage made the decision, what retrieval returned, and which tool produced the side effect. A prompt loop can answer what the Agent said; an explicit graph can answer what the Agent did, in what order, and with which inputs. Production incidents ask exactly the latter.

Control 2: Keep a trace for every production conversation turn

Failures that cannot be replayed are hard to fix. LangSmith leaves an end-to-end record of every conversation for both systems, including model calls, tool calls, inputs and outputs, latency, prompt versions, and run metadata. A single run ID can establish which prompt produced a given behavior and whether a tool call was the first attempt or a retry.

In the same survey, 89% of organizations have some form of Agent observability, and 62% have tracing detailed enough to see individual steps and tool calls. The gap is in action. Without traces, retrieval failures and CRM failures both look like the model having a bad day. Open Loyalty found its two important bugs in traces, not in the conversation logs.

Control 3: Every change goes through an evaluation gate

Open Loyalty built a small evaluation set from real conversations, covering pricing questions, objections, ambiguous intent, and missing fields. For every meaningful change to prompts, models, retrieval settings, or tool schemas, they run the same evaluation, checking four things: whether routing is correct, whether required fields were extracted, whether answers stay within approved materials, and whether there are unsafe or duplicate side effects.

This turns an argument about a single conversation into a regression test. Production incidents also flow back: the team classifies real errors and adds the best examples to the evaluation set. Industry practice lags here: 89% have observability, 52.4% run offline evaluation, and 37.3% run online evaluation. With traces but no evaluation gate, an Agent can see itself degrade and still ship.

Control 4: Make every side effect idempotent

Open Loyalty’s ugliest bug was not in the final response. A small number of conversations produced two CRM updates. The trace showed: a CRM write times out, the Agent retries, the second attempt succeeds, and the first attempt then also completes. One conversation, two writes.

The fix is an idempotent tool-call boundary, not a better prompt.

crm_write.invoke({
    "lead_id": state["lead_id"],
    "payload": payload,
    "idempotency_key": f"{thread_id}:{turn_id}",
})

Each write carries an idempotency key generated from the conversation and turn. Model retries and tool retries are separate decisions, and the evaluation set gains simulated timeout cases that assert the lead is updated only once per turn. LangGraph’s interrupt documentation also states this rule clearly: when a paused graph resumes, the node restarts from the beginning, and code before the interrupt runs again, so side effects at that point must be idempotent. Any node that touches money, email, or the CRM should have a key, and retry logic should assume the call may already have happened.

LangGraph Agent 生产流程图:显式状态机进入确定性置信门,分到带幂等写入的回答路径和人工审核路径,每一步都进入 LangSmith trace 和评估集

Control 5: Route low-confidence cases to humans, in code

In Shen.ai’s patient education assistant, a confident but unsupported explanation is a safety issue. Whether a question takes the normal answer path or goes to clinician review is decided in code, not in the prompt.

def should_route_to_human(state: PatientEducationState) -> str:
    if state["confidence_score"] < 0.7 or state["requires_review"]:
        return "human_review"
    return "education_module"

graph.add_conditional_edges("retrieve_kb", should_route_to_human)

The confidence gate makes uncertainty part of system state: low-confidence retrieval cannot reach the answer node, and the conversation goes to human review. Shen.ai’s tuned numbers are that about 15% of conversations go to human review, clinicians judge about 80% of those escalations to be appropriate, and after lowering the threshold from 0.8 to 0.7, unnecessary reviews fell by about 40%. These numbers describe only that system during its tuning period and are not a general benchmark. The pattern transfers to any domain where the cost of a wrong answer is higher than the cost of handing off to a human.

In the comments, reader MASA asked how to audit conversations that slip past the confidence gate. The original post does not expand on this question. It is harder than the threshold itself and worth noting separately. Prompts can make a model cautious; they cannot define when the system must stop. Conditional edges can.

Underneath, you still need persistent checkpoints

All five controls assume state survives. A gate that waits for human review is only useful if the pause is durable, so both systems write checkpoints to PostgreSQL. LangGraph’s persistence documentation recommends database checkpoints such as PostgresSaver for production, compiled into the graph with a stable thread_id.

from langgraph.checkpoint.postgres import PostgresSaver

with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    graph = builder.compile(checkpointer=checkpointer)

When a Shen.ai patient leaves and comes back, the state that the safety controls depend on is not lost. Checkpoints have three persistence modes: exit, async, and sync, trading off performance against recovery from an in-flight crash. If a long, expensive run cannot be lost, use sync.

There are more than two cases. Freedman International’s marketing localization pipeline uses similar controls, with tracing on Langfuse rather than LangSmith. This shows that the control points are traces, gates, idempotency boundaries, and human routing; vendors can change.

The five controls can be compressed into five sentences: write the workflow as an explicit state machine; trace every turn; gate every change with an evaluation set built from real conversations; give every side effect an idempotency key; when uncertain, route to a human via a conditional edge. LangGraph is used in production by companies such as Klarna, Uber, and J.P. Morgan, for reasons of inspectability and governability, not because it makes Agents smarter.

Original link: https://sobalabs.ai/blog/langgraph-agents-in-production/

发布时间: 2026-11-02 07:37