deepagents: route string summarizer models through the durable seam - #1843
Open
DABH wants to merge 6 commits into
Open
deepagents: route string summarizer models through the durable seam#1843DABH wants to merge 6 commits into
DABH wants to merge 6 commits into
Conversation
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.
There was a problem hiding this comment.
🟡 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.
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.
brianstrauch
approved these changes
Sep 10, 2026
DABH
enabled auto-merge (squash)
September 10, 2026 16:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 durableTemporalModel→ Activity path as every other model call. Plaincreate_deep_agent(...)was never affected.What
The plugin turns
model="<name string>"into a durableTemporalModelby patchingdeepagents.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 — aSummarizationMiddleware("anthropic:...")constructed in a sandboxed workflow resolved aChatAnthropic):SummarizationMiddleware→ LangChain'sinit_chat_model, bound inlangchain.agents.middleware.summarizationcreate_summarization_tool_middleware→ call-time import ofdeepagents._models.resolve_modelinstall_model_patchnow covers both (samein_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.