Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/develop/typescript/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Once your local Temporal Service is set up, continue building with the following
## [Integrations](/develop/typescript/integrations)

- [Braintrust integration](https://www.braintrust.dev/docs/integrations/sdk-integrations/temporal#typescript)
- [Google ADK integration](/develop/typescript/integrations/google-adk-agents)
- [LangSmith integration](/develop/typescript/integrations/langsmith)
- [Mastra integration](https://mastra.ai/guides/deployment/temporal)
- [OpenAI Agents SDK integration](/develop/typescript/integrations/openai-agents)
Expand Down
237 changes: 237 additions & 0 deletions docs/develop/typescript/integrations/google-adk-agents.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
---
id: google-adk-agents

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming question rather than a blocker, but it's free now and costs a redirect later: Python and Go both live at /integrations/google-adk, and every other cross-SDK integration shares one slug (openai-agents / strands-agents / langsmith). I get that the TS pages follow the npm name, but Python's module is google_adk_agents and its slug is still google-adk, title/sidebar_label here already say "Google ADK", and ReleaseNoteHeader's guidePath builds /develop/<sdk>/<path> assuming the trailing path matches across SDKs. Would you be open to google-adk? (Same change in sidebars.js and the registry href.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.S. We are working on cutting over to a separate repo (AI-420) and plan to rename this to google-adk there for parity - so should do that here now anyways

title: Google ADK integration
sidebar_label: Google ADK
toc_max_heading_level: 2
tags:
- Google ADK
- TypeScript SDK
- Temporal SDKs
description: Run Google ADK agent graphs as durable Temporal Workflows while model and MCP calls execute as retryable Activities.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) The three ADK pages share a title, so in search results the description is the only differentiator, and the sibling pages all name their SDK. AGENTS.md also asks for roughly 120-155 chars (this is 116).

Suggested change
description: Run Google ADK agent graphs as durable Temporal Workflows while model and MCP calls execute as retryable Activities.
description: Run Google ADK agents as durable Temporal Workflows in TypeScript, with model and MCP calls running as retryable Activities.

---

import { ReleaseNoteHeader } from '@site/src/components';

Temporal's integration with the [Google Agent Development Kit (ADK)](https://google.github.io/adk-docs/) lets you run
ADK agents as durable Temporal Workflows. The agent graph, including its orchestration, tool selection, and state, runs
inside the Workflow. Model inference and Model Context Protocol (MCP) calls run as Activities.
Comment thread
xumaple marked this conversation as resolved.

This separation keeps the ADK programming model while adding Temporal's failure recovery. A Worker can stop while an
agent is running, then another Worker can replay the Workflow and continue from the last completed model or MCP call.
Temporal records each Activity result in Event History, so those calls aren't repeated during replay.

The `GoogleAdkPlugin` configures the Worker for ADK, and `TemporalModel` replaces a standard ADK model inside Workflow
code. The integration also provides Workflow-safe APIs for Activity-backed tools, MCP servers, and streaming model
responses.

<ReleaseNoteHeader type="prerelease" />

The code excerpts in this guide come from the
[Google ADK samples](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents). Refer to the samples
for complete applications that run with a real model or an API-key-free test model.

## Prerequisites

- This guide assumes you are familiar with Google ADK. If you aren't, refer to the
[Google ADK documentation](https://google.github.io/adk-docs/) for an introduction to agents, runners, and tools.
- If you are new to Temporal, read [Understanding Temporal](/evaluate/understanding-temporal) or take the
[Temporal 101](https://learn.temporal.io/courses/temporal_101/) course.
- Set up your local development environment by following
[Set up your local with the TypeScript SDK](/develop/typescript/set-up-your-local-typescript). Leave the Temporal
development server running if you want to run the samples locally.

## Install the Google ADK integration

Install the Temporal integration and its Google ADK peer dependencies. Keep all `@temporalio/*` packages in your
application on the same version.

```bash
npm install @temporalio/google-adk-agents @google/adk @google/genai

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The peer range on the package is @google/adk >=1.5.0 <1.6.0, and @google/adk@latest is 2.0.0 now (1.6.0 shipped 8/6, 2.0.0 on 8/21), so the unpinned install is a bit of a trap. I checked with npm install --dry-run: npm 11 happens to back off to 1.5.0 to satisfy the peer dep, but --legacy-peer-deps (and yarn/pnpm in practice) pull 2.0.0, which the README says can break the workflow bundle (README:22-25, "the ceiling is exact by design"). Can we pin it in the command and say why, like the README does? Probably worth a Node version line too (package engines is >=20.3, the samples README says 22+).

Suggested change
npm install @temporalio/google-adk-agents @google/adk @google/genai
npm install @temporalio/google-adk-agents "@google/adk@>=1.5.0 <1.6.0" "@google/genai@^2.9.0"

Then something like: "Version 1.23.0 of the integration supports @google/adk 1.5.x only. The upper bound is deliberate: the plugin's Workflow-sandbox shims are keyed to that ADK line, and a newer minor or major (1.6.0 and 2.0.0 are both published) can break the Workflow bundle."

```

The Worker reads Gemini credentials from `GOOGLE_API_KEY` or `GEMINI_API_KEY`. Credentials stay in the Worker process
and are not stored in Workflow inputs or Event History.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The credentials sentence is right (nothing credential-shaped in InvokeModelArgs), but the flip side is that the full LlmRequest (contents, system instruction, tool schemas) and the LlmResponse[] are Activity inputs/results, so prompts and responses land in Event History and the UI. Worth a sentence pointing at Payload Codecs (/develop/typescript/best-practices/data-handling/data-encryption), the 2MB payload limit, and CAN for long chats? FWIW the Python/Go ADK pages don't say this either, so not blocking on it - but this sentence kind of invites the question.


## Run an ADK agent in a Workflow

Use the standard ADK `LlmAgent` and runner APIs in your Workflow, but configure the agent with `TemporalModel`. Each
call through `TemporalModel` becomes an Activity, while the runner and agent graph remain in deterministic Workflow
code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related: the page never says where TemporalModel comes from. The root entry only exports GoogleAdkPlugin (src/index.ts); TemporalModel, TemporalMCPToolset, activityAsTool and markModelFailureHandled live at @temporalio/google-adk-agents/workflow, the doubles at /testing, and both snippets start after their imports - so import { TemporalModel } from '@temporalio/google-adk-agents' is the first thing people will try, and it doesn't compile. openai-agents.mdx has a little import-paths table for exactly this (L47-57), worth copying that pattern?


<!--SNIPSTART typescript-google-adk-agent-chat-workflow-->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this marker only wraps the agent + runner construction, so a reader never sees the runAsync loop, isFinalResponse/stringifyContent, or a return value - and there's no client/start step anywhere on the page. The Python and Go ADK pages and both TS sibling pages (openai-agents, strands-agents) all show workflow + worker + client. Since agent-chat is Update-driven and CAN-heavy I'm not sure it's the right hello world anyway - what do you think about adding a basic scenario to samples-typescript (mirroring Python's basic) with typescript-google-adk-basic-{workflow,worker,client} markers? The README's askAgent (README:37-94) is basically that already. If you'd rather not wait on a samples PR, an inline fence lifted from the README seems fine as an interim (the Go page does that for streaming).

[google-adk-agents/src/agent-chat/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/google-adk-agents/src/agent-chat/workflows.ts)
```ts
const agent = new LlmAgent({
name: 'assistant',
model: new TemporalModel('gemini-2.5-flash'),
instruction: 'Continue the conversation using its prior context. Respond in one sentence.',
});
const runner = new InMemoryRunner({ agent, appName: 'agent-chat' });
```
<!--SNIPEND-->

Register `GoogleAdkPlugin` on the Worker that executes the Workflow. The plugin installs the model Activities and the
Workflow bundler configuration required by Google ADK.

<!--SNIPSTART typescript-google-adk-agent-chat-worker-->
[google-adk-agents/src/agent-chat/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/google-adk-agents/src/agent-chat/worker.ts)
```ts
const worker = await Worker.create({
connection,
taskQueue: 'google-adk-agent-chat',
workflowsPath: require.resolve('./workflows'),
plugins: [
new GoogleAdkPlugin(process.env.MODEL_PROVIDER === 'fake' ? { modelProvider: offlineModelProvider() } : {}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The marked region includes the MODEL_PROVIDER === 'fake' ? { modelProvider: offlineModelProvider() } toggle, and offlineModelProvider is a sample-local double (agent-chat/offline-model.ts) the page never mentions - I think readers will assume it comes from /testing, especially since the testing section below talks about fakeModelProvider. Could we hoist the ternary above the @@@SNIPSTART in the sample so the snippet is just plugins: [new GoogleAdkPlugin(pluginOptions)] (or plain new GoogleAdkPlugin())? Same shape in the tools/multi-agent/streaming/structured-output/observability workers, so any future markers there would inherit it. Interim, one sentence after the snippet explaining the toggle would help.

],
});
await worker.run();
```
<!--SNIPEND-->

The default model provider uses Google ADK's model registry. You can pass a custom `modelProvider` to
`GoogleAdkPlugin` to configure another provider, route model names through a proxy, or supply a test double. Register
the plugin on the Worker; a Client plugin is not required.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) Since the Python page has folks putting the plugin on Client + Worker, readers coming from there will be looking for this exact sentence - suggest moving it up next to "Register GoogleAdkPlugin on the Worker" at L73 and following it with a client snippet (README client.ts is a fine source).


## Add tools and MCP servers

Google ADK function tools run as part of the agent graph inside the Workflow. Use them for deterministic operations,
such as transforming values or updating agent state. A tool that reads a file, calls an API, queries a database, or
performs other I/O must run outside the Workflow.

Use `activityAsTool` from `@temporalio/google-adk-agents/workflow` to expose an existing Activity to an agent. The tool
name identifies the registered Activity, and its Activity options control timeouts and retries. The

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth saying the Activity also has to be registered on the Worker's activities (the only Worker snippet on the page has no activities key, so a reader adding a tool gets "Activity function X is not registered" at runtime), that the model's arguments object arrives as the Activity's single argument, and that the option is activity: ActivityOptions (src/tools.ts:12-28). The tools sample already has all of this (tools/worker.ts:13, tools/workflows.ts:24-32) - a marker pair there would let the page just show it.

[tools sample](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents/src/tools) shows a
deterministic function tool and an Activity-backed weather tool in the same agent.

For MCP, register a named toolset factory in `GoogleAdkPlugin` on the Worker, then use a `TemporalMCPToolset` with the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name the option here (mcpToolsets: { <name>: factory }) and show the worker/workflow pair from the README (README:124-146)? As written I don't think a reader can write the Worker side from the page. Two caveats from the README that I think belong here too: each operation opens its own MCP session, so per-session state (cursor, cwd, auth) doesn't carry between calls unless the factory returns a long-lived toolset (README:148-152); and MCP failures rarely carry a status, so they retry unbounded unless activity.retry.maximumAttempts is set on TemporalMCPToolset (src/error-types.ts:55-66).

same name in Workflow code. Listing tools and calling them execute as Activities. The
[MCP sample](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents/src/mcp) shows this pairing
with a stateless filesystem server and an API-key-free test implementation.

## Stream model responses

Set `streamingTopic` in `TemporalModel` options to publish model response chunks through
[`@temporalio/workflow-streams`](https://www.npmjs.com/package/@temporalio/workflow-streams). Stream delivery is
at-least-once. The complete model response returned by the Activity is the deterministic value used by the Workflow.
Comment on lines +113 to +115

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think streamingTopic alone does anything - src/model.ts:142-158 only takes the streaming Activity when the call passes stream === true (ADK does that under runConfig: { streamingMode: StreamingMode.SSE }, or you call generateContentAsync(request, true) directly like the sample does at streaming/workflows.ts:33); otherwise it's the plain adk-invokeModel Activity and nothing gets published. A streaming call without a topic fails non-retryably, and the Workflow has to host new WorkflowStream() for anyone to read the topic. The sample README actually spells this out ("Streaming is requested by generateContentAsync's stream argument, not by configuration"). Also worth saying that the linked sample streams from a direct TemporalModel call with no agent loop, and - same ask as on #4793 - making the @temporalio/workflow-streams install explicit. Suggested wording:

Suggested change
Set `streamingTopic` in `TemporalModel` options to publish model response chunks through
[`@temporalio/workflow-streams`](https://www.npmjs.com/package/@temporalio/workflow-streams). Stream delivery is
at-least-once. The complete model response returned by the Activity is the deterministic value used by the Workflow.
Streaming needs three things: a `WorkflowStream` (from `@temporalio/workflow-streams/workflow`) hosted at the top of
the Workflow, a `streamingTopic` in `TemporalModel` options, and a model call made in streaming mode, either
`runConfig: { streamingMode: StreamingMode.SSE }` through a runner or `generateContentAsync(request, true)` directly.
A streaming call without a `streamingTopic` fails. The model Activity publishes each chunk to the topic through
[`@temporalio/workflow-streams`](https://www.npmjs.com/package/@temporalio/workflow-streams) and still returns the
complete response to the Workflow, which is the deterministic value used on replay. Stream delivery is at-least-once,
and a retried Activity attempt publishes its chunks again from the beginning.


The [streaming sample](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents/src/streaming)
shows how a Workflow publishes chunks and waits for a stream consumer to finish.

## Test your agents

The `@temporalio/google-adk-agents/testing` entry point provides `fakeModelProvider` and `mockMCPToolset`. Pass these
helpers to `GoogleAdkPlugin` to test an agent without model credentials or a live MCP server. This keeps model and tool
behavior controlled while exercising the real Worker plugin, Workflow bundle, and Activities.

The Google ADK samples use the same testing APIs for their API-key-free execution path. For Workflow changes, also use

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is quite right - only streaming, observability and structured-output use fakeModelProvider, and mcp uses mockMCPToolset; agent-chat, tools and multi-agent hand-roll a BaseLlm subclass (offline-model.ts) because FakeLlm replays a fixed response list and can't do a context-dependent second turn. Suggest naming which samples use which helper - or making the sentence true by having those three subclass FakeLlm (agent-chat's mocha test already does).

[replay testing](/develop/typescript/best-practices/testing-suite#replay) to verify that the current code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding that the replayer needs the plugin too, i.e. Worker.runReplayHistory({ workflowsPath, plugins: [new GoogleAdkPlugin()] }, history) - the bundler config is what lets @google/adk load in the replay sandbox at all, and your replay.test.ts:55-60 does exactly this. The linked testing-suite example only passes workflowsPath, so readers will copy that and hit a bundle failure that looks unrelated.

remains compatible with recorded Event Histories.

## Add observability

Compose `GoogleAdkPlugin` after `OpenTelemetryPlugin` from `@temporalio/interceptors-opentelemetry` to export ADK's
agent, model, and tool spans from the Workflow sandbox. The Workflow interceptor suppresses span export during replay.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small precision thing: IIUC the replay gate is the OTel plugin's Worker sink (default callDuringReplay: false), not a Workflow interceptor - and that makes export at-least-once rather than exactly-once, since a Workflow Task retry re-runs live (README:236-242; the exact-count test in telemetry.test.ts is pinned on the same thing). Also, ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=false is inert in the sandbox because process.env is {} there (src/plugin.ts:85), which I'd mention right next to the "attributes can contain prompts" sentence since that's the first knob people will reach for. Maybe also the one-line plugins: [new OpenTelemetryPlugin(...), new GoogleAdkPlugin()] array plus the OTel package install, like openai-agents.mdx does (L635-640)?

The [observability sample](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents/src/observability)
shows the plugin order and an OpenTelemetry span processor that records model usage.

Model and MCP calls appear as Activities in Temporal Event History even when OpenTelemetry is not configured. ADK span
attributes can contain prompts and model responses, so send them only to an approved destination or remove sensitive
attributes in your span processor.

## Reference and troubleshooting

### Feature support

The integration supports ADK agents and runners, Activity-backed model calls, deterministic function tools,
Activity-backed tools, MCP tool discovery and calls, server-sent event (SSE) model streaming, test doubles, and ADK
OpenTelemetry spans.

Live bidirectional streaming through `BaseLlm.connect` isn't supported inside Workflows. ADK extension points that
perform I/O must run in Activities. `TemporalMCPToolset` accepts a list of tool names as its filter, but it doesn't
support ADK's `ToolPredicate` filter.

### Composing with other plugins

Register observability and governance plugins before `GoogleAdkPlugin`. For example, placing `OpenTelemetryPlugin` first
installs the Workflow tracer provider before ADK creates spans.

Custom payload and failure converter modules load before the plugin's polyfills. If either module imports `@google/adk`
or `@google/genai`, import `@temporalio/google-adk-agents/workflow` first in that module.

### Replay safety

The ADK runner, agent graph, regular function tools, and `summary` callback run in Workflow code and must remain
deterministic. Model calls, MCP operations, and tools created with `activityAsTool` run as Activities. Their completed
results come from Event History during replay instead of executing again.

Streaming publishes an at-least-once side channel, but the complete Activity result remains the deterministic value
returned to the Workflow. OpenTelemetry span export is also at-least-once: replay doesn't emit spans again, but a
Workflow Task retry can.

### Configuration

The following tables cover the integration-specific options. Options under `activity` accept the standard TypeScript SDK
`ActivityOptions` fields.

| API | Option | Default | Behavior |
| ----------------- | ------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GoogleAdkPlugin` | `modelProvider` | ADK `LLMRegistry` | Resolves a model name in the model Activities. Use it to configure another provider, a proxy, or a test double. |
| `GoogleAdkPlugin` | `mcpToolsets` | `{}` | Maps each name to an MCP factory and registers `<name>-listTools` and `<name>-callTool` Activities. |
| `TemporalModel` | `activity` | `startToCloseTimeout: '1 minute'` | Configures every model Activity. An explicit `startToCloseTimeout` overrides the default. |
| `TemporalModel` | `summary` | ADK agent name, then `adk.invokeModel <model>` | Sets the Activity summary. A function receives the model request and must be deterministic. This option takes precedence over `activity.summary`. |
| `TemporalModel` | `streamingTopic` | None | Publishes SSE response chunks to this workflow-streams topic when streaming is requested. |
| `TemporalModel` | `streamingBatchInterval` | `'100 milliseconds'` | Sets how frequently streaming chunks are batched for publication. |

| API | Option | Default | Behavior |
| -------------------- | ------------------ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `TemporalMCPToolset` | `name` | Required | Selects the Worker-registered factory and names its Activity pair. |
| `TemporalMCPToolset` | `toolFilter` | All tools | Advertises only the listed tool names. Names are matched after applying `prefix`. |
| `TemporalMCPToolset` | `prefix` | None | Advertises each tool as `<prefix>_<name>` without changing its name on the MCP server. |
| `TemporalMCPToolset` | `activity` | `startToCloseTimeout: '1 minute'` | Configures both tool discovery and tool-call Activities. |
| `TemporalMCPToolset` | `connectionParams` | None | Creates a real MCP toolset only when used outside a Workflow. Worker-side MCP configuration belongs in `mcpToolsets`. |
| `activityAsTool` | `name` | Required | Names both the tool and the registered Activity it calls. |
| `activityAsTool` | `description` | Required | Describes the tool to the model. |
| `activityAsTool` | `parameters` | Empty object schema | Defines the arguments passed to the Activity as its single input. |
| `activityAsTool` | `activity` | `startToCloseTimeout: '1 minute'` | Configures the Activity call. |
| `FakeLlm` | `model` | `'fake-model'` | Sets the model name used by the test double. |
| `FakeLlm` | `responses` | One canned text response | Sets the responses yielded in order by the test double. |
| `fakeModelProvider` | `responses` | One canned text response | Creates a model provider that returns a `FakeLlm` for every model name. |
| `mockMCPToolset` | `definitions` | Required | Creates an MCP factory from tool declarations and handlers. |

An MCP factory can return connection parameters or a `BaseToolset`. Connection parameters create and close one MCP
session per Activity. A `BaseToolset` remains owned by the factory, isn't closed by the plugin, and can open separate
sessions for discovery and the tool call.

When `heartbeatTimeout` is set, model and MCP Activities heartbeat on a timer at half the timeout. Streaming model
Activities also heartbeat for each chunk. These heartbeats deliver cancellation and detect a stopped Worker, but they
don't detect a hung model or MCP call; `startToCloseTimeout` bounds that call.

### Failure behavior

The plugin exports constants for its public `ApplicationFailure.type` values. Model and MCP failures originate in
Activities, so catch the surrounding `ActivityFailure` and inspect its cause chain for these types.

| Failure type | Meaning |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GoogleAdkModelError[.<status>]` | A model call failed. Statuses 408, 409, 429, and 5xx are retryable; other HTTP statuses are non-retryable. A failure without a status is retryable. `x-should-retry` overrides this classification, and `retry-after` or `retry-after-ms` sets the next retry delay. |
| `GoogleAdkMCPError[.<status>]` | MCP discovery or a tool call failed. It uses the same status classification as model errors. Failures without a status are retryable, so set `activity.retry.maximumAttempts` to bound retries. |
| `GoogleAdkMCPToolNotFound` | A factory-provided `BaseToolset` didn't contain the requested tool. This failure is non-retryable. |
| `GoogleAdkStreamingTopicRequired` | SSE streaming was requested without `streamingTopic`. This failure is non-retryable and is thrown directly in the Workflow. |
| `GoogleAdkUnsupported` | `BaseLlm.connect` was called in a Workflow. This failure is non-retryable and is thrown directly in the Workflow. |

ADK normally converts an error from an agent's model call into an event. The integration records that absorbed failure
and re-raises it after the Workflow or handler frame that ran the agent turn returns. To recover in an ADK
`onModelErrorCallback`, pass the received error to `markModelFailureHandled` and return a substitute event created with
ADK's `createEvent`. Cancellation can't be handled this way.

If a model call fails with a sandbox error such as `fetch is not defined`, check that the agent uses
`new TemporalModel(...)` instead of a raw model string. A raw model makes ADK attempt the network call inside the
Workflow instead of routing it to an Activity.

## Resources

- [Google ADK integration package](https://www.npmjs.com/package/@temporalio/google-adk-agents)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three of the eight scenarios (multi-agent, human-in-the-loop, structured-output) never appear on the page, and agent-chat only shows up as a snippet path even though its Updates/Query/Continue-As-New pattern is the most Temporal-y thing in the samples. Cheapest fix is a ## Samples table like the one in the samples README (the Python and Go pages both close with one). Longer term I'd love short HITL and long-conversation sections once markers exist - happy to help with the samples-side PR.

- [Google ADK integration source](https://github.com/temporalio/sdk-typescript/tree/main/contrib/google-adk-agents)
- [Google ADK samples](https://github.com/temporalio/samples-typescript/tree/main/google-adk-agents)
- [Google ADK documentation](https://google.github.io/adk-docs/)
- [Temporal TypeScript SDK documentation](/develop/typescript)
1 change: 1 addition & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,7 @@ const developTypeScriptCategory = {
},
items: [
'develop/typescript/integrations/ai-sdk',
'develop/typescript/integrations/google-adk-agents',
'develop/typescript/integrations/langsmith',
'develop/typescript/integrations/openai-agents',
'develop/typescript/integrations/strands-agents',
Expand Down
9 changes: 9 additions & 0 deletions src/components/IntegrationsGrid/integrations-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@
"sdk": "Go",
"href": "/develop/go/integrations/google-adk"
},
{
"name": "Google ADK",
"description": "Run Google ADK agents as durable Temporal Workflows with the TypeScript SDK.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) The three Google ADK entries now have three different descriptions, whereas every other cross-SDK entry repeats one sentence and skips the SDK name (the card already shows the SDK pill). Suggest one shared string, e.g. "Run Google ADK agents as durable Temporal Workflows." - happy for the Python/Go edits to ride along here or in a follow-up.

"tags": [
"Agent framework"
],
"sdk": "TypeScript",
"href": "/develop/typescript/integrations/google-adk-agents"
},
{
"name": "Google GenAI",
"description": "Call Google Gemini models durably from Temporal Workflows with the Google Gen AI SDK.",
Expand Down