Skip to content

Add Deep Agents plugin samples - #328

Merged
DABH merged 10 commits into
mainfrom
deepagents-plugin-samples
Aug 12, 2026
Merged

Add Deep Agents plugin samples#328
DABH merged 10 commits into
mainfrom
deepagents-plugin-samples

Conversation

@DABH

@DABH DABH commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What

Samples for the Temporal ↔ LangChain Deep Agents integration (temporalio.contrib.deepagents): eight scenarios under deepagents_plugin/, each a runnable worker/starter pair with its own README, plus offline tests (fake model provider, no API keys) under tests/deepagents_plugin/.

  • hello_world — vanilla create_deep_agent(...).ainvoke(...) inside a workflow; the only change is plugins=[DeepAgentsPlugin()], and every model call becomes a Temporal Activity.
  • react_agent — the explicit per-tool Workflow-vs-Activity choice: activity_as_tool (surface an existing @activity.defn) and tool_as_activity (route an I/O LangChain tool through an activity), with per-agent activity_options via create_temporal_deep_agent.
  • human_in_the_loop — the native LangGraph interrupt/resume protocol mapped to a Temporal Query + Update; no custom shim.
  • continue_as_newrun_deep_agent carrying the conversation and the model/tool result cache across continue-as-new (server-suggested trigger by default).
  • filesystem_backendTemporalBackend(FilesystemBackend(...)): the agent's built-in file tools execute as durable deepagents.backend_op activities instead of doing I/O in workflow code.
  • subagents — sub-agents inherit the durable model automatically; delegation needs no per-sub-agent wiring.
  • streamingstreaming_topic=... publishes chunk batches to a workflow-streams topic for live subscribers while the durable result stays identical to the non-streaming path.
  • langsmith_tracing — composing DeepAgentsPlugin with LangSmithPlugin for tracing (no test; needs real API keys).

Repo registration: a deepagents dependency group (gated on Python ≥ 3.11) and the root README row (sample packages are auto-discovered).

Status

The plugin is merged to sdk-python main (temporalio/sdk-python#1644) and ships as the temporalio[deepagents] extra in the next temporalio release (> 1.31.0 — the current PyPI 1.31.0 predates the merge and does not carry the extra; next release expected early next week). Until a release with the extra is on PyPI the dependency group deliberately does not include it (an unresolvable dep would break uv lock/uv sync for everyone), and tests/deepagents_plugin/ skips collection when the plugin isn't importable — CI stays green with no plugin present. The suite README documents the interim install from sdk-python main, and the release-day follow-up is a one-line group change (swap the group's temporalio[langsmith] entry for temporalio[deepagents,langsmith] pinned to the first release with the extra). The full suite passes against merged main (8 passed).

How to run / test evidence

Interim install (documented in deepagents_plugin/README.md): install the plugin from sdk-python main, then

uv run --no-sync pytest tests/deepagents_plugin

Current result against merged sdk-python main: 8 passed, with ruff check / ruff format --check clean on the new directories.

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.

Pull request overview

Adds a new deepagents_plugin/ sample suite demonstrating how the upcoming temporalio.contrib.deepagents integration makes LangChain Deep Agents durable (model/tool/backend calls executed as Temporal Activities while the agent loop replays in Workflow code). It also introduces an optional deepagents dependency group (Python ≥ 3.11) and a guarded offline test suite under tests/deepagents_plugin/.

Changes:

  • Add eight runnable Deep Agents plugin sample scenarios under deepagents_plugin/ (worker/starter pairs + per-scenario READMEs).
  • Add offline pytest coverage for the scenarios (skipped at collection time when the plugin isn’t importable / Python < 3.11).
  • Register the sample package in pyproject.toml, update root README, and update uv.lock for the new dependency group resolution.

Reviewed changes

Copilot reviewed 43 out of 53 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
uv.lock Locks new deepagents group deps and associated transitive packages.
pyproject.toml Adds deepagents dependency group (Python ≥ 3.11) and registers deepagents_plugin as a package.
README.md Adds deepagents_plugin to the root sample list.
deepagents_plugin/init.py Package marker for the Deep Agents samples.
deepagents_plugin/README.md Suite-level documentation, prerequisites, and run instructions.
deepagents_plugin/hello_world/workflow.py Minimal durable agent workflow example.
deepagents_plugin/hello_world/run_worker.py Worker wiring with DeepAgentsPlugin.
deepagents_plugin/hello_world/run_workflow.py Starter for hello world scenario.
deepagents_plugin/hello_world/README.md Scenario documentation.
deepagents_plugin/hello_world/init.py Package marker.
deepagents_plugin/react_agent/workflow.py Tool loop example showing activity_as_tool vs tool_as_activity + explicit TemporalModel.
deepagents_plugin/react_agent/run_worker.py Worker wiring + registers the user activity tool.
deepagents_plugin/react_agent/run_workflow.py Starter for react-agent scenario.
deepagents_plugin/react_agent/README.md Scenario documentation.
deepagents_plugin/react_agent/init.py Package marker.
deepagents_plugin/human_in_the_loop/workflow.py Interrupt/resume mapping to Temporal Query + Update.
deepagents_plugin/human_in_the_loop/run_worker.py Worker wiring with plugin.
deepagents_plugin/human_in_the_loop/run_workflow.py Starter demonstrating query polling + update resume.
deepagents_plugin/human_in_the_loop/README.md Scenario documentation.
deepagents_plugin/human_in_the_loop/init.py Package marker.
deepagents_plugin/continue_as_new/workflow.py run_deep_agent continue-as-new contract example.
deepagents_plugin/continue_as_new/run_worker.py Worker wiring with plugin.
deepagents_plugin/continue_as_new/run_workflow.py Starter for continue-as-new scenario.
deepagents_plugin/continue_as_new/README.md Scenario documentation.
deepagents_plugin/continue_as_new/init.py Package marker.
deepagents_plugin/filesystem_backend/workflow.py TemporalBackend(FilesystemBackend(...)) durable file I/O example.
deepagents_plugin/filesystem_backend/run_worker.py Worker wiring with plugin.
deepagents_plugin/filesystem_backend/run_workflow.py Starter for filesystem-backend scenario.
deepagents_plugin/filesystem_backend/README.md Scenario documentation.
deepagents_plugin/filesystem_backend/init.py Package marker.
deepagents_plugin/subagents/workflow.py Sub-agent durability inheritance example.
deepagents_plugin/subagents/run_worker.py Worker wiring with plugin.
deepagents_plugin/subagents/run_workflow.py Starter for subagents scenario.
deepagents_plugin/subagents/README.md Scenario documentation.
deepagents_plugin/subagents/init.py Package marker.
deepagents_plugin/streaming/workflow.py Streaming model chunks to workflow-streams topic example.
deepagents_plugin/streaming/run_worker.py Worker wiring enabling streaming dispatch.
deepagents_plugin/streaming/run_workflow.py Starter subscribing to streamed chunks and printing live output.
deepagents_plugin/streaming/README.md Scenario documentation.
deepagents_plugin/streaming/init.py Package marker.
deepagents_plugin/langsmith_tracing/workflow.py Durable agent workflow used for tracing scenario.
deepagents_plugin/langsmith_tracing/main.py Single-process driver composing LangSmithPlugin + DeepAgentsPlugin.
deepagents_plugin/langsmith_tracing/README.md Scenario documentation (no offline test).
deepagents_plugin/langsmith_tracing/init.py Package marker.
tests/deepagents_plugin/conftest.py Collection-time guard to skip tests when plugin isn’t available / Python < 3.11.
tests/deepagents_plugin/hello_world_test.py Offline test for hello world scenario using mock_model_provider.
tests/deepagents_plugin/react_agent_test.py Offline test for tool loop scenario.
tests/deepagents_plugin/human_in_the_loop_test.py Offline test for interrupt/resume scenario.
tests/deepagents_plugin/continue_as_new_test.py Offline tests for run_deep_agent contract + continue-as-new carry behavior.
tests/deepagents_plugin/filesystem_backend_test.py Offline test for durable filesystem backend ops.
tests/deepagents_plugin/subagents_test.py Offline test for sub-agent durability inheritance.
tests/deepagents_plugin/streaming_test.py Offline test for streaming topic publishing.
tests/deepagents_plugin/init.py Test package marker.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deepagents_plugin/human_in_the_loop/workflow.py
Comment thread tests/deepagents_plugin/conftest.py Outdated
Comment thread tests/deepagents_plugin/streaming_test.py Outdated
DABH added 4 commits July 14, 2026 18:23
…test

- human_in_the_loop: clear the pending-approval prompt on resume so the
  query honors its documented contract, and add an update validator that
  rejects decisions other than approve/reject before they enter history
- tests conftest: replace find_spec with a guarded import so collection
  is skipped when the plugin package exists but its runtime deps do not
- streaming test: replace the fixed sleep-then-cancel drain with a
  condition-based subscriber awaited via wait_for, matching the other
  streaming tests
…tests

- CODEOWNERS: add /deepagents_plugin/ and /tests/deepagents_plugin/ for the
  AI SDK team, matching the sibling AI suites
- Suite README: state the Python >= 3.11 floor in Prerequisites (on 3.10 the
  dependency group silently resolves to nothing)
- streaming/run_workflow.py: drain the subscriber until the full durable
  result has been printed (bounded by a timeout) instead of cancelling it
  immediately and dropping tail chunks
- subagents_test: script the coordinator -> task tool -> researcher ->
  synthesis path so the delegation headline is actually exercised, and assert
  three invoke_model activities in history
- hello_world_test: assert the model call was scheduled as a
  deepagents.invoke_model activity (shared count_scheduled_activities helper)
- pyproject: cap langchain-anthropic at <2 like its group siblings
- Drop the workflow.unsafe.imports_passed_through() guards from all eight
  workflows: the plugin passes the deepagents/LangChain import tree through
  the sandbox itself, and its README highlights bare imports as the intended
  developer experience. hello_world carries a comment explaining why no
  guard is needed. Verified by the full test suite (real sandboxed worker)
  plus an ad-hoc sandbox run of the untested langsmith_tracing workflow.
- continue_as_new: use run_deep_agent's default server-suggested mode (the
  documented recommended mode) instead of a hardcoded event threshold; the
  probe test retains continue_as_new_after=1 as explicit-override coverage.
- react_agent: build the agent with create_temporal_deep_agent and per-agent
  activity_options — the recommended way to scope model-call timeouts —
  replacing the bare TemporalModel construction.
- Extend the history seam assertions to every testable scenario: react_agent
  (get_weather + invoke_tool), filesystem_backend (backend_op >= 2),
  streaming (invoke_model_streaming, no invoke_model), human_in_the_loop
  (invoke_tool after resume).
- HITL README: note that a production loop would re-check __interrupt__
  after each resume.
@DABH
DABH marked this pull request as ready for review August 11, 2026 22:31
@DABH
DABH requested review from a team as code owners August 11, 2026 22:31
DABH added 4 commits August 11, 2026 17:33
)

The plugin is on sdk-python main and ships as the temporalio[deepagents]
extra in the next release (>= 1.31.0); it is not on PyPI yet. Point the
interim install at sdk-python main (the per-plugin overlay path retired
at merge), name the real post-release group entry in the pyproject note,
and drop the plugin-ordering claim from langsmith_tracing — registration
order does not matter. Suite verified against merged main: 8 passed.
…503S0JPFMRFBEDGY

# Conflicts:
#	pyproject.toml
The previous merge commit was pushed with unresolved conflict markers
in pyproject.toml. Resolve to main's setuptools auto-discovery (which
finds deepagents_plugin without registration) and regenerate the lock.

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.

Pull request overview

Copilot reviewed 45 out of 55 changed files in this pull request and generated no new comments.

Suppressed comments (2)

deepagents_plugin/human_in_the_loop/workflow.py:91

  • resume can be accepted even when the workflow is not actually paused (or even before it reaches the interrupt). That allows a client to pre-approve and skip the intended wait_condition, and it can also accept multiple resumes. Add a state check in the update validator so the update is only accepted when there is a pending approval and the workflow hasn’t already resumed.
    def validate_resume(self, decision: str) -> None:
        # Runs before the update is accepted, keeping invalid decisions out of
        # workflow history entirely. Only the decisions this workflow feeds to
        # `Command(resume=...)` are allowed.
        if decision not in ("approve", "reject"):

deepagents_plugin/langsmith_tracing/main.py:27

  • This comment implies plugin registration order matters, but the scenario README states order does not matter. Align the in-code comment with the documented behavior to avoid confusing readers.
            # Register observability first, then the Deep Agents plugin.

The review's headline: temporalio 1.31.0 already shipped on PyPI
(2026-07-29) WITHOUT the deepagents extra, so every ">= 1.31.0" claim
in the install story was wrong and the documented group swap would
have resolved to an extra-less release. Floors now say "> 1.31.0 /
the first release that ships the extra", and the group's temporalio
pin rises to >= 1.31.0 to match the repo base pin.

Also: the conftest collection guard now announces itself via
pytest_report_header instead of silently collecting nothing, and its
docstring drops the retired temporalio-contrib-deepagents dist story;
the continue-as-new probe pins the first run's close event to
CONTINUED_AS_NEW (a loop-in-one-run regression previously passed);
the HITL suite covers the validator's invalid-decision rejection and
the reject path (guarded tool never runs as an activity); scenario
READMEs name the Python floor and defer to the suite setup instead of
repeating it; the streaming README describes what the workflow
actually drives (TemporalModel.astream).
@DABH
DABH merged commit 05070f6 into main Aug 12, 2026
11 checks passed
@DABH
DABH deleted the deepagents-plugin-samples branch August 12, 2026 18:23
DABH added a commit to temporalio/documentation that referenced this pull request Aug 12, 2026
The samples merged (temporalio/samples-python#328) after these snippet
blocks were populated, and the merged code dropped the sandbox import
guards, adopted create_temporal_deep_agent with per-agent
activity_options, and switched continue-as-new to the server-suggested
default. Re-sync all eleven snipsync bodies to what is actually on
samples-python main so the page matches what snipsync will maintain.
lennessyy added a commit to temporalio/documentation that referenced this pull request Aug 12, 2026
* Add deepagents integration docs

* Populate Deep Agents snippet blocks and alphabetize integrations entry

Fill each snipsync wrapper on the Deep Agents page with the code and
source link extracted from the samples-python deepagents_plugin sources,
matching the checked-in snipsync output used across the docs. Move the
Deep Agents entry in integrations-data.json to its alphabetical slot
after the Datadog entries.

* Refresh Deep Agents snippets from merged samples-python main

The samples merged (temporalio/samples-python#328) after these snippet
blocks were populated, and the merged code dropped the sandbox import
guards, adopted create_temporal_deep_agent with per-agent
activity_options, and switched continue-as-new to the server-suggested
default. Re-sync all eleven snipsync bodies to what is actually on
samples-python main so the page matches what snipsync will maintain.

* Point the install instructions at sdk-python main until the release ships

The plugin is merged to main but the current PyPI release predates the
extra, so a plain temporalio[deepagents] install does not work yet.
Lead with the install-from-main command and note the plain extra takes
over once the next SDK release is on PyPI.

* Fix the four findings Copilot suppressed in its latest review

All four were real: the composition section still required registering
the observability plugin first (order does not matter per the merged
plugin and samples); the react_agent prose described TemporalModel(...)
while the refreshed snippet builds via create_temporal_deep_agent; the
unwrapped-tool warning was described as "never silent" when the plugin
frames it as best-effort; and the continue-as-new section claimed a
messages/todos snapshot when the snapshot is exactly messages plus the
result cache (todos only gate whether to continue). Also aligns the
CAN intro with run_deep_agent's server-suggested default.

* docs: drop redundant experimental admonitions from Deep Agents page

The release header already states that this is a prerelease whose API
may change, so the :::info and :::note blocks repeating that added
nothing.

The :::note also carried the Python version requirement, which the
header does not cover. That moves into Prerequisites as a bullet.

---------

Co-authored-by: Lenny Chen <lenny.chen@temporal.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants