Skip to content

Commit 5d16bb1

Browse files
Merge pull request #36 from Contextable/issue-24-cleanup-agent-registration
feat: eliminate AgentRegistry and implement direct agent embedding
2 parents ceec7e6 + 848b465 commit 5d16bb1

26 files changed

+333
-975
lines changed

typescript-sdk/integrations/adk-middleware/CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.5.0] - 2025-08-05
11+
12+
### Breaking Changes
13+
- **BREAKING**: ADKAgent constructor now requires `adk_agent` parameter instead of `agent_id` for direct agent embedding
14+
- **BREAKING**: Removed AgentRegistry dependency - agents are now directly embedded in middleware instances
15+
- **BREAKING**: Removed `agent_id` parameter from `ADKAgent.run()` method
16+
- **BREAKING**: Endpoint registration no longer extracts agent_id from URL path
17+
- **BREAKING**: AgentRegistry class removed from public API
18+
19+
### Architecture Improvements
20+
- **ARCHITECTURE**: Eliminated AgentRegistry entirely - simplified architecture by embedding ADK agents directly
21+
- **ARCHITECTURE**: Cleaned up agent registration/instantiation redundancy (issue #24)
22+
- **ARCHITECTURE**: Removed confusing indirection where endpoint agent didn't determine execution
23+
- **ARCHITECTURE**: Each ADKAgent instance now directly holds its ADK agent instance
24+
- **ARCHITECTURE**: Simplified method signatures and removed agent lookup overhead
25+
26+
### Fixed
27+
- **FIXED**: All 271 tests now pass with new simplified architecture
28+
- **TESTS**: Updated all test fixtures to match new ADKAgent.run(input_data) signature without agent_id parameter
29+
- **TESTS**: Fixed test expectations in test_endpoint.py to work with direct agent embedding architecture
30+
- **TESTS**: Updated all test fixtures to work with new agent embedding pattern
31+
- **EXAMPLES**: Updated examples to demonstrate direct agent embedding pattern
32+
1033
### Added
1134
- **NEW**: SystemMessage support for ADK agents (issue #22) - SystemMessages as first message are now appended to agent instructions
1235
- **NEW**: Comprehensive tests for SystemMessage functionality including edge cases

typescript-sdk/integrations/adk-middleware/LOGGING.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import logging
3838
logging.getLogger().setLevel(logging.DEBUG)
3939

4040
# Or configure specific components
41-
components = ['adk_agent', 'event_translator', 'endpoint', 'session_manager', 'agent_registry']
41+
components = ['adk_agent', 'event_translator', 'endpoint', 'session_manager']
4242
for component in components:
4343
logging.getLogger(component).setLevel(logging.DEBUG)
4444
```
@@ -51,7 +51,6 @@ for component in components:
5151
| `endpoint` | HTTP endpoint responses | WARNING |
5252
| `adk_agent` | Main agent logic | INFO |
5353
| `session_manager` | Session management | WARNING |
54-
| `agent_registry` | Agent registration | WARNING |
5554

5655
## Python API
5756

@@ -128,8 +127,7 @@ components = {
128127
'adk_agent': os.getenv('LOG_ADK_AGENT', 'INFO'),
129128
'event_translator': os.getenv('LOG_EVENT_TRANSLATOR', 'WARNING'),
130129
'endpoint': os.getenv('LOG_ENDPOINT', 'WARNING'),
131-
'session_manager': os.getenv('LOG_SESSION_MANAGER', 'WARNING'),
132-
'agent_registry': os.getenv('LOG_AGENT_REGISTRY', 'WARNING')
130+
'session_manager': os.getenv('LOG_SESSION_MANAGER', 'WARNING')
133131
}
134132

135133
for component, level in components.items():

typescript-sdk/integrations/adk-middleware/README.md

Lines changed: 65 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This Python middleware enables Google ADK agents to be used with the AG-UI Proto
77
- ⚠️ Full event translation between AG-UI and ADK (partial - full support coming soon)
88
- ✅ Automatic session management with configurable timeouts
99
- ✅ Automatic session memory option - expired sessions automatically preserved in ADK memory service
10-
- ✅ Support for multiple agents with centralized registry
10+
- ✅ Support for multiple agents with direct embedding
1111
- ❌ State synchronization between protocols (coming soon)
1212
-**Complete bidirectional tool support** - Enable AG-UI Protocol tools within Google ADK agents
1313
- ✅ Streaming responses with SSE
@@ -49,7 +49,7 @@ Although this is a Python integration, it lives in `typescript-sdk/integrations/
4949

5050
### Option 1: Direct Usage
5151
```python
52-
from adk_middleware import ADKAgent, AgentRegistry
52+
from adk_middleware import ADKAgent
5353
from google.adk.agents import Agent
5454

5555
# 1. Create your ADK agent
@@ -58,30 +58,38 @@ my_agent = Agent(
5858
instruction="You are a helpful assistant."
5959
)
6060

61-
# 2. Register the agent
62-
registry = AgentRegistry.get_instance()
63-
registry.set_default_agent(my_agent)
64-
65-
# 3. Create the middleware
66-
agent = ADKAgent(app_name="my_app", user_id="user123")
61+
# 2. Create the middleware with direct agent embedding
62+
agent = ADKAgent(
63+
adk_agent=my_agent,
64+
app_name="my_app",
65+
user_id="user123"
66+
)
6767

68-
# 4. Use directly with AG-UI RunAgentInput
68+
# 3. Use directly with AG-UI RunAgentInput
6969
async for event in agent.run(input_data):
7070
print(f"Event: {event.type}")
7171
```
7272

7373
### Option 2: FastAPI Server
7474
```python
7575
from fastapi import FastAPI
76-
from adk_middleware import ADKAgent, AgentRegistry, add_adk_fastapi_endpoint
76+
from adk_middleware import ADKAgent, add_adk_fastapi_endpoint
7777
from google.adk.agents import Agent
7878

79-
# Set up agent and registry (same as above)
80-
registry = AgentRegistry.get_instance()
81-
registry.set_default_agent(my_agent)
82-
agent = ADKAgent(app_name="my_app", user_id="user123")
79+
# 1. Create your ADK agent
80+
my_agent = Agent(
81+
name="assistant",
82+
instruction="You are a helpful assistant."
83+
)
84+
85+
# 2. Create the middleware with direct agent embedding
86+
agent = ADKAgent(
87+
adk_agent=my_agent,
88+
app_name="my_app",
89+
user_id="user123"
90+
)
8391

84-
# Create FastAPI app
92+
# 3. Create FastAPI app
8593
app = FastAPI()
8694
add_adk_fastapi_endpoint(app, agent, path="/chat")
8795

@@ -90,32 +98,15 @@ add_adk_fastapi_endpoint(app, agent, path="/chat")
9098

9199
## Configuration Options
92100

93-
### Agent Registry
94-
95-
The `AgentRegistry` provides flexible agent mapping:
96-
97-
```python
98-
registry = AgentRegistry.get_instance()
99-
100-
# Option 1: Default agent for all requests
101-
registry.set_default_agent(my_agent)
102-
103-
# Option 2: Map specific agent IDs
104-
registry.register_agent("support", support_agent)
105-
registry.register_agent("coder", coding_agent)
106-
107-
# Option 3: Dynamic agent creation
108-
def create_agent(agent_id: str) -> BaseAgent:
109-
return Agent(name=agent_id, instruction="You are a helpful assistant.")
110-
111-
registry.set_agent_factory(create_agent)
112-
```
113-
114101
### App and User Identification
115102

116103
```python
117104
# Static app name and user ID (single-tenant apps)
118-
agent = ADKAgent(app_name="my_app", user_id="static_user")
105+
agent = ADKAgent(
106+
adk_agent=my_agent,
107+
app_name="my_app",
108+
user_id="static_user"
109+
)
119110

120111
# Dynamic extraction from context (recommended for multi-tenant)
121112
def extract_app(input: RunAgentInput) -> str:
@@ -133,6 +124,7 @@ def extract_user(input: RunAgentInput) -> str:
133124
return f"anonymous_{input.thread_id}"
134125

135126
agent = ADKAgent(
127+
adk_agent=my_agent,
136128
app_name_extractor=extract_app,
137129
user_id_extractor=extract_user
138130
)
@@ -219,19 +211,16 @@ my_agent = Agent(
219211
tools=[adk_tools.preload_memory_tool.PreloadMemoryTool()] # Add memory tools here
220212
)
221213

222-
# Register the agent
223-
registry = AgentRegistry.get_instance()
224-
registry.set_default_agent(my_agent)
225-
226-
# Create middleware WITHOUT tools parameter - THIS IS CORRECT
214+
# Create middleware with direct agent embedding
227215
adk_agent = ADKAgent(
216+
adk_agent=my_agent,
228217
app_name="my_app",
229218
user_id="user123",
230219
memory_service=shared_memory_service # Memory service enables automatic session memory
231220
)
232221
```
233222

234-
**⚠️ Important**: The `tools` parameter belongs to the ADK agent (like `Agent` or `LlmAgent`), **not** to the `ADKAgent` middleware. The middleware automatically handles any tools defined on the registered agents.
223+
**⚠️ Important**: The `tools` parameter belongs to the ADK agent (like `Agent` or `LlmAgent`), **not** to the `ADKAgent` middleware. The middleware automatically handles any tools defined on the embedded agents.
235224

236225
### Memory Testing Configuration
237226

@@ -377,7 +366,7 @@ toolset = ClientProxyToolset(
377366
### Tool Configuration
378367

379368
```python
380-
from adk_middleware import ADKAgent, AgentRegistry
369+
from adk_middleware import ADKAgent
381370
from google.adk.agents import LlmAgent
382371
from ag_ui.core import RunAgentInput, UserMessage, Tool
383372

@@ -431,11 +420,9 @@ agent = LlmAgent(
431420
Use calculate for math operations and get_weather for weather information."""
432421
)
433422

434-
registry = AgentRegistry.get_instance()
435-
registry.set_default_agent(agent)
436-
437423
# 3. Create middleware with hybrid execution configuration
438424
adk_agent = ADKAgent(
425+
adk_agent=agent,
439426
user_id="user123",
440427
tool_timeout_seconds=60, # Timeout for blocking tools only
441428
execution_timeout_seconds=300, # Overall execution timeout
@@ -664,18 +651,19 @@ This will start a FastAPI server that connects your ADK middleware to the Dojo a
664651

665652
```python
666653
import asyncio
667-
from adk_middleware import ADKAgent, AgentRegistry
654+
from adk_middleware import ADKAgent
668655
from google.adk.agents import Agent
669656
from ag_ui.core import RunAgentInput, UserMessage
670657

671658
async def main():
672659
# Setup
673-
registry = AgentRegistry.get_instance()
674-
registry.set_default_agent(
675-
Agent(name="assistant", instruction="You are a helpful assistant.")
676-
)
660+
my_agent = Agent(name="assistant", instruction="You are a helpful assistant.")
677661

678-
agent = ADKAgent(app_name="demo_app", user_id="demo")
662+
agent = ADKAgent(
663+
adk_agent=my_agent,
664+
app_name="demo_app",
665+
user_id="demo"
666+
)
679667

680668
# Create input
681669
input = RunAgentInput(
@@ -702,17 +690,33 @@ asyncio.run(main())
702690
### Multi-Agent Setup
703691

704692
```python
705-
# Register multiple agents
706-
registry = AgentRegistry.get_instance()
707-
registry.register_agent("general", general_agent)
708-
registry.register_agent("technical", technical_agent)
709-
registry.register_agent("creative", creative_agent)
693+
# Create multiple agent instances with different ADK agents
694+
general_agent_wrapper = ADKAgent(
695+
adk_agent=general_agent,
696+
app_name="demo_app",
697+
user_id="demo"
698+
)
710699

711-
# The middleware uses the default agent from the registry
712-
agent = ADKAgent(
700+
technical_agent_wrapper = ADKAgent(
701+
adk_agent=technical_agent,
702+
app_name="demo_app",
703+
user_id="demo"
704+
)
705+
706+
creative_agent_wrapper = ADKAgent(
707+
adk_agent=creative_agent,
713708
app_name="demo_app",
714-
user_id="demo" # Or use user_id_extractor for dynamic extraction
709+
user_id="demo"
715710
)
711+
712+
# Use different endpoints for each agent
713+
from fastapi import FastAPI
714+
from adk_middleware import add_adk_fastapi_endpoint
715+
716+
app = FastAPI()
717+
add_adk_fastapi_endpoint(app, general_agent_wrapper, path="/agents/general")
718+
add_adk_fastapi_endpoint(app, technical_agent_wrapper, path="/agents/technical")
719+
add_adk_fastapi_endpoint(app, creative_agent_wrapper, path="/agents/creative")
716720
```
717721

718722
## Event Translation

0 commit comments

Comments
 (0)