Skip to main content
Bitfab integrates with LangChain Deep Agents (deepagents), the agent harness built on LangGraph, in Python and TypeScript. One integration records each run of a deep agent as a replayable trace: the main agent, every model call, every subagent the task tool hands work to, and every tool call nested where Deep Agents runs it, including write_todos and the built-in file tools. Canonical signatures: Python reference | TypeScript reference
Experimental (alpha): The Deep Agents integration builds on the LangGraph tool replay integration and shares its matching rules and limitations. Its API may change before it is stable.

Supported Languages

Python requires Python 3.11+ (the deepagents minimum) and deepagents 0.7 or later. TypeScript requires deepagents 1.0 or later and langchain 1.0 or later.

Quick Start

Build the agent with the integration’s createDeepAgent() / create_deep_agent() in place of Deep Agents’ own. It takes the same parameters:
The builder passes every parameter to Deep Agents unchanged, except that it adds the integration’s middleware to the main agent and to each subagent you define as a spec, so every one of their tool calls is replayable. It returns the agent itself, traced: still a Deep Agents agent of the same type, so it can be nested in another graph or exported to LangGraph Platform, with every way of running it traced (invoke, stream, streamEvents, and batch in TypeScript; invoke, ainvoke, stream, astream, batch, stream_events, and astream_events in Python). Each run records the agent input as the trace’s replayable root and the final agent state, including todos and files, as the root’s output. They return or yield exactly what the agent’s own methods do, and every other property, such as getState() / get_state(), is the agent’s own. Runtime configuration you pass at call time, such as a thread_id, is kept. In TypeScript the builder is async, because it loads deepagents when it runs. For a subagent you pass as a compiled runnable, build it with the integration’s createAgent() / create_agent(), the same drop-in for LangChain’s createAgent / create_agent, so its tool calls are replayable too. It nests under the task call in the same trace.

Building the agent yourself

If the agent is built somewhere you can’t change the call, add the two pieces by hand: pass integration.middleware in the agent’s middleware (and in each subagent spec’s middleware whose tools should be replayable), and wrap the built agent with instrument():
If the agent is called directly instead of through instrument(), it still runs, but its tool calls are not recorded as replayable spans, and the SDK logs a one-time warning saying so. getDeepAgentsIntegration() / get_deep_agents_integration() is the LangGraph integration under a Deep Agents name, so createAgent(), middleware, and instrument() work the same way for LangChain agents. Passing a name to the builder names the main agent’s span in the trace. Without it, LangGraph names it LangGraph.

What Gets Captured

Replay

Replay recorded runs through the method your app calls, or through your own handler that relays the agent’s stream. A streamed replay is drained inside the replay, and its result is the agent’s final state:
If the agent has a checkpointer and the run has a thread_id, the thread’s checkpoint at the start of the run is recorded with the trace. Replay restores it into an in-memory checkpointer, so a later turn of a conversation sees the same history, a run that resumes a human approval (Command(resume=...), including from interrupt_on) resumes the same interrupt, and the agent’s own checkpointer is never written to during replay. By default, every tool call the integration handles is marked for replay mocking: the call does not run, and it returns its recorded result instead. That covers write_todos, the file tools, your own tools, and task. A mocked task call returns the subagent’s recorded answer without running the subagent, so none of the subagent’s model calls or tools run again. File changes recorded with a file tool call are applied to the replayed agent’s files, so later steps read the same files the recorded run did. Model calls run live during replay. Use mockToolsOnReplay / mock_tools_on_replay to choose which tools are mocked:
true / True (the default) mocks every tool the integration handles, false / False mocks none, and a list mocks only the tools it names. With task left live, a subagent built through the integration runs again on replay while its own tool calls return their recordings. Replay’s mock: "all" strategy and matching mock overrides can still substitute any tool the integration handles. If a tool marked for mocking has no recorded result at that point in the run, Bitfab refuses to run it live and raises an error naming the tool. Recorded results are matched by tool name and the order of calls, as in the LangGraph integration.

Current alpha limitations

  • The built-in general-purpose subagent’s tools are not replayable one by one. Deep Agents builds that subagent itself and does not pass custom middleware to it, so its tool calls are recorded but cannot be mocked individually. Mocking its task call skips it entirely. Subagents you define are covered by the integration’s builder.
  • Async subagents are not covered. Subagents deployed on LangSmith and started as async subagents run outside the traced process.
  • TypeScript restores threads through a LangGraph run setting. The in-memory checkpointer is lent to the replayed run through the run config key LangGraph uses to lend a checkpointer to subgraphs. A LangGraph version that renames it would replay against the agent’s own checkpointer.
  • Model calls are not mocked. A replay calls the model again, so a model that picks a different tool or calls tools in a different order can reach a tool call with no matching recording.
  • Python file changes are recorded through LangGraph internals. The Python default state backend saves files through LangGraph’s internal state-write function, which Bitfab records for the length of each tool call. If a LangGraph version stops exposing it, the SDK logs a one-time warning and file changes are not restored on replay. In TypeScript the file tools return their file changes, so they are recorded with the result.
  • The todo list needs the todo-list middleware. Add todoListMiddleware() (TypeScript) or TodoListMiddleware() (Python) to the middleware if your agent should plan with a todo list; Deep Agents only adds write_todos for some model profiles.