From 2eb9dbe0448a6264dacf8b521415d1e5ed2672ac Mon Sep 17 00:00:00 2001 From: maplexu Date: Mon, 31 Aug 2026 12:47:44 -0400 Subject: [PATCH 1/3] docs: document Google ADK integration (AI-282) --- .../integrations/google-adk-agents.mdx | 156 ++++++++++++++++++ sidebars.js | 1 + .../IntegrationsGrid/integrations-data.json | 9 + 3 files changed, 166 insertions(+) create mode 100644 docs/develop/typescript/integrations/google-adk-agents.mdx diff --git a/docs/develop/typescript/integrations/google-adk-agents.mdx b/docs/develop/typescript/integrations/google-adk-agents.mdx new file mode 100644 index 0000000000..5d6c5e4d33 --- /dev/null +++ b/docs/develop/typescript/integrations/google-adk-agents.mdx @@ -0,0 +1,156 @@ +--- +id: google-adk-agents +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. +--- + +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. + +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. + + + +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 +``` + +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. + +## 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. + + +[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' }); +``` + + +Register `GoogleAdkPlugin` on the Worker that executes the Workflow. The plugin installs the model Activities and the +Workflow bundler configuration required by Google ADK. + + +[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() } : {}), + ], +}); +await worker.run(); +``` + + +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. + +## 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 +[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 +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. + +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 +[replay testing](/develop/typescript/best-practices/testing-suite#replay) to verify that the current code +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. +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. + +## Understand replay safety and operational behavior + +- `TemporalModel` disables nested model SDK retries so Temporal Activity retry policies control retries and backoff. +- Model calls and MCP operations are not repeated during Workflow replay. A failed Activity attempt can be retried + according to its retry policy. +- Regular ADK function tools run inside the Workflow and must remain deterministic. Use `activityAsTool` for I/O. +- Live bidirectional streaming through `BaseLlm.connect` is not supported inside Workflows. +- Configure a heartbeat timeout for long model Activities when you need cancellation delivery and progress detection. + +## Resources + +- [Google ADK integration package](https://www.npmjs.com/package/@temporalio/google-adk-agents) +- [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) diff --git a/sidebars.js b/sidebars.js index ba42163641..481b4f8010 100644 --- a/sidebars.js +++ b/sidebars.js @@ -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', diff --git a/src/components/IntegrationsGrid/integrations-data.json b/src/components/IntegrationsGrid/integrations-data.json index 081cb5624e..715f2312a5 100644 --- a/src/components/IntegrationsGrid/integrations-data.json +++ b/src/components/IntegrationsGrid/integrations-data.json @@ -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.", + "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.", From 02db63236f7f7258bbd53a55bf62e6d61e03a24e Mon Sep 17 00:00:00 2001 From: maplexu Date: Wed, 2 Sep 2026 18:23:57 -0400 Subject: [PATCH 2/3] AI-282 Add Google ADK to TypeScript integrations --- docs/develop/typescript/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/develop/typescript/index.mdx b/docs/develop/typescript/index.mdx index 4cf2e9edcc..eba8a0c866 100644 --- a/docs/develop/typescript/index.mdx +++ b/docs/develop/typescript/index.mdx @@ -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) From 4529508762661e28a10a5c8d7a087b5d67d5a176 Mon Sep 17 00:00:00 2001 From: maplexu Date: Thu, 3 Sep 2026 14:28:44 -0400 Subject: [PATCH 3/3] AI-282 Add Google ADK integration reference --- .../integrations/google-adk-agents.mdx | 97 +++++++++++++++++-- 1 file changed, 89 insertions(+), 8 deletions(-) diff --git a/docs/develop/typescript/integrations/google-adk-agents.mdx b/docs/develop/typescript/integrations/google-adk-agents.mdx index 5d6c5e4d33..9d2b3aba00 100644 --- a/docs/develop/typescript/integrations/google-adk-agents.mdx +++ b/docs/develop/typescript/integrations/google-adk-agents.mdx @@ -138,14 +138,95 @@ Model and MCP calls appear as Activities in Temporal Event History even when Ope attributes can contain prompts and model responses, so send them only to an approved destination or remove sensitive attributes in your span processor. -## Understand replay safety and operational behavior - -- `TemporalModel` disables nested model SDK retries so Temporal Activity retry policies control retries and backoff. -- Model calls and MCP operations are not repeated during Workflow replay. A failed Activity attempt can be retried - according to its retry policy. -- Regular ADK function tools run inside the Workflow and must remain deterministic. Use `activityAsTool` for I/O. -- Live bidirectional streaming through `BaseLlm.connect` is not supported inside Workflows. -- Configure a heartbeat timeout for long model Activities when you need cancellation delivery and progress detection. +## 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 `-listTools` and `-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 ` | 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 `_` 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[.]` | 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[.]` | 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