Trading  ·  BraivIQ AI Engineering Playbook

Trading AI Architecture For Trade Breaks: Checkpoints, Retries, A Step Budget And A Human Queue

A trading AI architecture for trade breaks has to survive a crash without sending the same chaser twice, stop an agent that keeps searching, and hand anything it cannot finish to a person. LangGraph 1.2.17 and 1.2.18, released on 24 and 26 October 2026, tightened exactly these behaviours: an explicit recursion limit, error handlers that recover on every path, and the last checkpoint streamed when a run stops. This playbook builds the same guarantees in plain Python, with checkpointed steps, idempotent side effects, a step budget and an operations lead approving every chaser.

Published  ·  Updated  ·  11 min read  ·  By BraivIQ Engineering

Trading floor screens in a dark room, illustrating a trading AI architecture for crash-safe trade-break workflows

Key takeaways

  • LangGraph 1.2.17 (24 October 2026) applies an explicit recursion_limit equal to the default, and 1.2.18 (26 October) lets error_handler recover on every path and streams the last checkpoint of a run stopped by the recursion limit.
  • Checkpoint each step under a key of break and step, so a resumed run returns the stored result instead of repeating a side effect.
  • Give every agent loop a step budget. When it runs out, stop, keep the partial work and hand the break to a person.
  • Send failures that survive the retry limit to a human queue with the error, not into an endless retry.
  • This is engineering for operations workflows. It uses sample data and contains no trading signals or advice.

A dependable trading AI architecture treats every trade break as a small, restartable workflow. Load the trade and custodian records, let the model draft an explanation and a chaser, queue the chaser for approval, and checkpoint each step. If the process dies, it resumes where it stopped and does not send anything twice. If the model loops or keeps failing, a person gets the break with the work done so far.

Both samples are standard library Python on 3.14.4, using sqlite3 for checkpoints. Trades and references are sample data.

What changed in LangGraph this week?

LangGraph 1.2.17, released on 24 October 2026, applies an explicit recursion_limit equal to the default. Version 1.2.18, released on 26 October, lets error_handler recover on every path and stream failed task results, streams the last checkpoint of a run stopped by interrupt_after or the recursion limit, and sets DeltaChannel to take a full snapshot every 100 updates instead of 1,000. checkpoint 4.3.1 now rejects NUL bytes in namespace labels. If you run LangGraph, upgrade and re-test your error paths. If you do not, the same guarantees are worth building yourself.

What does a trading AI architecture for trade breaks look like?

Trading AI architecture diagram for trade breaks: a break loads trade and custodian sample records, a checkpoint store keeps one row per step so a resumed run does not repeat work, a step budget stops a looping agent, the model drafts a chaser with retries, failures after the retry limit go to a human queue, an operations lead approves each chaser before it is sent and every step goes to an audit log.
Engineering only. Sample data. No trading signals. Tap to open full size.

How do you make each step crash-safe?

break_workflow.py
"""A trade-break workflow that survives a crash: checkpointed steps, idempotent side effects,
and an error handler that sends failures to a person instead of retrying for ever.

The same ideas appear in LangGraph 1.2.18 (26 October 2026), which lets error_handler recover on every
path, and checkpoint 4.3.1, which rejects NUL bytes in namespace labels. Python 3.14 standard library
only (sqlite3). Sample trades only.
"""
from __future__ import annotations

import sqlite3
from collections.abc import Callable

db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE steps (break_id TEXT, step TEXT, result TEXT, PRIMARY KEY (break_id, step))")
db.execute("CREATE TABLE human_queue (break_id TEXT PRIMARY KEY, reason TEXT)")
SENT: list[str] = []
CRASH = {"armed": True}


def checkpoint(break_id: str, step: str, fn: Callable[[], str]) -> str:
    row = db.execute("SELECT result FROM steps WHERE break_id=? AND step=?", (break_id, step)).fetchone()
    if row:
        return str(row[0])  # already done before the crash: do not repeat the side effect
    result = fn()
    db.execute("INSERT INTO steps VALUES (?,?,?)", (break_id, step, result))
    return result


def draft_chaser(break_id: str) -> str:
    if CRASH["armed"]:
        CRASH["armed"] = False
        raise ConnectionError("model endpoint timed out")
    return f"Draft chaser for {break_id}: confirm settlement date"


def run(break_id: str, max_attempts: int = 2) -> str:
    if "\x00" in break_id:
        raise ValueError("NUL byte in break id")
    checkpoint(break_id, "load", lambda: "loaded TRD-88302 and custodian record")
    for attempt in range(1, max_attempts + 1):
        try:
            draft = checkpoint(break_id, "draft", lambda: draft_chaser(break_id))
            return checkpoint(break_id, "queue_for_approval", lambda: (SENT.append(draft) or "awaiting ops lead"))
        except ConnectionError as exc:
            if attempt == max_attempts:
                db.execute("INSERT OR IGNORE INTO human_queue VALUES (?,?)", (break_id, str(exc)))
                return "sent to human queue"
    return "unreachable"


if __name__ == "__main__":
    print("run 1:", run("BRK-1001"))
    print("run 2 (resume):", run("BRK-1001"))
    print("chasers queued once:", len(SENT))
    CRASH["armed"] = True
    print("max_attempts=1:", run("BRK-1002", max_attempts=1), db.execute("SELECT * FROM human_queue").fetchall())

Python 3.14.4, standard library only. Run once as shown. Sample trades only.

The first run times out while drafting, retries and queues the chaser. The second run reads every step from the checkpoint table and returns without queuing it again, so only one chaser exists. With a retry limit of one, the timeout sends BRK-1002 to the human queue with the error text. The NUL byte check mirrors the change in checkpoint 4.3.1.

How do you stop an agent that keeps searching?

loop_guard.py
"""A step budget for agent loops on trade breaks: stop at a fixed limit and hand over to a person.

LangGraph 1.2.17 (24 October 2026) applies an explicit recursion_limit equal to the default, and 1.2.18
streams the last checkpoint of a run stopped by the recursion limit. The same rule applies in any
framework: decide the limit, log the stop, and keep the partial work for the reviewer.
Python 3.14 standard library only. Sample data only.
"""
from __future__ import annotations

from collections.abc import Iterator


class StepBudgetExceeded(RuntimeError):
    pass


def guarded(steps: Iterator[str], limit: int) -> list[str]:
    done: list[str] = []
    for n, step in enumerate(steps, start=1):
        if n > limit:
            raise StepBudgetExceeded(f"stopped after {limit} steps, last: {done[-1]}")
        done.append(step)
    return done


def agent_that_keeps_searching() -> Iterator[str]:
    n = 0
    while True:  # e.g. a model that keeps asking for one more custodian file
        n += 1
        yield f"search custodian file {n}"


if __name__ == "__main__":
    print(guarded(iter(["load break", "match trade", "draft chaser"]), limit=8))
    try:
        guarded(agent_that_keeps_searching(), limit=8)
    except StepBudgetExceeded as exc:
        print("handed to ops lead:", exc)

Python 3.14.4, standard library only. Run once as shown. Sample data only.

A normal break finishes in three steps. An agent that keeps asking for one more custodian file stops at eight and the break goes to the operations lead with the last step recorded. Choose the budget from your own runs, log every stop and review the stops weekly, because a rising count usually means missing data rather than a weak model.

What breaks in production?

  • **Side effects outside the checkpoint.** Anything that sends, books or writes must be inside a checkpointed step with a stable key, or a resume will repeat it.
  • **Keys that change between runs.** Use the break reference, never a timestamp or a random ID, as the checkpoint key.
  • **Retries that hide data problems.** If the same break fails on every retry, the data is usually wrong. Send it to a person early.
  • **Unbounded snapshots.** Long-running threads grow storage. LangGraph 1.2.18 changed its default snapshot frequency for this reason, so measure your own growth.
  • **Approvals bypassed on resume.** A resumed run must still wait for the approval step. Never mark a chaser as sent until a person approves it.

What are the alternatives to hand-rolled checkpoints?

OptionGood fitTrade-off
LangGraph with a durable checkpointerAgent graphs with interrupts for approvalKeep up with releases and re-test error paths
A workflow engine such as TemporalLong-running workflows across servicesMore infrastructure, strong durability
A database job table, as aboveOne team, a few workflow typesSimple, but you build retries and visibility yourself

Our earlier playbook on durable approvals covers approvals that wait for days, and our T+1 worked example covers confirmation exceptions. For the deadline context, read our blog on trade confirmation automation for T+1.

Where should a trading operations team start?

Pick the break type with the most chasers and put checkpointing and a step budget around it before adding more model calls. Our trade allocations and confirmations workflow follows this pattern, and a 14-day Proof Run puts it on your own sample breaks. As a Workflow Automation Agency we keep the person in charge of every chaser.

Frequently asked questions

What changed in LangGraph 1.2.18?

Released on 26 October 2026, it lets error_handler recover on every path and stream failed task results, streams the last checkpoint of a run stopped by interrupt_after or the recursion limit, and takes a full DeltaChannel snapshot every 100 updates by default.

How do you stop an AI agent from sending the same message twice after a crash?

Put the send inside a checkpointed step keyed by a stable reference such as the break ID. On resume, the workflow finds the stored result and skips the send.

Does this architecture make trading decisions?

No. It prepares explanations and chasers for operations staff, who approve every message. It contains no trading signals, strategies or advice.

References

  1. LangChain (GitHub), "langgraph 1.2.18 release notes", 26 October 2026. https://github.com/langchain-ai/langgraph/releases/tag/1.2.18
  2. LangChain (GitHub), "langgraph 1.2.17 release notes", 24 October 2026. https://github.com/langchain-ai/langgraph/releases/tag/1.2.17
  3. LangChain (GitHub), "LangGraph releases, including checkpoint 4.3.1", 26 October 2026. https://github.com/langchain-ai/langgraph/releases