Inside the Google ADK and Temporal integration

AUTHORS
Tim-Conley, Drew Hoskins
DATE
Apr 20, 2026
CATEGORY
DURATION
11 MIN

Before we built official support for Google's Agent Development Kit, Kyndryl (a company that uses our product) had already figured out how to make it work with Temporal. They wrote it up and posted it on Medium.

We read the post and it confirmed what we were already hypothesizing: there was a real demand for this.

Why integrate at all?#

So, outside of Google ADK specifically, there's a bigger question here: why are we doing integrations at all?

There are two answers.

One is that Temporal is, in our opinion, the best durable execution agentic runtime in the world. And two, there are a bunch of other frameworks out there. AI frameworks, observability solutions, all kinds of things. And those are all great, too. Beyond giving our users the choice to mix and match, we want them to feel confident they're following Temporal best practices while doing it. Whatever tool they think is the best fit for the job, at whatever layer of the stack they care about, we want that connection to feel solid and well-supported.

Our main goal is for Temporal to be a platform that's easy to adopt and lets users do whatever they want. Building an integration for Google ADK is a prime example of that.

We want Temporal users to be able to choose from all of the top agent frameworks. We often express that as meeting developers where they are (or where they want to be).

And to be fair, that's also what we're saying for all distributed programming. The larger point is that the agentic stack is just distributed programming that happens to run agents. Which means it has distinct layers: a durable execution layer, an agent framework layer, and an observability layer. A lot of people haven't really thought through that distinction, and there are frameworks that blur the lines there. What we're trying to say is: those are actually different things, and we want to be the right choice at our layer without being opinionated about the others.

Google ADK is the third high-profile integration we've shipped, after OpenAI Agents SDK and Vercel's AI SDK. This first release supports Python, with other ADK languages likely to follow. We've also recently launched an AI Partner Program for framework teams who want to build integrations with us, but more on that at the end.

What deeper integration makes possible#

The Kyndryl team's initial approach was to run ADK agents as independent HTTP services and call them from Temporal activities — Temporal handled durability at the agent-call boundary, with each activity wrapping one A2A JSON-RPC request.

Our integration offers a different approach. Rather than using Temporal as a harness around the agent, we bring Temporal into the agentic loop itself. Each LLM call and tool call runs as its own Activity, which means the loop is durable at every step instead of just from the outside.

The harness pattern has some limitations though. You get zero visibility into what's happening inside the Activity in the Temporal UI, you have to craft a single timeout and retry policy for the entire agent run (which can take a long time and slows down crash recovery), and you end up rolling your own recovery code to handle anything that goes wrong mid-execution. It's the same reason you wouldn't put any complex workflow entirely inside a single activity — you lose many of the things that make Temporal useful.

The agentic loop is actually a deterministic sequence of non-deterministic things. The agent invokes the LLM, decides what to do, calls a tool, invokes the LLM again, decides again, calls another tool, returns a result. The loop itself is deterministic and what's non-deterministic is each individual LLM call and each individual tool call.

So the better architecture is to run the agentic loop in the Temporal Workflow and push each LLM call and tool call into its own Activity. Smaller atoms, more precise retries. If a single LLM call fails, Temporal retries that exact call with the same context history and same inputs instead of writing the entire agent from scratch. If a tool call to an external API fails, Temporal retries the tool call, not the decision to make it.

This is what our integration does. Kyndryl is publishing an updated blog post alongside this launch showing what the more integrated approach makes possible. It's very worth reading alongside this one.

How the integration works#

The entire integration is about 200 lines of code (not counting MCP support) and about 400 with it. The goal is to make a workflow-safe version of ADK that runs in the Workflow and farms out the non-deterministic pieces (LLM calls, tool calls) into individual Activities. There are two main seams where that happens.

The model seam#

We provide TemporalModel, a wrapper that reroutes LLM calls through Temporal Activities. Wrap your model, configure your timeouts and retries, and you're done:

agent = Agent(
    model=TemporalModel(
        "gemini-2.5-pro",
        activity_config=ActivityConfig(
            start_to_close_timeout=timedelta(minutes=1)
        )
    ),
    tools=[weather_tool],
)

Models aren't serializable because they contain HTTP clients and other objects that can't cross the wire between processes, so rather than moving the model object, we move just its name and recreate it on the activity side using ADK's built-in LLM registry. ADK already had exactly the mechanism we needed for this.

The tool seam#

Tools in this integration are Workflow functions, which means they can do anything you can do in a Temporal Workflow including run Activities, execute a child Workflows, call a Nexus operations, or any other deterministic operations. For the most common case (running a single Activity), we provide activity_tool as a convenient helper that handles retries, backoff, and heartbeating automatically.

weather_tool = activity_tool(
    get_weather,
    start_to_close_timeout=timedelta(seconds=30),
    retry_policy=RetryPolicy(maximum_attempts=3),
)

You can also define Nexus operations or child Workflows as tools, which opens up multi-agent patterns.

The worker setup#

The worker setup is just a single line:

client = await Client.connect(
    "localhost:7233",
    plugins=[GoogleAdkPlugin()]
)

GoogleAdkPlugin() handles sandbox passthrough for ADK and Gemini modules, Pydantic serialization for ADK data types, and the deterministic time and UUID replacements covered in the next section.

The change that required a PR into Google's codebase#

There was one piece we couldn't solve entirely on our side.

Temporal Workflow code has to be deterministic — meaning the same inputs always produce the same outputs, even when replaying after a failure on a different machine, potentially days later. That breaks the moment workflow code calls time.time() or uuid.uuid4() directly, because those return different values every time they run.

ADK was doing exactly this. Core components (session management, event logging, invocation context) all used standard library calls for timestamps and UUIDs.

So we worked with the Google team to introduce an abstraction layer: google.adk.platform.time and google.adk.platform.uuid. These thin functions allow the time and UUID providers to be swapped out at runtime. In standard ADK usage, they call the standard library as before. Inside a Temporal Workflow, they call Temporal's deterministic equivalents: workflow.now() and workflow.uuid4().

You can see exactly what changed in the PR. The change was small, and the ADK team implemented it in a general way — so if you're building on any durable execution system, not just Temporal, this abstraction is available to you.

The MCP issue#

MCP breaks the mold of typical tools. Usually, when you set up an agent, you give it set tools from the start. MCP gives it a way to discover and call tools from a server at runtime instead. The gist of it is: what if we let the agent discover tools itself, rather than providing them?

Even though those tools are discovered dynamically at runtime, each call still runs as a Temporal Activity and shows up in the UI — grouped by MCP server under a single activity definition (servername_call_tool). You get visibility and retries on every tool call, whether you pre-assigned it or not.

It's a commonly requested feature, so we wanted it to work with Temporal and these integrations out of the box, but first it required working through a subtler problem.

ADK tools have access to a context object that includes the current agent's state, its parent agent, and up the chain from there. When you serialize a tool call across the Workflow/Activity boundary, you have to decide what to do with all of that. One option is to take the whole context, serialize it over to the activity, let the tool make modifications, reserialize it, and send it back. But given that the tool context in ADK is potentially a huge tree of information, that's a pretty expensive way to make it work.

Digging into the ADK source code for MCP tools, it's clear they only interact with a small portion of the context, mostly to ask for approval to run. What we did was take a focused snapshot, give it to the activity, let the tool handle it, and then bring the results back.

Just so you know, there's nothing stopping future ADK updates from letting MCP tools do more with the tool context. When that happens, the integration will require an update. We're going into it knowing that piece might need work down the line.

Basically, if you're building a framework and want it to be super reliable, remember to only give non-deterministic parts (like tool runs) the exact info they need, nothing more. The more expansive the context, the harder it becomes to serialize cleanly across a process boundary.

What it looks like for a developer#

There are really two paths into this, depending on where you're starting from.

If you're already using ADK, we aimed to make it super simple to move your current agent to a Temporal Workflow with hardly any code tweaks, and we're proud of what we've produced. There's an almost mechanical process: wrap your model with TemporalModel, decide which tools you want running as Activities and define them with activity_tool, drop your agent in a Workflow. Worker setup is a single line (GoogleAdkPlugin() passed to the Temporal client on connect) and it takes care of sandbox passthrough for ADK and Gemini modules, Pydantic serialization for ADK data types, and the deterministic time and UUID replacements. You're lifting your SDK into durable execution. Should you want to incorporate additional Temporal features like timers, fairness, or schedules, go for it — though it's unnecessary for the initial setup.

If you're not already an ADK user but you're on Temporal, it's more like you're selecting from a menu: here's Pydantic AI, here's OpenAI Agents SDK, here's ADK — or go without an agentic framework and just pick an observability provider like Braintrust. Pick what fits your stack, and getting an agent spun up should be pretty straightforward.

Either way, once you're running, you get full visibility into what your agent is actually doing. Every LLM call and tool execution shows up as an Activity in the Temporal UI. In a multi-agent setup, you can see which agent is doing what in real time — a pretty different debugging experience from staring at logs. ADK is particularly strong at multi-agent setups; you can build coordinator/dispatcher patterns, parallel fan-out, human-in-the-loop flows, and more (see ADK's multi-agent docs). When you run those through Temporal, you get full visibility into each agent's activity in real time and you can watch exactly which agent is doing what from the UI.

Paying it forward#

Every integration we ship sharpens how we do this. The lessons learned from ADK — the LLM registry approach, the platform abstractions for time and UUIDs, the MCP tool context work — all go into how we approach the next one. We took what we learned and put it into our AI Partner Program, so other teams can benefit from it too.

The program is currently soft-launched and invite-only. If you're building an AI framework or tool and want to integrate with Temporal, that's the place to start: t.mp/aipartnersguide.

And if you just want to try the integration: pip install "temporalio[google-adk]". Full docs at google.github.io/adk-docs/integrations/temporal.

Temporal Cloud

Ready to see for yourself?

Sign up for Temporal Cloud today and get $1,000 in free credits.

Build invincible applications

It sounds like magic, we promise it's not.