Skip to main content

Google ADK integration

View Markdown

The Temporal Google Agent Development Kit (ADK) integration runs an ADK agent graph as a durable Temporal Workflow. The agent loop, tool selection, and state run in the Workflow, while model inference and Model Context Protocol (MCP) operations run as Activities. Completed calls are recorded in Event History and aren't repeated during replay.

GoogleAdkPlugin configures the Worker and Workflow bundle. In Workflow code, TemporalModel replaces a standard ADK model and routes each model call to an Activity. The integration also provides Workflow-safe APIs for Activity-backed tools, MCP servers, and streamed model responses.

Prerequisites

Install the Google ADK integration

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

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

Version 1.23.0 of the integration supports @google/adk 1.5.x. The upper bound is required because the Workflow bundle uses compatibility shims for that ADK line. Newer ADK versions can fail while bundling the Workflow.

The Worker reads Gemini credentials from GOOGLE_API_KEY or GEMINI_API_KEY. Credentials remain in the Worker process. Model requests and responses are Activity inputs and results, so they are stored in Event History. Use a Payload Codec to encrypt sensitive data, and account for the programming model limits, including the 2 MB limit on a single payload.

Run an ADK agent in a Workflow

The basic Google ADK sample contains a complete Workflow, Worker, and Client. It uses the standard ADK LlmAgent and InMemoryRunner APIs in the Workflow, with TemporalModel as the agent's model. The runner iterates over ADK events and returns the final response.

The Worker registers GoogleAdkPlugin, which installs the model Activities and the Workflow bundler configuration. The Client starts the Workflow normally and doesn't need the plugin.

Use each API from its package entry point:

Entry pointAPIs
@temporalio/google-adk-agentsGoogleAdkPlugin for Worker code
@temporalio/google-adk-agents/workflowTemporalModel, TemporalMCPToolset, and activityAsTool for Workflow code
@temporalio/google-adk-agents/testingfakeModelProvider and mockMCPToolset for tests

Start the Worker, then run the Client from the sample directory:

npx tsx src/basic/worker.ts
npx tsx src/basic/client.ts

Configure model calls

Pass Activity options to TemporalModel to set timeouts, retries, a Task Queue, or an Activity summary. The default startToCloseTimeout is one minute.

const model = new TemporalModel('gemini-2.5-flash', {
activity: {
startToCloseTimeout: '5 minutes',
heartbeatTimeout: '30 seconds',
retry: { maximumAttempts: 3 },
},
});

The plugin disables retries in the underlying model SDK so that the Activity retry policy controls retries and backoff. Set heartbeatTimeout to detect a dead Worker and deliver cancellation to a long model call. The Activity heartbeats on a timer, so a Heartbeat Timeout doesn't detect a stalled call; startToCloseTimeout bounds a stalled call.

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 to expose an existing Activity to an agent. Its name must match an Activity registered in the Worker's activities option. The model's arguments object becomes the Activity's single argument, and the activity option controls its timeouts and retries. The tools sample shows the Workflow and Worker configuration together.

For MCP, register a named factory with mcpToolsets: { <name>: factory } in the Worker plugin, then create a TemporalMCPToolset with the same name in Workflow code. Listing tools and calling them execute as Activities. Each operation opens a new MCP session, so session state doesn't carry between operations unless the factory returns a long-lived toolset. MCP failures often have no status and are retryable, so set activity.retry.maximumAttempts on the TemporalMCPToolset when retries must be bounded. See the complete Worker and Workflow pair in the MCP sample.

Stream model responses

Install @temporalio/workflow-streams, host a WorkflowStream at the top of the Workflow, and set streamingTopic in the TemporalModel options. The model call must also request streaming, either through ADK runner configuration with StreamingMode.SSE or by calling generateContentAsync(request, true). A streaming call without a topic fails.

The model Activity publishes chunks to the topic and returns the complete response to the Workflow. The Activity result is the deterministic value used during replay. Stream delivery is at-least-once, and a retried Activity publishes its chunks again from the beginning.

The streaming sample shows how a Workflow publishes chunks and waits for a stream consumer to finish.

Test and observe your agents

The testing entry point provides fakeModelProvider and mockMCPToolset. Pass them to GoogleAdkPlugin to test without model credentials or a live MCP server while exercising the Worker plugin, Workflow bundle, and Activities.

Use replay testing for Workflow changes. Pass plugins: [new GoogleAdkPlugin()] to Worker.runReplayHistory because the plugin's bundler configuration is required to load Google ADK in the replay sandbox.

Compose GoogleAdkPlugin after OpenTelemetryPlugin from @temporalio/interceptors-opentelemetry to export ADK's agent, model, and tool spans from the Workflow sandbox.

plugins: [new OpenTelemetryPlugin({ resource, spanProcessor }), new GoogleAdkPlugin()]

The OpenTelemetry plugin's Worker sink suppresses span export during replay. Export is at-least-once because a failed or timed-out Workflow Task can execute again without being a replay. The observability sample shows the plugin order and an OpenTelemetry span processor that records model usage.

ADK span attributes can contain prompts and model responses. Send them only to an approved destination or remove sensitive attributes in the span processor. ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS doesn't control this behavior in a Workflow because the Workflow sandbox doesn't expose Worker environment variables.

Reference and troubleshooting

Feature support

The integration supports ADK agent graphs, sequential and delegated multi-agent patterns, function tools, Activities as tools, MCP toolsets, human approval through Signals or Updates, structured model output, SSE response streaming, and OpenTelemetry tracing. Live bidirectional streaming through BaseLlm.connect isn't supported in Workflows.

Composing with other plugins

Register observability and governance plugins before GoogleAdkPlugin. In particular, place OpenTelemetryPlugin first so that ADK's Workflow-side spans bind to its tracer provider. Register GoogleAdkPlugin only on the Worker; a Client plugin isn't required.

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 callbacks execute inside the Workflow and must remain deterministic. TemporalModel, TemporalMCPToolset, and activityAsTool move model calls, MCP operations, and other I/O into Activities. Completed Activity results are read from Event History during replay.

The full model request and response cross the Activity boundary and are recorded in Event History. For long-running conversations, use Continue-As-New before Event History approaches its limits.

Configuration

Options under activity accept the standard TypeScript SDK ActivityOptions fields.

APIOptionDefaultBehavior
GoogleAdkPluginmodelProviderADK LLMRegistryResolves model names in model Activities. Use it for another provider, proxy, or test double.
GoogleAdkPluginmcpToolsets{}Maps names to MCP factories and registers <name>-listTools and <name>-callTool Activities.
TemporalModelactivitystartToCloseTimeout: '1 minute'Configures every model Activity.
TemporalModelsummaryADK agent name, then adk.invokeModel <model>Sets the Activity summary. A function receives the request and must be deterministic. This takes precedence over activity.summary.
TemporalModelstreamingTopicNonePublishes SSE response chunks to this Workflow streams topic when streaming is requested.
TemporalModelstreamingBatchInterval'100 milliseconds'Sets how frequently response chunks are batched for publication.
APIOptionDefaultBehavior
TemporalMCPToolsetnameRequiredSelects the Worker-registered factory and names its Activity pair.
TemporalMCPToolsettoolFilterAll toolsAdvertises only listed tool names, matched after applying prefix. ADK ToolPredicate filters aren't supported.
TemporalMCPToolsetprefixNoneAdvertises each tool as <prefix>_<name> without changing its MCP server name.
TemporalMCPToolsetactivitystartToCloseTimeout: '1 minute'Configures tool discovery and tool-call Activities.
TemporalMCPToolsetconnectionParamsNoneCreates a real MCP toolset only outside a Workflow. Worker-side configuration belongs in mcpToolsets.
activityAsToolnameRequiredNames the tool and the registered Activity it calls.
activityAsTooldescriptionRequiredDescribes the tool to the model.
activityAsToolparametersEmpty object schemaDefines the arguments passed to the Activity as its single input.
activityAsToolactivitystartToCloseTimeout: '1 minute'Configures the Activity call.
FakeLlmmodel'fake-model'Sets the test double's model name.
FakeLlmresponsesOne canned text responseSets the responses yielded in order.
fakeModelProviderresponsesOne canned text responseReturns a FakeLlm for every model name.
mockMCPToolsetdefinitionsRequiredCreates 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 maintain state.

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 typeMeaning
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.
GoogleAdkMCPToolNotFoundA factory-provided BaseToolset didn't contain the requested tool. This failure is non-retryable.
GoogleAdkStreamingTopicRequiredSSE streaming was requested without streamingTopic. This failure is non-retryable and is thrown directly in the Workflow.
GoogleAdkUnsupportedBaseLlm.connect was called in a Workflow. This failure is non-retryable and is thrown directly in the Workflow.

ADK converts an error from an agent's model call into an event. The integration records that failure and re-raises it after the Workflow or handler frame returns. To recover in an ADK onModelErrorCallback, pass the 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