Skip to content

Commit 5f4f051

Browse files
chore: sync code snippets via snipsync (#5030)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 513b9e4 commit 5f4f051

3 files changed

Lines changed: 63 additions & 98 deletions

File tree

docs/develop/python/integrations/google-adk.mdx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ that starts a Workflow to the Workflow itself, and the Worker side runs the agen
117117
```py
118118
plugin = GoogleAdkPlugin()
119119

120-
client = await Client.connect("localhost:7233", plugins=[plugin])
120+
client = await Client.connect(
121+
os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), plugins=[plugin]
122+
)
121123

122124
worker = Worker(
123125
client,
@@ -146,7 +148,10 @@ code is linked to the run.
146148
{/* SNIPSTART google-adk-agents-basic-starter */}
147149
[google_adk_agents/basic/run_hello_world_workflow.py](https://github.com/temporalio/samples-python/blob/main/google_adk_agents/basic/run_hello_world_workflow.py)
148150
```py
149-
client = await Client.connect("localhost:7233", plugins=[GoogleAdkPlugin()])
151+
client = await Client.connect(
152+
os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"),
153+
plugins=[GoogleAdkPlugin()],
154+
)
150155

151156
result = await client.execute_workflow(
152157
HelloWorldAgentWorkflow.run,
@@ -192,7 +197,9 @@ class WeatherAgentWorkflow:
192197
```py
193198
plugin = GoogleAdkPlugin()
194199

195-
client = await Client.connect("localhost:7233", plugins=[plugin])
200+
client = await Client.connect(
201+
os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), plugins=[plugin]
202+
)
196203

197204
worker = Worker(
198205
client,

docs/develop/python/integrations/google-genai.mdx

Lines changed: 50 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ takes no credentials — it resolves each call to an Activity that runs on the W
7474
{/* SNIPSTART python-google-genai-hello-world-workflow */}
7575
[google_genai/hello_world/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/hello_world/workflow.py)
7676
```py
77-
from temporalio import workflow
78-
from temporalio.contrib.google_genai import TemporalAsyncClient
79-
80-
8177
@workflow.defn
8278
class HelloWorldWorkflow:
8379
@workflow.run
@@ -190,21 +186,6 @@ This Workflow passes one of each on a single call.
190186
{/* SNIPSTART python-google-genai-tools-workflow */}
191187
[google_genai/tools/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/tools/workflow.py)
192188
```py
193-
from datetime import timedelta
194-
195-
from google.genai import types
196-
from temporalio import activity, workflow
197-
from temporalio.contrib.google_genai import TemporalAsyncClient, activity_as_tool
198-
from temporalio.workflow import ActivityConfig
199-
200-
201-
@activity.defn
202-
async def get_weather(city: str) -> str:
203-
"""Look up the current weather for a city."""
204-
# Stub — replace with a real HTTP call in production.
205-
return f"It's 72F and sunny in {city}."
206-
207-
208189
@workflow.defn
209190
class ToolsWorkflow:
210191
@workflow.run
@@ -221,13 +202,13 @@ class ToolsWorkflow:
221202
start_to_close_timeout=timedelta(seconds=30),
222203
),
223204
),
224-
self.recommend_activity,
205+
self.recommend_thing_to_do,
225206
],
226207
),
227208
)
228209
return response.text or ""
229210

230-
async def recommend_activity(self, weather: str) -> str:
211+
async def recommend_thing_to_do(self, weather: str) -> str:
231212
"""Recommend something to do given a weather description."""
232213
if "sunny" in weather.lower():
233214
return "Go for a hike."
@@ -246,12 +227,13 @@ Register the Activity on the Worker alongside the Workflow.
246227
{/* SNIPSTART python-google-genai-tools-worker {"selectedLines": ["21-26"]} */}
247228
[google_genai/tools/run_worker.py](https://github.com/temporalio/samples-python/blob/main/google_genai/tools/run_worker.py)
248229
```py
249-
worker = Worker(
250-
client,
251-
task_queue="google-genai-tools",
252-
workflows=[ToolsWorkflow],
253-
activities=[get_weather],
254-
)
230+
# ...
231+
worker = Worker(
232+
client,
233+
task_queue="google-genai-tools",
234+
workflows=[ToolsWorkflow],
235+
activities=[get_weather],
236+
)
255237
```
256238
{/* SNIPEND */}
257239

@@ -263,10 +245,6 @@ call runs as its own Activity, so a conversation that spans hours or days surviv
263245
{/* SNIPSTART python-google-genai-chat-workflow */}
264246
[google_genai/chat/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/chat/workflow.py)
265247
```py
266-
from temporalio import workflow
267-
from temporalio.contrib.google_genai import TemporalAsyncClient
268-
269-
270248
@workflow.defn
271249
class ChatWorkflow:
272250
@workflow.run
@@ -294,12 +272,6 @@ unchanged. Pass the model as `response_schema` and read the parsed result from `
294272
{/* SNIPSTART python-google-genai-structured-output-workflow */}
295273
[google_genai/structured_output/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/structured_output/workflow.py)
296274
```py
297-
from google.genai import types
298-
from pydantic import BaseModel
299-
from temporalio import workflow
300-
from temporalio.contrib.google_genai import TemporalAsyncClient
301-
302-
303275
class Recipe(BaseModel):
304276
name: str
305277
ingredients: list[str]
@@ -320,7 +292,15 @@ class StructuredOutputWorkflow:
320292
),
321293
)
322294
recipe = response.parsed
323-
assert isinstance(recipe, Recipe)
295+
if not isinstance(recipe, Recipe):
296+
# ``parsed`` is None when the model returns malformed JSON. Fail the
297+
# workflow with an ApplicationError rather than asserting: an
298+
# assertion is a workflow task failure, which Temporal retries
299+
# forever, so the run would hang instead of failing visibly.
300+
raise ApplicationError(
301+
f"Gemini did not return a valid Recipe: {response.text!r}",
302+
non_retryable=True,
303+
)
324304
return recipe
325305

326306

@@ -338,6 +318,7 @@ Register each server with a factory that yields a connected, initialized `mcp.Cl
338318
{/* SNIPSTART python-google-genai-mcp-worker {"selectedLines": ["20-32"]} */}
339319
[google_genai/mcp/run_worker.py](https://github.com/temporalio/samples-python/blob/main/google_genai/mcp/run_worker.py)
340320
```py
321+
# ...
341322
@asynccontextmanager
342323
async def echo_session() -> AsyncIterator[ClientSession]:
343324
"""Yield a connected, initialized session to the stdio echo MCP server."""
@@ -360,17 +341,6 @@ discovers and calls the server's tools from there.
360341
{/* SNIPSTART python-google-genai-mcp-workflow */}
361342
[google_genai/mcp/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/mcp/workflow.py)
362343
```py
363-
from datetime import timedelta
364-
365-
from google.genai import types
366-
from temporalio import workflow
367-
from temporalio.contrib.google_genai import (
368-
TemporalAsyncClient,
369-
TemporalMcpClientSession,
370-
)
371-
from temporalio.workflow import ActivityConfig
372-
373-
374344
@workflow.defn
375345
class McpWorkflow:
376346
@workflow.run
@@ -410,11 +380,6 @@ to that topic as it arrives. The Workflow's own iteration over the stream is unc
410380
{/* SNIPSTART python-google-genai-streaming-workflow */}
411381
[google_genai/streaming/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/streaming/workflow.py)
412382
```py
413-
from temporalio import workflow
414-
from temporalio.contrib.google_genai import TemporalAsyncClient
415-
from temporalio.contrib.workflow_streams import WorkflowStream
416-
417-
418383
@workflow.defn
419384
class StreamingWorkflow:
420385
@workflow.init
@@ -432,7 +397,15 @@ class StreamingWorkflow:
432397
contents=prompt,
433398
):
434399
chunks.append(chunk.text or "")
435-
await workflow.wait_condition(lambda: self._done)
400+
# Bound the wait: if the subscriber dies without signaling, complete
401+
# anyway instead of waiting forever.
402+
try:
403+
await workflow.wait_condition(lambda: self._done, timeout=FINISH_TIMEOUT)
404+
except asyncio.TimeoutError:
405+
workflow.logger.warning(
406+
"No finish signal after %s; completing without a subscriber.",
407+
FINISH_TIMEOUT,
408+
)
436409
return "".join(chunks)
437410

438411
@workflow.signal
@@ -449,20 +422,21 @@ A consumer subscribes to the topic with `WorkflowStreamClient`. The published ch
449422
{/* SNIPSTART python-google-genai-streaming-run-workflow {"selectedLines": ["29-42"]} */}
450423
[google_genai/streaming/run_workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/streaming/run_workflow.py)
451424
```py
452-
# Subscribe to the "gemini" topic and print chunks as the model produces them.
453-
stream = WorkflowStreamClient.create(client, workflow_id)
454-
async for item in stream.subscribe(
455-
["gemini"],
456-
from_offset=0,
457-
result_type=types.GenerateContentResponse,
458-
poll_cooldown=timedelta(milliseconds=50),
459-
):
460-
chunk: types.GenerateContentResponse = item.data
461-
if chunk.text:
462-
print(chunk.text, end="", flush=True)
463-
if chunk.candidates and chunk.candidates[0].finish_reason:
464-
print()
465-
break
425+
# ...
426+
if chunk.candidates and chunk.candidates[0].finish_reason:
427+
print()
428+
return
429+
430+
431+
async def main() -> None:
432+
# The stream publishes Pydantic GenerateContentResponse chunks, so the
433+
# consumer needs the Pydantic data converter to decode them.
434+
client = await Client.connect(
435+
os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"),
436+
data_converter=pydantic_data_converter,
437+
)
438+
workflow_id = "google-genai-streaming"
439+
466440
```
467441
{/* SNIPEND */}
468442

@@ -479,13 +453,6 @@ pass the returned handle in `contents`.
479453
{/* SNIPSTART python-google-genai-files-workflow */}
480454
[google_genai/files/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/files/workflow.py)
481455
```py
482-
from typing import cast
483-
484-
from google.genai import types
485-
from temporalio import workflow
486-
from temporalio.contrib.google_genai import TemporalAsyncClient
487-
488-
489456
@workflow.defn
490457
class FilesWorkflow:
491458
@workflow.run
@@ -517,12 +484,6 @@ runs as its own Activity.
517484
{/* SNIPSTART python-google-genai-interactions-workflow */}
518485
[google_genai/interactions/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/interactions/workflow.py)
519486
```py
520-
from typing import Any
521-
522-
from temporalio import workflow
523-
from temporalio.contrib.google_genai import TemporalAsyncClient
524-
525-
526487
@workflow.defn
527488
class InteractionsWorkflow:
528489
@workflow.run
@@ -562,10 +523,6 @@ deterministic.
562523
{/* SNIPSTART python-google-genai-vertex-ai-workflow */}
563524
[google_genai/vertex_ai/workflow.py](https://github.com/temporalio/samples-python/blob/main/google_genai/vertex_ai/workflow.py)
564525
```py
565-
from temporalio import workflow
566-
from temporalio.contrib.google_genai import TemporalAsyncClient
567-
568-
569526
@workflow.defn
570527
class VertexAIWorkflow:
571528
@workflow.run
@@ -591,12 +548,13 @@ The Worker's `genai.Client` uses Application Default Credentials instead of an A
591548
{/* SNIPSTART python-google-genai-vertex-ai-worker {"selectedLines": ["13-18"]} */}
592549
[google_genai/vertex_ai/run_worker.py](https://github.com/temporalio/samples-python/blob/main/google_genai/vertex_ai/run_worker.py)
593550
```py
594-
genai_client = genai.Client(
595-
vertexai=True,
596-
project=os.environ["GOOGLE_CLOUD_PROJECT"],
597-
location=os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1"),
598-
)
599-
plugin = GoogleGenAIPlugin(genai_client)
551+
# ...
552+
genai_client = genai.Client(
553+
vertexai=True,
554+
project=os.environ["GOOGLE_CLOUD_PROJECT"],
555+
location=os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1"),
556+
)
557+
plugin = GoogleGenAIPlugin(genai_client)
600558
```
601559
{/* SNIPEND */}
602560

docs/develop/python/integrations/strands-agents.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,15 +521,15 @@ class HumanInTheLoopWorkflow:
521521
tools=[delete_file],
522522
hooks=[ApprovalHook()],
523523
)
524-
self._approval: Optional[str] = None
525-
self._pending_reason: Optional[str] = None
524+
self._approval: str | None = None
525+
self._pending_reason: str | None = None
526526

527527
@workflow.signal
528528
def approve(self, response: str) -> None:
529529
self._approval = response
530530

531531
@workflow.query
532-
def pending_approval(self) -> Optional[str]:
532+
def pending_approval(self) -> str | None:
533533
return self._pending_reason
534534

535535
@workflow.run

0 commit comments

Comments
 (0)