|
| 1 | +# ADK Middleware Architecture |
| 2 | + |
| 3 | +This document describes the architecture and design of the ADK Middleware that bridges Google ADK agents with the AG-UI Protocol. |
| 4 | + |
| 5 | +## High-Level Architecture |
| 6 | + |
| 7 | +``` |
| 8 | +AG-UI Protocol ADK Middleware Google ADK |
| 9 | + │ │ │ |
| 10 | +RunAgentInput ──────> ADKAgent.run() ──────> Runner.run_async() |
| 11 | + │ │ │ |
| 12 | + │ EventTranslator │ |
| 13 | + │ │ │ |
| 14 | +BaseEvent[] <──────── translate events <──────── Event[] |
| 15 | +``` |
| 16 | + |
| 17 | +## Core Components |
| 18 | + |
| 19 | +### ADKAgent (`adk_agent.py`) |
| 20 | +The main orchestrator that: |
| 21 | +- Manages agent lifecycle and session state |
| 22 | +- Handles the bridge between AG-UI Protocol and ADK |
| 23 | +- Coordinates tool execution through proxy tools |
| 24 | +- Implements direct agent embedding pattern |
| 25 | + |
| 26 | +### EventTranslator (`event_translator.py`) |
| 27 | +Converts between event formats: |
| 28 | +- ADK events → AG-UI protocol events (16 standard event types) |
| 29 | +- Maintains proper message boundaries |
| 30 | +- Handles streaming text content |
| 31 | +- Per-session instances for thread safety |
| 32 | + |
| 33 | +### SessionManager (`session_manager.py`) |
| 34 | +Singleton pattern for centralized session control: |
| 35 | +- Automatic session cleanup with configurable timeouts |
| 36 | +- Session isolation per user |
| 37 | +- Memory service integration for session persistence |
| 38 | +- Resource management and limits |
| 39 | + |
| 40 | +### ExecutionState (`execution_state.py`) |
| 41 | +Tracks background ADK executions: |
| 42 | +- Manages asyncio tasks running ADK agents |
| 43 | +- Event queue for streaming results |
| 44 | +- Execution timing and completion tracking |
| 45 | +- Tool call state management |
| 46 | + |
| 47 | +### ClientProxyTool (`client_proxy_tool.py`) |
| 48 | +Individual tool proxy implementation: |
| 49 | +- Wraps AG-UI tools for ADK compatibility |
| 50 | +- Emits tool events to client |
| 51 | +- Currently all tools are long-running |
| 52 | +- Integrates with ADK's tool system |
| 53 | + |
| 54 | +### ClientProxyToolset (`client_proxy_toolset.py`) |
| 55 | +Manages collections of proxy tools: |
| 56 | +- Dynamic toolset creation per request |
| 57 | +- Fresh tool instances for each execution |
| 58 | +- Combines client and backend tools |
| 59 | + |
| 60 | +## Event Flow |
| 61 | + |
| 62 | +1. **Client Request**: AG-UI Protocol `RunAgentInput` received |
| 63 | +2. **Session Resolution**: SessionManager finds or creates session |
| 64 | +3. **Agent Execution**: ADK Runner executes agent with context |
| 65 | +4. **Tool Handling**: ClientProxyTools emit events for client-side execution |
| 66 | +5. **Event Translation**: ADK events converted to AG-UI events |
| 67 | +6. **Streaming Response**: Events streamed back via SSE or other transport |
| 68 | + |
| 69 | +## Key Design Patterns |
| 70 | + |
| 71 | +### Direct Agent Embedding |
| 72 | +```python |
| 73 | +# Agents are directly embedded in ADKAgent instances |
| 74 | +agent = ADKAgent( |
| 75 | + adk_agent=my_adk_agent, # Direct reference |
| 76 | + app_name="my_app", |
| 77 | + user_id="user123" |
| 78 | +) |
| 79 | +``` |
| 80 | + |
| 81 | +### Service Dependency Injection |
| 82 | +The middleware uses dependency injection for ADK services: |
| 83 | +- Session service (default: InMemorySessionService) |
| 84 | +- Memory service (optional, enables session persistence) |
| 85 | +- Artifact service (default: InMemoryArtifactService) |
| 86 | +- Credential service (default: InMemoryCredentialService) |
| 87 | + |
| 88 | +### Tool Proxy Pattern |
| 89 | +All client-supplied tools are wrapped as long-running ADK tools: |
| 90 | +- Emit events for client-side execution |
| 91 | +- Can be combined with backend tools |
| 92 | +- Unified tool handling interface |
| 93 | + |
| 94 | +### Session Lifecycle |
| 95 | +1. Session created on first request |
| 96 | +2. Maintained across multiple runs |
| 97 | +3. Automatic cleanup after timeout |
| 98 | +4. Optional persistence to memory service |
| 99 | + |
| 100 | +## Thread Safety |
| 101 | + |
| 102 | +- Per-session EventTranslator instances |
| 103 | +- Singleton SessionManager with proper locking |
| 104 | +- Isolated execution states per thread |
| 105 | +- Thread-safe event queues |
| 106 | + |
| 107 | +## Error Handling |
| 108 | + |
| 109 | +- RunErrorEvent for various failure scenarios |
| 110 | +- Proper async exception handling |
| 111 | +- Resource cleanup on errors |
| 112 | +- Timeout management at multiple levels |
| 113 | + |
| 114 | +## Performance Considerations |
| 115 | + |
| 116 | +- Async/await throughout for non-blocking operations |
| 117 | +- Event streaming for real-time responses |
| 118 | +- Configurable concurrent execution limits |
| 119 | +- Automatic stale execution cleanup |
| 120 | +- Efficient event queue management |
| 121 | + |
| 122 | +## Future Enhancements |
| 123 | + |
| 124 | +- Additional tool execution modes |
| 125 | +- Enhanced state synchronization |
| 126 | +- More sophisticated error recovery |
| 127 | +- Performance optimizations |
| 128 | +- Extended protocol support |
0 commit comments