> ## Documentation Index
> Fetch the complete documentation index at: https://omnirexflora-labs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Google ADK Agent with Supervisor

> Production-ready Google ADK integration with process isolation

# Google ADK Agent Example

Learn how to run **[Google Agent Development Kit (ADK)](https://github.com/google/adk)** agents in production with OmniDaemon using the Supervisor pattern.

> 💡 **Working code:** [`examples/google_adk_with_supervisor/`](https://github.com/omnirexflora-labs/OmniDaemon/tree/main/examples/google_adk_with_supervisor)

***

## The Challenge

When you build AI agents with Google ADK (or any framework), running them in production means dealing with:

* ❌ **Agent crashes** - Memory errors, API failures, unexpected exceptions
* ❌ **Resource leaks** - Connections that don't close, memory that doesn't free
* ❌ **No fault isolation** - One agent's problem affects your entire system
* ❌ **Manual recovery** - You have to restart everything manually

Google ADK gives you great tools for building agents, but it doesn't solve these operational challenges. That's where OmniDaemon's supervisors come in.

***

## The Supervisor Solution

**Supervisors run your Google ADK agent in an isolated process** - like putting it in its own container.

### What This Means for Your Google ADK Agent

**Without Supervisor:**

```
Single Process
├── Event Bus
├── Google ADK Agent (with sessions, MCP tools)
└── Another Agent
    ↓
If Google ADK crashes → Everything dies ❌
```

**With Supervisor:**

```
Main Process
├── Event Bus
└── Supervisor → Google ADK Process (PID: 5678)
                 ├── Agent
                 ├── Sessions
                 └── MCP Tools
    ↓
If Google ADK crashes → Supervisor restarts it ✅
Other agents keep running ✅
```

### Why This Matters for Google ADK

Google ADK agents often:

* Maintain **session state** for conversations
* Connect to **MCP servers** for tools (filesystem, GitHub, etc.)
* Make **external API calls** to Gemini or other LLMs
* Hold **persistent connections**

All of these can fail. The Supervisor ensures:

* ✅ Failures are isolated
* ✅ Sessions can be recovered
* ✅ MCP connections restart cleanly
* ✅ No manual intervention needed

> 📚 **How supervisors work:** [Agent Supervisor Architecture](../architecture/agent-supervisor.mdx) explains the technical implementation details.

***

## How It Works

### ❌ Simple Pattern (Not Production-Ready)

Running Google ADK directly in your main process:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Google ADK agent in main process - risky
from google.adk.agents import LlmAgent

agent = LlmAgent(...)  # In main process
runner = Runner(agent=agent, ...)

async def callback(message: dict):
    # Run agent directly
    async for event in runner.run_async(...):
        if event.is_final_response():
            return event.content

await sdk.register_agent(callback=callback)  # No isolation!
```

**Problems:**

* Agent crash kills main process
* No automatic recovery
* Sessions lost on crash

### ✅ Supervisor Pattern (Production-Ready)

Running Google ADK in an isolated process:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Supervisor manages Google ADK in separate process
supervisor = await create_supervisor_from_directory(
    agent_name="google_adk_agent",
    agent_dir="./google_adk_with_supervisor",  # Agent code here
    callback_function="callback.call_google_adk_agent"
)

await sdk.register_agent(
    callback=supervisor.handle_event  # Supervisor handles everything!
)
```

**Benefits:**

* Process isolation ✅
* Auto-restart on crash ✅
* Session state preserved ✅
* MCP connections managed ✅

The supervisor spawns a new Python process, loads your Google ADK agent, and manages its entire lifecycle.

> 📚 **Complete flow:** [Agent Process Flow](../how-to-guides/agent-process-flow.mdx) shows exactly how events flow from OmniDaemon → Supervisor → Google ADK → Response.

***

## Implementation

Now that you understand why supervisors matter for Google ADK, let's build it.

### Prerequisites

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# 1. Install OmniDaemon
pip install omnidaemon

# 2. Install Google ADK
pip install google-adk

# 3. Install LiteLLM (for non-Gemini models)
pip install litellm

# 4. Start Redis
docker run -d -p 6379:6379 --name redis redis:latest

# 5. Set API keys
export GOOGLE_API_KEY=your_key  # For Gemini
# Or
export OPENAI_API_KEY=your_key  # For OpenAI via LiteLLM
```

### Directory Structure

```
google_adk_agent/
├── __init__.py
├── adk_agent.py      # Google ADK setup (runs in isolated process)
├── callback.py       # Callback function (entry point)
└── requirements.txt  # Dependencies
```

### Step 1: Google ADK Setup

Create `google_adk_agent/adk_agent.py`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.models.lite_llm import LiteLlm
from google.adk.sessions import InMemorySessionService
from google.adk.runners import Runner

# Create session service (stores conversation history)
session_service = InMemorySessionService()

# Create Google ADK agent
agent = LlmAgent(
    # Use Gemini
    model="gemini-2.0-flash",
    
    # Or use OpenAI via LiteLLM
    # model=LiteLlm(model="openai/gpt-4o"),
    
    name="filesystem_agent",
    instruction="Help manage files",
    tools=[
        McpToolset(...)  # MCP filesystem tools
    ]
)

# Create runner
runner = Runner(
    agent=agent,
    app_name="filesystem_agent",
    session_service=session_service
)
```

### Step 2: Callback Function

Create `google_adk_agent/callback.py`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from google.genai import types
from .adk_agent import runner, session_service
import logging

logger = logging.getLogger(__name__)

async def call_google_adk_agent(message: dict):
    """
    This runs in the ISOLATED PROCESS managed by the supervisor.
    
    The supervisor:
    1. Spawned this process
    2. Loaded this module
    3. Calls this function when events arrive
    4. Returns results back via stdio
    """
    # Create session for this conversation
    await session_service.create_session(
        app_name="filesystem_agent",
        user_id="user_1",
        session_id="session_001"
    )
    
    query = message.get("content", "")
    logger.info(f"Processing: {query}")
    
    # Create Google ADK content
    content = types.Content(
        role="user",
        parts=[types.Part(text=query)]
    )
    
    # Run Google ADK agent (async streaming)
    async for event in runner.run_async(
        user_id="user_1",
        session_id="session_001",
        new_message=content
    ):
        if event.is_final_response():
            response = event.content.parts[0].text
            logger.info(f"Response: {response}")
            return response
    
    return "No response from agent"
```

**Key Point:** This entire callback runs in an isolated process. If it crashes, only this process dies - the supervisor restarts it automatically.

### Step 3: Runner with Supervisor

Create `agent_runner.py`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import asyncio
import logging
from omnidaemon import OmniDaemonSDK, AgentConfig, SubscriptionConfig
from omnidaemon.agent_runner.agent_supervisor_runner import (
    create_supervisor_from_directory,
    shutdown_all_supervisors,
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

sdk = OmniDaemonSDK()
_supervisor = None

async def get_supervisor():
    """Initialize supervisor for Google ADK agent"""
    global _supervisor
    if _supervisor is None:
        _supervisor = await create_supervisor_from_directory(
            agent_name="google_adk_agent",
            agent_dir="./google_adk_agent",
            callback_function="callback.call_google_adk_agent"
        )
    return _supervisor

async def call_supervised_agent(message: dict):
    """Delegate to supervisor"""
    supervisor = await get_supervisor()
    return await supervisor.handle_event(message)

async def main():
    try:
        logger.info("Initializing Google ADK agent with supervisor...")
        await get_supervisor()  # Spawn isolated process
        
        await sdk.register_agent(
            agent_config=AgentConfig(
                name="google_adk_agent",
                topic="file.tasks",
                callback=call_supervised_agent,
                config=SubscriptionConfig(
                    reclaim_idle_ms=6000,
                    dlq_retry_limit=3,
                    consumer_count=3,
                ),
            )
        )
        
        logger.info("Starting OmniDaemon...")
        await sdk.start()
        logger.info("✅ Google ADK agent running in isolated process.")
        
        await asyncio.Event().wait()
        
    except KeyboardInterrupt:
        logger.info("Shutdown signal received")
    finally:
        logger.info("Shutting down...")
        await sdk.shutdown()
        await shutdown_all_supervisors()  # Clean shutdown of agent process
        logger.info("Shutdown complete")

if __name__ == "__main__":
    asyncio.run(main())
```

### Step 4: Run It

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
python agent_runner.py
```

Your Google ADK agent is now running in an isolated process, managed by the supervisor!

***

## Using Different LLM Providers

Google ADK works with any LLM via LiteLLM:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Gemini (native)
model="gemini-2.0-flash"

# OpenAI
model=LiteLlm(model="openai/gpt-4o")

# Anthropic
model=LiteLlm(model="anthropic/claude-3-opus")

# Azure, Mistral, Together AI, etc.
model=LiteLlm(model="azure/gpt-4")
model=LiteLlm(model="mistral/mistral-large")
```

Just change the model config - the supervisor pattern stays the same.

***

## Session Management

Google ADK uses sessions to maintain conversation history. With supervisors, sessions persist across restarts:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Multi-user sessions
async def call_google_adk_agent(message: dict):
    # Extract user from message
    user_id = message.get("tenant_id", "default_user")
    session_id = f"session_{user_id}"
    
    # Each user gets their own session
    await session_service.create_session(
        app_name="my_app",
        user_id=user_id,
        session_id=session_id
    )
    
    # Run with user-specific session
    async for event in runner.run_async(
        user_id=user_id,
        session_id=session_id,
        new_message=content
    ):
        ...
```

If the agent process crashes and restarts, sessions are recreated automatically by the supervisor.

***

## Production Deployment

### Environment Variables

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# .env
GOOGLE_API_KEY=your_key
REDIS_URL=redis://prod-redis:6379
STORAGE_BACKEND=redis
LOG_LEVEL=INFO
```

### Horizontal Scaling

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Run multiple instances - automatic load balancing
python agent_runner.py &  # Instance 1
python agent_runner.py &  # Instance 2
python agent_runner.py &  # Instance 3
```

Each instance runs its own isolated Google ADK process. OmniDaemon distributes events across all instances.

### Monitoring

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Health check
omnidaemon health

# Metrics
omnidaemon metrics --topic file.tasks

# Failed events
omnidaemon bus dlq --topic file.tasks
```

***

## Complete Working Example

See the full production implementation:

📁 **[`examples/google_adk_with_supervisor/`](https://github.com/omnirexflora-labs/OmniDaemon/tree/main/examples/google_adk_with_supervisor)**

This example shows:

* Complete Google ADK setup
* MCP filesystem tools
* Session management
* Process isolation with supervisors
* Error handling
* Graceful shutdown

***

## Understanding the Architecture

### Process Flow

```
┌────────────────────────────────────┐
│  Main Process                      │
│  ┌──────────────────────────────┐  │
│  │ AgentSupervisor              │  │
│  │ - Spawns subprocess          │  │
│  │ - Monitors health            │  │
│  │ - stdio communication        │  │
│  └──────────────────────────────┘  │
│             │ JSON over stdio       │
└─────────────┼───────────────────────┘
              ↓
       ┌──────────────────────────────┐
       │ Google ADK Process           │
       │ ┌──────────────────────────┐ │
       │ │ callback.py              │ │
       │ │ - Google ADK Agent       │ │
       │ │ - Session Service        │ │
       │ │ - MCP Tools              │ │
       │ └──────────────────────────┘ │
       └──────────────────────────────┘
```

### Related Documentation

**Understanding Supervisors:**

* [Agent Supervisor Architecture](../architecture/agent-supervisor.mdx) - How supervisors work internally
* [Process Isolation](../how-to-guides/agent-isolation.mdx) - Dependency and resource isolation

**Implementation Details:**

* [Complete Agent Process Flow](../how-to-guides/agent-process-flow.mdx) - Full lifecycle walkthrough
* [Common Patterns](https://omnirexflora-labs.mintlify.site/docs/how-to-guides/common-patterns.md) - Production best practices

**Other Examples:**

* [OmniCore Agent Example](https://omnirexflora-labs.mintlify.site/docs/examples/omnicore-agent.md) - Alternative framework with supervisors
* [Content Moderation Pipeline](content-moderation.mdx) - Multi-agent system

***

## Key Takeaways

✅ **Supervisors make Google ADK production-ready** - Process isolation prevents cascading failures\
✅ **Session state is preserved** - Sessions survive process restarts\
✅ **Works with any LLM** - Gemini, OpenAI, Anthropic via LiteLLM\
✅ **Simple integration** - `create_supervisor_from_directory()` handles complexity\
✅ **Auto-recovery** - Crashed agents restart automatically with sessions intact

**Google ADK is excellent for building agents. Supervisors make them production-ready.** Together with OmniDaemon, you get fault-tolerant, scalable AI systems.

***

**Next:** Check out the [content moderation example](content-moderation.mdx) for a multi-agent pipeline using supervisors.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.