|
| 1 | +# Deep Agents Samples |
| 2 | + |
| 3 | +These samples demonstrate the [Temporal Deep Agents plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/deepagents), |
| 4 | +which makes [LangChain Deep Agents](https://github.com/langchain-ai/deepagents) |
| 5 | +durable. Build your agent with `create_deep_agent(...)` inside a |
| 6 | +`@workflow.defn` and add `DeepAgentsPlugin()` to your client — each LLM call and |
| 7 | +each I/O tool/backend operation becomes a Temporal Activity, while the agent's |
| 8 | +control loop runs (and deterministically replays) inside the Workflow. |
| 9 | + |
| 10 | +> **Experimental.** The `temporalio.contrib.deepagents` plugin is experimental |
| 11 | +> and its API may change. |
| 12 | +
|
| 13 | +`DeepAgentsPlugin` is a **client-level** plugin: add it to `Client.connect(...)` |
| 14 | +and the SDK propagates it to any Worker built from that client. Add it on exactly |
| 15 | +one side. |
| 16 | + |
| 17 | +## Samples |
| 18 | + |
| 19 | +| Sample | Description | |
| 20 | +|--------|-------------| |
| 21 | +| [hello_world](hello_world) | Minimal single-shot Deep Agent; a bare `model=` string auto-routed through the model activity. Start here. | |
| 22 | +| [react_agent](react_agent) | Tool-calling loop showing the explicit per-tool choice: `activity_as_tool` for an existing activity, `tool_as_activity` for an I/O tool, plus per-agent `activity_options` via `create_temporal_deep_agent`. | |
| 23 | +| [human_in_the_loop](human_in_the_loop) | Pause on `interrupt_on` and resume via the native LangGraph protocol, mapped to a Temporal Query + Update. | |
| 24 | +| [continue_as_new](continue_as_new) | Long-running agent that carries messages and the model/tool result cache across continue-as-new via `run_deep_agent`. | |
| 25 | +| [filesystem_backend](filesystem_backend) | Durable real filesystem I/O by wrapping a `FilesystemBackend` in `TemporalBackend`. | |
| 26 | +| [subagents](subagents) | Durability propagates across the agent tree — sub-agent model calls become activities with no per-sub-agent wiring. | |
| 27 | +| [streaming](streaming) | Stream model chunks to external subscribers via `streaming_topic` + `WorkflowStream`, keeping the durable result identical. | |
| 28 | +| [langsmith_tracing](langsmith_tracing) | Compose `DeepAgentsPlugin` with `LangSmithPlugin` for durable execution + LLM tracing. | |
| 29 | + |
| 30 | +## Prerequisites |
| 31 | + |
| 32 | +> **Python ≥ 3.11 required.** `deepagents` (and therefore the plugin) does not |
| 33 | +> support older interpreters. On Python 3.10 the `deepagents` dependency group |
| 34 | +> resolves to nothing, so `uv sync` silently installs none of the dependencies |
| 35 | +> below. |
| 36 | +
|
| 37 | +1. Install dependencies: |
| 38 | + |
| 39 | + ```bash |
| 40 | + uv sync --group deepagents |
| 41 | + ``` |
| 42 | + |
| 43 | + > The Deep Agents plugin ships as the `temporalio[deepagents]` extra. It |
| 44 | + > is merged to `sdk-python` `main` but the current PyPI release (1.31.0) |
| 45 | + > predates the merge and does not carry the extra, so the `deepagents` |
| 46 | + > group above does not include it yet. Until a release ships the extra |
| 47 | + > (> 1.31.0), install it from main: |
| 48 | + > |
| 49 | + > ```bash |
| 50 | + > uv pip install "temporalio[deepagents] @ git+https://github.com/temporalio/sdk-python.git" |
| 51 | + > ``` |
| 52 | + > |
| 53 | + > This builds the SDK from source (including its Rust core), so expect a |
| 54 | + > few minutes on first install. Once a release with the extra is on PyPI |
| 55 | + > this step goes away: `temporalio[deepagents]` joins the `deepagents` |
| 56 | + > group and a plain `uv sync --group deepagents` is all you need. |
| 57 | +
|
| 58 | +2. Configure a model provider. The samples use |
| 59 | + `anthropic:claude-sonnet-4-5`, which needs an Anthropic API key: |
| 60 | +
|
| 61 | + ```bash |
| 62 | + export ANTHROPIC_API_KEY=... |
| 63 | + ``` |
| 64 | +
|
| 65 | + To use a different provider, change the `model=` string in the sample's |
| 66 | + `workflow.py` and set that provider's credentials (the plugin resolves the |
| 67 | + model worker-side via LangChain's `init_chat_model`). |
| 68 | + |
| 69 | +3. Start a [Temporal dev server](https://docs.temporal.io/cli#start-dev-server): |
| 70 | + |
| 71 | + ```bash |
| 72 | + temporal server start-dev |
| 73 | + ``` |
| 74 | + |
| 75 | +## Running a Sample |
| 76 | + |
| 77 | +> **Use `uv run --no-sync`.** Because the plugin is installed out-of-band |
| 78 | +> from sdk-python main (see Prerequisites) and is not yet in any dependency |
| 79 | +> group, a bare `uv run` or `uv sync` re-syncs the environment to the lockfile |
| 80 | +> first and uninstalls it. `--no-sync` runs against the environment as-is. |
| 81 | +> (Once a released `temporalio[deepagents]` joins the `deepagents` group, the |
| 82 | +> flag becomes unnecessary.) |
| 83 | +
|
| 84 | +Most samples have two scripts. Start the Worker first, then the Workflow starter |
| 85 | +in a separate terminal: |
| 86 | + |
| 87 | +```bash |
| 88 | +# Terminal 1: start the Worker |
| 89 | +uv run --no-sync deepagents_plugin/<sample>/run_worker.py |
| 90 | + |
| 91 | +# Terminal 2: start the Workflow |
| 92 | +uv run --no-sync deepagents_plugin/<sample>/run_workflow.py |
| 93 | +``` |
| 94 | + |
| 95 | +For example, to run the hello world sample: |
| 96 | + |
| 97 | +```bash |
| 98 | +# Terminal 1 |
| 99 | +uv run --no-sync deepagents_plugin/hello_world/run_worker.py |
| 100 | + |
| 101 | +# Terminal 2 |
| 102 | +uv run --no-sync deepagents_plugin/hello_world/run_workflow.py |
| 103 | +``` |
| 104 | + |
| 105 | +The `langsmith_tracing` sample instead bundles the worker and starter into a |
| 106 | +single driver: |
| 107 | + |
| 108 | +```bash |
| 109 | +uv run --no-sync deepagents_plugin/langsmith_tracing/main.py |
| 110 | +``` |
| 111 | + |
| 112 | +## Key Features Demonstrated |
| 113 | + |
| 114 | +- **Durable model invocation** — every LLM call runs in an `invoke_model` |
| 115 | + activity with configurable timeouts and retries; a bare `model=` string is |
| 116 | + auto-routed, or use `create_temporal_deep_agent(..., activity_options=...)` |
| 117 | + to scope model-call options per agent (recommended). |
| 118 | +- **Explicit Workflow-vs-Activity tool choice** — `activity_as_tool`, |
| 119 | + `tool_as_activity`, and `TemporalBackend` move I/O out of workflow code. |
| 120 | +- **Human-in-the-loop** — the native LangGraph `interrupt_on` return value |
| 121 | + mapped to a Temporal Query and Update. |
| 122 | +- **Long-lived agents** — `run_deep_agent(...)` carries messages and the result |
| 123 | + cache across server-suggested (or explicitly thresholded) continue-as-new. |
| 124 | +- **Sub-agent durability** — sub-agents inherit the durable model object with no |
| 125 | + extra wiring. |
| 126 | +- **Streaming** — forward model chunks to external subscribers while keeping the |
| 127 | + durable result unchanged. |
| 128 | +- **Observability** — compose with `LangSmithPlugin` for tracing. |
| 129 | + |
| 130 | +## Related |
| 131 | + |
| 132 | +- [Temporal Deep Agents plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/deepagents) |
| 133 | +- [LangChain Deep Agents](https://github.com/langchain-ai/deepagents) |
| 134 | +- [langgraph_plugin](../langgraph_plugin) — for agents built directly as LangGraph graphs |
0 commit comments