Skip to content

deepagents: route string summarizer models through the durable seam - #1843

Open
DABH wants to merge 6 commits into
mainfrom
deepagents-summarization-seam
Open

deepagents: route string summarizer models through the durable seam#1843
DABH wants to merge 6 commits into
mainfrom
deepagents-summarization-seam

Conversation

@DABH

@DABH DABH commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

TLDR: If you create a summarization middleware with a model name string (e.g. SummarizationMiddleware("anthropic:claude-sonnet-4-5", ...)), the summarizer's LLM calls ran inside the workflow instead of as Activities — breaking determinism and replay. This PR makes those calls go through the same durable TemporalModel → Activity path as every other model call. Plain create_deep_agent(...) was never affected.

What

The plugin turns model="<name string>" into a durable TemporalModel by patching deepagents.graph.resolve_model — but two summarization paths resolve strings through other bindings and were building real provider clients inside the workflow (replay-unsafe; confirmed live — a SummarizationMiddleware("anthropic:...") constructed in a sandboxed workflow resolved a ChatAnthropic):

  • SummarizationMiddleware → LangChain's init_chat_model, bound in langchain.agents.middleware.summarization
  • create_summarization_tool_middleware → call-time import of deepagents._models.resolve_model

install_model_patch now covers both (same in_workflow() gate; the LangChain binding is best-effort so an upstream module move degrades gracefully and the regression test catches it). The default agent stack was never affected — it receives the already-resolved model.

Tests

One in-workflow regression pin per seam, asserting the resolved summarizer is a TemporalModel. Full deepagents suite: 34 passed; all lint/type/docs gates clean.

SummarizationMiddleware and create_summarization_tool_middleware
resolve a model NAME STRING through seams the plugin did not patch:
LangChain's summarization middleware resolves via init_chat_model
(bound at the top of langchain.agents.middleware.summarization), and
the tool-middleware helper via a call-time import of
deepagents._models.resolve_model. Constructed in-workflow with a
string — the documented way to customize the summarizer's trigger,
keep policy, or prompt — either path built a real provider client
inside the workflow and would run compaction LLM calls there:
nondeterministic, replay-unsafe, and invisible until a conversation
grew past its trigger (demonstrated live: the middleware resolved a
ChatAnthropic inside a sandboxed workflow).

install_model_patch now covers both additional bindings, gated on
workflow.in_workflow() like the existing graph seam, and
uninstall_model_patch restores them. The DEFAULT stack was never
affected: create_deep_agent resolves the agent model through the
patched graph seam before handing the middleware an already-durable
instance. Regression tests pin the resolved type for both explicit
string-model paths.
@DABH
DABH requested review from a team as code owners September 10, 2026 05:54
@DABH DABH added the ai-sdk Related to AI integrations label Sep 10, 2026
@brianstrauch
brianstrauch requested a balanced review from Copilot September 10, 2026 16:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The best-effort LangChain patch silently restores replay-unsafe behavior when its internal seam changes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Routes string-configured DeepAgents summarization models through TemporalModel, preserving workflow determinism.

Changes:

  • Patches both DeepAgents and LangChain summarization resolution seams.
  • Adds regression tests for both middleware paths.
  • Documents the fix in the changelog.
File summaries
File Description
temporalio/contrib/deepagents/_model.py Extends durable model patching to summarization paths.
tests/contrib/deepagents/test_summarization.py Verifies string summarizers resolve to TemporalModel.
CHANGELOG.md Records the user-facing fix.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread temporalio/contrib/deepagents/_model.py Outdated
The LangChain-internal init_chat_model binding was guarded best-effort,
so an upstream module move silently restored the in-workflow provider
client this patch exists to prevent. Patch
SummarizationMiddleware.__init__ on deepagents' class instead —
pre-resolving a string model before the middleware delegates to
LangChain — which sits inside this package's deepagents version pin
and therefore needs no guard: a missing seam is a broken install and
fails the worker at startup.
@DABH
DABH enabled auto-merge (squash) September 10, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-sdk Related to AI integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants