You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/durable_execution/temporal.md
+9-332Lines changed: 9 additions & 332 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -185,343 +185,20 @@ The event stream handler function will receive the agent [run context][pydantic_
185
185
As the streaming model request activity, workflow, and workflow execution call all take place in separate processes, passing data between them requires some care:
186
186
187
187
- To get data from the workflow call site or workflow to the event stream handler, you can use a [dependencies object](#agent-run-context-and-dependencies).
188
-
- To get data from the event stream handler to the workflow, workflow call site, or a frontend, you need to use an external system that the event stream handler can write to and the event consumer can read from, like a message queue. You can use the dependency object to make sure the same connection string or other unique ID is available in all the places that need it.
188
+
- To get data from the event stream handler to the workflow, workflow call site, or a frontend, you need to use an external system that the event stream handler can write to and the event consumer can read from. Alternatively, you can use Temporal's built-in signals and queries to pass events from activities to the workflow and from the workflow to the caller.
Assuming your project has the following structure:
196
-
```
197
-
project/
198
-
├── src/
199
-
│ ├── agents.py
200
-
│ ├── datamodels.py
201
-
│ ├── streaming_handler.py
202
-
│ ├── utils.py
203
-
│ └── workflow.py
204
-
└── pyproject.toml
205
-
206
-
```
207
-
208
-
```py {title="utils.py" test="skip"}
209
-
import os
210
-
from copy import copy
211
-
212
-
import yaml
213
-
214
-
215
-
defrecursively_modify_api_key(conf):
216
-
"""
217
-
Recursively replace API key placeholders with environment variable values.
218
-
219
-
This function traverses a configuration dictionary and replaces any keys
220
-
containing 'api_key' with the corresponding environment variable value.
221
-
It handles nested dictionaries and lists recursively.
222
-
223
-
Args:
224
-
conf: The configuration dictionary to process.
225
-
226
-
Returns:
227
-
A copy of the configuration with API keys replaced by environment variable values.
228
-
"""
229
-
230
-
definner(_conf):
231
-
for key, value in _conf.items():
232
-
ifisinstance(value, dict):
233
-
inner(value)
234
-
elifisinstance(value, list):
235
-
iflen(value) >0andisinstance(value[0], dict):
236
-
for item in value:
237
-
inner(item)
238
-
else:
239
-
_conf[key] = [os.environ.get(str(v), v) for v in value]
240
-
elifisinstance(value, str):
241
-
_conf[key] = os.environ.get(value, value)
242
-
else:
243
-
_conf[key] = value
244
-
245
-
copy_conf = copy(conf)
246
-
inner(copy_conf)
247
-
return copy_conf
248
-
249
-
250
-
defread_config_yml(path):
251
-
"""
252
-
Read and process a YAML configuration file.
253
-
254
-
This function reads a YAML file, processes it to replace API key placeholders
255
-
with environment variable values, and returns the processed configuration.
256
-
257
-
Args:
258
-
path: The path to the YAML configuration file.
259
-
260
-
Returns:
261
-
dict: The parsed and processed YAML content as a Python dictionary.
262
-
"""
263
-
withopen(path) as f:
264
-
configs = yaml.safe_load(f)
265
-
recursively_modify_api_key(configs)
266
-
return configs
267
-
```
268
-
269
-
```py {title="datamodels.py" test="skip"}
270
-
from enum import Enum
271
-
272
-
from pydantic import BaseModel
273
-
274
-
275
-
classAgentDependencies(BaseModel):
276
-
workflow_id: str
277
-
run_id: str
192
+
For a complete working example of streaming with Temporal using signals and queries, see the [temporal_streaming example](https://github.com/pydantic/pydantic-ai/tree/main/examples/pydantic_ai_examples/temporal_streaming). This example demonstrates:
278
193
194
+
- How to use an [`event_stream_handler`][pydantic_ai.agent.EventStreamHandler] to capture agent events in activities
195
+
- Using Temporal signals to send events from activities to the workflow
196
+
- Using Temporal queries to poll events from the workflow to the caller
197
+
- Setting up dependencies to pass workflow identification for signal routing
198
+
- Integrating MCP toolsets and custom tools with streaming
199
+
- Complete project structure with all necessary files
279
200
280
-
classEventKind(str, Enum):
281
-
CONTINUE_CHAT='continue_chat'
282
-
EVENT='event'
283
-
RESULT='result'
284
-
285
-
286
-
classEventStream(BaseModel):
287
-
kind: EventKind
288
-
content: str
289
-
```
290
-
291
-
292
-
```py {title="agents.py" test="skip"}
293
-
from datetime import timedelta
294
-
295
-
from mcp_run_python import code_sandbox
296
-
from pydantic_ai import Agent, FilteredToolset, ModelSettings, RunContext
297
-
from pydantic_ai.durable_exec.temporal import TemporalAgent
298
-
from pydantic_ai.mcp import MCPServerStdio
299
-
from pydantic_ai.models.anthropic import AnthropicModel
300
-
from pydantic_ai.providers.anthropic import AnthropicProvider
# This signal is invoked by streaming_handler, pushing event for every async loop
523
-
self.events.append(event_stream)
524
-
```
201
+
The example includes a Yahoo Finance search agent with Python code execution capabilities, showing how to stream tool calls, model responses, and results in real-time during workflow execution.
0 commit comments