Dapr plugin for ADK¶
Dapr is a distributed workflow orchestration engine that makes ADK agents resilient to failures. LLM calls and tool executions run as Dapr Workflow activities with automatic retries and recovery. If anything fails, your agent automatically picks up exactly where it left off.
Use cases¶
The Dapr plugin gives your agents:
- Durable execution: Never lose progress. If your agent crashes or stalls, Dapr automatically recovers from the last successful activity with no need to manually resume.
- Built-in retries and backoff: Configurable retry policies with exponential backoff to handle transient failures from LLM providers and tool APIs.
- Long-running and ambient agents: Support for agents and tools that run for hours, days, or indefinitely, backed by Dapr's persistent state stores.
- Portable infrastructure: Swap 15+ databases (Redis, GCP Firestore, PostgreSQL, DynamoDB, Cosmos DB, and many more) without changing agent code. Dapr's pluggable component model lets you move from local dev to any cloud.
- Observability and debugging: Inspect every step of your agent's execution using Dapr's workflow APIs, and emit traces and metrics through Dapr's built-in OpenTelemetry integration.
Prerequisites¶
- Python 3.11+
- A Gemini API key (or any supported model)
- Dapr CLI and runtime installed (install guide)
- A configured Dapr state store component for workflow persistence
Installation¶
Install the Diagrid Agent package for Dapr, which includes the ADK extension:
Initialize Dapr:
Use with agent¶
Basic setup¶
The integration wraps your ADK agent so each LLM call and each tool execution runs as a durable Dapr Workflow activity. The runner handles workflow registration, starts the Dapr workflow runtime, and exposes an async interface for invoking the agent.
Define your agent and runner
Create an ADK agent as usual and pass it to DaprWorkflowAgentRunner.
import asyncio
from google.adk.agents import LlmAgent
from google.adk.tools import FunctionTool
from diagrid.agent.adk import DaprWorkflowAgentRunner
def get_weather(city: str) -> str:
"""Get the current weather for a city.
Args:
city: The name of the city to get weather for.
Returns:
A string describing the weather.
"""
# Your weather API call here
return f"72°F and sunny in {city}"
# Define the ADK agent
agent = LlmAgent(
name="weather_agent",
model="gemini-flash-latest",
instruction="You are a helpful assistant that can check the weather.",
tools=[FunctionTool(get_weather)],
)
async def main():
# Wrap the agent so each tool call runs as a durable Dapr activity
runner = DaprWorkflowAgentRunner(
agent=agent,
name="weather-agent",
max_iterations=10,
)
# Start the Dapr Workflow runtime
runner.start()
try:
async for event in runner.run_async(
user_message="What's the weather in San Francisco?",
session_id="session-001",
):
if event["type"] == "workflow_completed":
print(event["final_response"])
finally:
runner.shutdown()
if __name__ == "__main__":
asyncio.run(main())
Run the agent with Dapr
Dapr Workflow uses a lightweight sidecar and a configured state store. Use this command to run Dapr locally and your agent alongside it:
Note
By default Dapr uses the Redis component installed with Dapr, located at
~/.dapr/components/statestore.yaml. See supported state
stores
to change the state store used.
Crash recovery¶
If the process hosting your agent crashes mid-execution, Dapr automatically resumes the workflow from the last successful activity when the app restarts - no custom replay logic required.
# First run: process crashes after tool 1 completes.
# Second run: Dapr automatically resumes and executes tools 2 and 3.
runner = DaprWorkflowAgentRunner(agent=agent, name="sequential-agent")
runner.start()
async for event in runner.run_async(
user_message="Run the three-step pipeline.",
session_id="pipeline-001",
):
if event["type"] == "workflow_completed":
print(event["final_response"])
Because the session_id and workflow instance ID are stable, relaunching the
same app with Dapr causes the sidecar to pick up in-flight workflows and drive
them to completion, without needing to manually resume.
How it works¶
The plugin turns an ADK agent loop into a Dapr Workflow so that each step is checkpointed, retried, and automatically replayable:
- LLM calls are executed as Dapr Workflow activities. If a call fails or the worker crashes, Dapr retries according to the configured retry policy or replays the workflow from the last successful activity, adding resilience and reducing token spend.
- Tool executions are run as independent activities, one per tool call. The
workflow fans out parallel tool calls via Dapr's
when_allprimitive and waits for them to complete before re-invoking the LLM. - Workflow state (messages, tool calls, tool results) is serialized and stored in the configured Dapr state store after every activity, so any replica with access to the state store can take over execution.
- Deterministic orchestration: the
agent_workflowfunction contains only deterministic control flow; all side effects (LLM calls, tool invocations) happen inside activities, which is the model Dapr Workflow requires for replay safety.
Capabilities¶
| Capability | Description |
|---|---|
| Durable tool execution | Each ADK tool runs as a Dapr Workflow activity, with automatic retries, backoff, and replay on failure |
| Parallel tool calls | Multiple tool calls from a single LLM response are dispatched concurrently as activities and joined before the next LLM step |
| Portable state stores | Swap between Redis, GCP Firestore, PostgreSQL, Cosmos DB, and many others via Dapr components without code changes |
| Long-running agents | Workflows can run for hours, days, or indefinitely; state stays in the Dapr state store until completion |
| Observability | Every LLM call and tool execution is a workflow activity, traceable via Dapr's OpenTelemetry integration and inspectable through the workflow API |
| Kubernetes-native | Deploy the same agent to Kubernetes without code changes using Dapr's sidecar injection |
Additional resources¶
- Dapr Workflow documentation - Full reference for Dapr's workflow building block
- Diagrid Agent SDK on GitHub - Source code for the Dapr ADK integration
- Dapr Community Discord - Questions, bug reports, and community discussion
- Supported state stores - List of state store components compatible with Dapr Workflow