Skip to content

Commit 1f9da91

Browse files
mefogleclaude
andcommitted
feat: eliminate AgentRegistry and implement direct agent embedding
- BREAKING: ADKAgent constructor now requires adk_agent parameter instead of agent_id - BREAKING: Removed AgentRegistry dependency - agents directly embedded in middleware instances - BREAKING: Removed agent_id parameter from ADKAgent.run() method - BREAKING: AgentRegistry class removed from public API - ARCHITECTURE: Eliminated confusing indirection where endpoint agent didn't determine execution - ARCHITECTURE: Each ADKAgent instance now directly holds its ADK agent instance - ARCHITECTURE: Simplified method signatures and removed agent lookup overhead - FIXED: All 271 tests now pass with new simplified architecture - EXAMPLES: Updated examples to demonstrate direct agent embedding pattern - TESTS: Updated all test fixtures to work with new agent embedding pattern 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 20bce0b commit 1f9da91

22 files changed

+278
-889
lines changed

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

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

88
## [Unreleased]
99

10+
## [0.5.0] - 2025-01-08
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+
- **EXAMPLES**: Updated examples to demonstrate direct agent embedding pattern
29+
- **TESTS**: Updated all test fixtures to work with new agent embedding pattern
30+
1031
### Added
1132
- **NEW**: SystemMessage support for ADK agents (issue #22) - SystemMessages as first message are now appended to agent instructions
1233
- **NEW**: Comprehensive tests for SystemMessage functionality including edge cases
34+
- **NEW**: Long running tools can be defined in backend side as well
35+
- **NEW**: Predictive state demo is added in dojo App
1336

1437
### Fixed
1538
- **FIXED**: Race condition in tool result processing causing "No pending tool calls found" warnings
1639
- **FIXED**: Tool call removal now happens after pending check to prevent race conditions
1740
- **IMPROVED**: Better handling of empty tool result content with graceful JSON parsing fallback
1841
- **FIXED**: Pending tool call state management now uses SessionManager methods (issue #25)
42+
- **FIXED**: Pending tools issue for normal backend tools is now fixed (issue #32)
43+
- **FIXED**: TestEventTranslatorComprehensive unit test cases fixed
1944

2045
### Enhanced
2146
- **LOGGING**: Added debug logging for tool result processing to aid in troubleshooting

typescript-sdk/integrations/adk-middleware/examples/complete_setup.py

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
# from adk_agent import ADKAgent
2626
# from agent_registry import AgentRegistry
2727
# from endpoint import add_adk_fastapi_endpoint
28-
from adk_middleware import ADKAgent, AgentRegistry, add_adk_fastapi_endpoint
28+
from adk_middleware import ADKAgent, add_adk_fastapi_endpoint
2929
# Import Google ADK components
3030
from google.adk.agents import Agent
3131
from google.adk import tools as adk_tools
@@ -74,32 +74,22 @@ async def setup_and_run():
7474
tools=[adk_tools.preload_memory_tool.PreloadMemoryTool()]
7575
)
7676

77-
# Step 3: Register agents
78-
print("📝 Registering agents...")
79-
registry = AgentRegistry.get_instance()
80-
81-
# Register with specific IDs that AG-UI clients can reference
82-
registry.register_agent("assistant", assistant)
83-
84-
# Try to import and register haiku generator agent
77+
# Try to import haiku generator agent
8578
print("🎋 Attempting to import haiku generator agent...")
79+
haiku_generator_agent = None
8680
try:
8781
from tool_based_generative_ui.agent import haiku_generator_agent
8882
print(f" ✅ Successfully imported haiku_generator_agent")
8983
print(f" Type: {type(haiku_generator_agent)}")
9084
print(f" Name: {getattr(haiku_generator_agent, 'name', 'NO NAME')}")
91-
registry.register_agent('adk-tool-based-generative-ui', haiku_generator_agent)
92-
print(f" ✅ Registered as 'adk-tool-based-generative-ui'")
85+
print(f" ✅ Available for use")
9386
except Exception as e:
9487
print(f" ❌ Failed to import haiku_generator_agent: {e}")
9588

96-
# Set default agent
97-
registry.set_default_agent(assistant)
98-
99-
# List all registered agents
100-
print("\n📋 Currently registered agents:")
101-
for agent_id in registry.list_registered_agents():
102-
print(f" - {agent_id}")
89+
print(f"\n📋 Available agents:")
90+
print(f" - assistant: {assistant.name}")
91+
if haiku_generator_agent:
92+
print(f" - haiku_generator: {haiku_generator_agent.name}")
10393

10494

10595
# Step 4: Configure ADK middleware
@@ -127,14 +117,26 @@ def extract_app_name(input_data):
127117
return ctx.value
128118
return "default_app"
129119

130-
adk_agent = ADKAgent(
120+
# Create ADKAgent instances for different agents
121+
assistant_adk_agent = ADKAgent(
122+
adk_agent=assistant,
131123
app_name_extractor=extract_app_name,
132124
user_id_extractor=extract_user_id,
133125
use_in_memory_services=True,
134126
memory_service=shared_memory_service, # Use the same memory service as the ADK agent
135127
# Defaults: 1200s timeout (20 min), 300s cleanup (5 min)
136128
)
137129

130+
haiku_adk_agent = None
131+
if haiku_generator_agent:
132+
haiku_adk_agent = ADKAgent(
133+
adk_agent=haiku_generator_agent,
134+
app_name_extractor=extract_app_name,
135+
user_id_extractor=extract_user_id,
136+
use_in_memory_services=True,
137+
memory_service=shared_memory_service,
138+
)
139+
138140
# Step 5: Create FastAPI app
139141
print("🌐 Creating FastAPI app...")
140142
app = FastAPI(
@@ -153,52 +155,60 @@ def extract_app_name(input_data):
153155

154156

155157
# Step 6: Add endpoints
156-
# Main chat endpoint
157-
add_adk_fastapi_endpoint(app, adk_agent, path="/chat")
158-
159-
# Add haiku generator endpoint
160-
add_adk_fastapi_endpoint(app, adk_agent, path="/adk-tool-based-generative-ui")
161-
print(" ✅ Added endpoint: /adk-tool-based-generative-ui")
162-
163-
# Agent-specific endpoints (optional)
164-
# This allows clients to specify which agent to use via the URL
165-
# add_adk_fastapi_endpoint(app, adk_agent, path="/agents/assistant")
166-
# add_adk_fastapi_endpoint(app, adk_agent, path="/agents/code-helper")
158+
# Each endpoint uses its specific ADKAgent instance
159+
add_adk_fastapi_endpoint(app, assistant_adk_agent, path="/chat")
160+
161+
# Add haiku generator endpoint if available
162+
if haiku_adk_agent:
163+
add_adk_fastapi_endpoint(app, haiku_adk_agent, path="/adk-tool-based-generative-ui")
164+
print(" ✅ Added endpoint: /adk-tool-based-generative-ui")
165+
else:
166+
print(" ❌ Skipped haiku endpoint - agent not available")
167+
168+
# Agent-specific endpoints (optional) - each would use its own ADKAgent instance
169+
# assistant_adk_agent = ADKAgent(adk_agent=assistant, ...)
170+
# add_adk_fastapi_endpoint(app, assistant_adk_agent, path="/agents/assistant")
171+
# code_helper_adk_agent = ADKAgent(adk_agent=code_helper, ...)
172+
# add_adk_fastapi_endpoint(app, code_helper_adk_agent, path="/agents/code-helper")
167173

168174
@app.get("/")
169175
async def root():
170-
registry = AgentRegistry.get_instance()
176+
available_agents = ["assistant"]
177+
endpoints = {"chat": "/chat", "docs": "/docs", "health": "/health"}
178+
if haiku_generator_agent:
179+
available_agents.append("haiku-generator")
180+
endpoints["adk-tool-based-generative-ui"] = "/adk-tool-based-generative-ui"
181+
171182
return {
172183
"service": "ADK-AG-UI Integration",
173184
"version": "0.1.0",
174185
"agents": {
175186
"default": "assistant",
176-
"available": registry.list_registered_agents()
187+
"available": available_agents
177188
},
178-
"endpoints": {
179-
"chat": "/chat",
180-
"adk-tool-based-generative-ui": "/adk-tool-based-generative-ui",
181-
"docs": "/docs",
182-
"health": "/health"
183-
}
189+
"endpoints": endpoints
184190
}
185191

186192
@app.get("/health")
187193
async def health():
188-
registry = AgentRegistry.get_instance()
194+
agent_count = 1 # assistant
195+
if haiku_generator_agent:
196+
agent_count += 1
189197
return {
190198
"status": "healthy",
191-
"agents_registered": len(registry._agents),
192-
"default_agent": registry._default_agent_id
199+
"agents_available": agent_count,
200+
"default_agent": "assistant"
193201
}
194202

195203
@app.get("/agents")
196204
async def list_agents():
197205
"""List available agents."""
198-
registry = AgentRegistry.get_instance()
206+
available_agents = ["assistant"]
207+
if haiku_generator_agent:
208+
available_agents.append("haiku-generator")
199209
return {
200-
"agents": list(registry._agents.keys()),
201-
"default": registry._default_agent_id
210+
"agents": available_agents,
211+
"default": "assistant"
202212
}
203213

204214

typescript-sdk/integrations/adk-middleware/examples/fastapi_server.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .tool_based_generative_ui.agent import haiku_generator_agent
1313
from .human_in_the_loop.agent import human_in_loop_agent
1414
from .shared_state.agent import shared_state_agent
15+
from .predictive_state_updates.agent import predictive_state_updates_agent
1516

1617
# Basic logging configuration
1718
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@@ -22,48 +23,52 @@
2223
# from src.agent_registry import AgentRegistry
2324
# from src.endpoint import add_adk_fastapi_endpoint
2425

25-
from adk_middleware import ADKAgent, AgentRegistry, add_adk_fastapi_endpoint
26+
from adk_middleware import ADKAgent, add_adk_fastapi_endpoint
2627
from google.adk.agents import LlmAgent
2728
from google.adk import tools as adk_tools
2829

29-
# Set up the agent registry
30-
registry = AgentRegistry.get_instance()
31-
3230
# Create a sample ADK agent (this would be your actual agent)
3331
sample_agent = LlmAgent(
3432
name="assistant",
3533
model="gemini-2.0-flash",
36-
instruction="You are a helpful assistant.",
34+
instruction="You are a helpful assistant. Help users by answering their questions and assisting with their needs.",
3735
tools=[adk_tools.preload_memory_tool.PreloadMemoryTool()]
3836
)
39-
# Register the agent
40-
registry.set_default_agent(sample_agent)
41-
registry.register_agent('adk-tool-based-generative-ui', haiku_generator_agent)
42-
registry.register_agent('adk-human-in-loop-agent', human_in_loop_agent)
43-
registry.register_agent('adk-shared-state-agent', shared_state_agent)
44-
# Create ADK middleware agent
45-
adk_agent = ADKAgent(
37+
# Create ADK middleware agent instances with direct agent references
38+
chat_agent = ADKAgent(
39+
adk_agent=sample_agent,
4640
app_name="demo_app",
4741
user_id="demo_user",
4842
session_timeout_seconds=3600,
4943
use_in_memory_services=True
5044
)
5145

5246
adk_agent_haiku_generator = ADKAgent(
47+
adk_agent=haiku_generator_agent,
5348
app_name="demo_app",
5449
user_id="demo_user",
5550
session_timeout_seconds=3600,
5651
use_in_memory_services=True
5752
)
5853

5954
adk_human_in_loop_agent = ADKAgent(
55+
adk_agent=human_in_loop_agent,
6056
app_name="demo_app",
6157
user_id="demo_user",
6258
session_timeout_seconds=3600,
6359
use_in_memory_services=True
6460
)
6561

6662
adk_shared_state_agent = ADKAgent(
63+
adk_agent=shared_state_agent,
64+
app_name="demo_app",
65+
user_id="demo_user",
66+
session_timeout_seconds=3600,
67+
use_in_memory_services=True
68+
)
69+
70+
adk_predictive_state_agent = ADKAgent(
71+
adk_agent=predictive_state_updates_agent,
6772
app_name="demo_app",
6873
user_id="demo_user",
6974
session_timeout_seconds=3600,
@@ -74,10 +79,11 @@
7479
app = FastAPI(title="ADK Middleware Demo")
7580

7681
# Add the ADK endpoint
77-
add_adk_fastapi_endpoint(app, adk_agent, path="/chat")
82+
add_adk_fastapi_endpoint(app, chat_agent, path="/chat")
7883
add_adk_fastapi_endpoint(app, adk_agent_haiku_generator, path="/adk-tool-based-generative-ui")
7984
add_adk_fastapi_endpoint(app, adk_human_in_loop_agent, path="/adk-human-in-loop-agent")
8085
add_adk_fastapi_endpoint(app, adk_shared_state_agent, path="/adk-shared-state-agent")
86+
add_adk_fastapi_endpoint(app, adk_predictive_state_agent, path="/adk-predictive-state-agent")
8187

8288
@app.get("/")
8389
async def root():

typescript-sdk/integrations/adk-middleware/src/adk_middleware/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
"""
77

88
from .adk_agent import ADKAgent
9-
from .agent_registry import AgentRegistry
109
from .event_translator import EventTranslator
1110
from .session_manager import SessionManager
1211
from .endpoint import add_adk_fastapi_endpoint, create_adk_app
1312

14-
__all__ = ['ADKAgent', 'AgentRegistry', 'add_adk_fastapi_endpoint', 'create_adk_app','EventTranslator','SessionManager']
13+
__all__ = ['ADKAgent', 'add_adk_fastapi_endpoint', 'create_adk_app', 'EventTranslator', 'SessionManager']
1514

1615
__version__ = "0.1.0"

0 commit comments

Comments
 (0)