xiaohongshu
xiaohongshu
adk-agent-handling
Google ADK (Agent Development Kit) multi-agent system architecture for BigQuery data analytics. Covers BigQuery agent vs conversational agent patterns, ADK Single Parent Rule, domain routing with sub-agents, agent selection mechanisms, SQL error recovery with ReflectAndRetryToolPlugin, transfer_t...
Full skill instructions
Complete guide for architecting and managing Google ADK multi-agent systems in the ALYac Family data analytics platform. This skill covers the dual-orchestrator pattern (BigQuery vs Conversational agents), ADK framework constraints, domain-based routing, and production-ready error recovery strategies.
Automatically activates when you mention:
Manual activation: Ask about ADK agent architecture, agent selection mechanisms, or error recovery strategies.
This project uses TWO top-level orchestrator agents:
1. bigquery_agent (SQL-based orchestrator)
adk-backend/src/adk_backend/agents/base/bigquery_agent.py2. conversational_analytics_agent (AI-based orchestrator)
adk-backend/src/adk_backend/agents/base/conversational_analytics_agent.pyBoth orchestrators delegate to these specialists:
Critical: Domain experts are sub_agents of bigquery_agent ONLY, following ADK's Single Parent Rule.
Every agent can have ONLY ONE parent agent.
Violation example:
# ❌ WRONG - Two parents
bigquery_agent = Agent(sub_agents=[alyac_family_agent, ...])
conversational_agent = Agent(sub_agents=[alyac_family_agent, ...]) # ERROR!
Error: ValidationError: Agent 'alyac_family_analyst' already has a parent agent
# ✅ CORRECT - Single parent
# bigquery_agent: Has domain expert sub_agents
bigquery_agent = Agent(
name="general_orchestrator",
sub_agents=[alyac_family_agent, security_agent, marketing_agent, conversion_agent]
)
# conversational_analytics_agent: No sub_agents (tools only)
conversational_agent = Agent(
name="conversational_analyst",
tools=[ask_data_insights, search_catalog, google_search],
sub_agents=[] # Empty - uses AI tools instead
)
Reference: See reference/single_parent_rule.md for official ADK documentation and detailed examples.
File: adk-backend/src/adk_backend/services/agent_selector.py
def select_agent_for_request(
agent_type: Optional[str], # "sql" or "conversational"
message: str,
conversation_history: Iterable[Tuple[str, Optional[str]]]
) -> Tuple[AgentInfo, str, str]:
"""
Routes requests based on:
1. Explicit agent_type selection
2. Keyword matching in message content
"""
Routing Logic:
agent_type="conversational" → conversational_analytics_agent (default)agent_type="sql" + keywords → Domain expert agent
Discovery (from 05_domain_routing_frontend_analysis.md):
Frontend domain state is NOT sent to backend!
// frontend/src/App.tsx:293-299
const stopStream = apiService.streamQuery({
query: trimmed,
user_id: 'demo-user',
session_id: 'demo-session',
agent_type: agentType // ✅ Only agent_type is sent, NOT domain!
})
Implication:
Reference: See reference/routing.md for complete flow analysis and mismatch scenarios.
Real error (2025-11-16):
WHERE detection_timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 MONTH)
BigQuery Error:
400 POST: TIMESTAMP_SUB does not support the MONTH date part
when the argument is TIMESTAMP type
Root cause: TIMESTAMP_SUB only supports DAY, HOUR, MINUTE, SECOND (not MONTH/YEAR)
Add explicit constraints to agent instructions:
"## SQL 작성 지침\n"
"- 시간 필터: **반드시 DAY 단위만 사용**\n"
" - ✅ 올바름: `TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)` (1개월)\n"
" - ❌ 금지: `TIMESTAMP_SUB(..., INTERVAL 1 MONTH)` → TIMESTAMP 타입에서 MONTH 지원 안 됨\n"
Applied to: All 4 domain expert agents
Files: alyac_family_domain_expert.py, security_domain_expert.py, conversion_domain_expert.py, marketing_domain_expert.py
Effectiveness: ~90% prevention rate
Google ADK's official auto-retry mechanism:
# adk-backend/src/adk_backend/api/chat.py
from google.adk.plugins import ReflectAndRetryToolPlugin
runner = InMemoryRunner(
app_name="ADK Chat Stream",
agent=agent,
plugins=[
ReflectAndRetryToolPlugin(
max_retries=2, # Total 3 attempts
throw_exception_if_retry_exceeded=True,
),
],
)
How it works:
Effectiveness: ~80% recovery rate of remaining 10%
User Query: "최근 한 달간 스미싱 TOP5"
↓
[1st Defense] Instruction (90% prevention)
AI generates: INTERVAL 30 DAY ✅
↓
BigQuery executes successfully (no retry needed)
↓
User receives results (fast)
If instruction missed:
[1st Defense] Instruction missed
AI generates: INTERVAL 1 MONTH ❌
↓
BigQuery error
↓
[2nd Defense] ReflectAndRetryToolPlugin (80% recovery)
Plugin: "Error detected, feedback to AI..."
↓
AI corrects: INTERVAL 30 DAY ✅
↓
BigQuery retry succeeds
↓
User receives results (slightly slower)
Combined success rate: ~98%
Reference: See reference/error_recovery.md for complete error patterns, custom plugin examples, and SQL validation layer.
bigquery_agent → Domain Expert:
# In bigquery_agent instruction
"""
## 도메인 에이전트 위임 규칙
- `alyac_family_analyst`: 악성 앱·피싱 메시지·ALYac Family 고유 지표
- `security_analyst`: 스미싱, FCM 보안 이벤트, 악성앱/위협 경보
- `marketing_analyst`: 캠페인, 세그먼트, 가족 초대, 구독 전환
- `conversion_analyst`: 구독/퍼널/리텐션/코호트 등 SaaS 핵심 지표
위임이 필요할 때는 반드시 `transfer_to_agent`를 사용해 해당 이름을 호출하고,
응답을 사용자에게 요약/보완하세요.
"""
Flow:
User: "최근 악성 앱 Top 5는?"
↓
bigquery_agent detects keyword "악성 앱"
↓
transfer_to_agent("alyac_family_analyst")
↓
alyac_family_agent executes BigQuery tools
↓
Result → bigquery_agent
↓
bigquery_agent summarizes and returns to user
When to use each:
| Scenario | Use bigquery_agent | Use conversational_agent |
|---|---|---|
| Direct SQL needed | ✅ | ❌ |
| Natural language query | ⚠️ Limited | ✅ |
| Web search required | ❌ | ✅ |
| Latest information | ❌ | ✅ |
| Template-based analysis | ✅ | ❌ |
| Exploratory data analysis | ⚠️ | ✅ |
File: adk-backend/src/adk_backend/agents/registry.py
AGENT_REGISTRY = {
"conversational": AgentInfo(
key="conversational",
display_name="대화형 데이터 분석가",
agent=conversational_analytics_agent,
focus="자연어 데이터 분석",
keywords=["자연어", "대화", "인사이트", "AI분석", ...],
),
"general": AgentInfo(
key="general",
display_name="범용 데이터 분석가",
agent=bigquery_agent,
focus="범용 데이터 분석",
keywords=[],
),
"alyac_family": AgentInfo(
key="alyac_family",
display_name="ALYac Family 보안 분석가",
agent=alyac_family_agent,
focus="악성 앱 및 피싱 분석",
keywords=["악성", "malware", "phishing", ...],
),
# ... security, marketing, conversion
}
def get_active_agents() -> List[AgentInfo]:
"""Returns all agents with active=True"""
return [info for info in AGENT_REGISTRY.values() if info.active]
# 1. Create domain expert agent
new_domain_agent = Agent(
name="new_domain_analyst",
description="Domain-specific analysis",
tools=[bigquery_list_templates, bigquery_render_template,
bigquery_dry_run, bigquery_execute],
# NO sub_agents (domain experts are leaf nodes)
)
# 2. Add to bigquery_agent sub_agents
bigquery_agent = Agent(
name="general_orchestrator",
sub_agents=[
alyac_family_agent,
security_agent,
marketing_agent,
conversion_agent,
new_domain_agent, # ✅ Add here
]
)
# 3. Register in registry
AGENT_REGISTRY["new_domain"] = AgentInfo(
key="new_domain",
agent=new_domain_agent,
keywords=["keyword1", "keyword2"],
)
# 4. Update agent_selector routing logic
from google.adk.plugins import ReflectAndRetryToolPlugin
class BigQueryErrorRecoveryPlugin(ReflectAndRetryToolPlugin):
"""Custom error detection for BigQuery warnings"""
async def extract_error_from_result(self, *, tool, tool_args,
tool_context, result):
if isinstance(result, dict):
# Detect warnings in successful responses
if result.get('warnings'):
return {
'error': 'BigQuery Warning',
'warnings': result['warnings'],
'suggestion': '경고를 해결하여 최적화된 쿼리를 생성하세요.'
}
return None # No error
# Apply to runner
runner = InMemoryRunner(
agent=agent,
plugins=[BigQueryErrorRecoveryPlugin(max_retries=3)]
)
User Query
↓
conversational_analytics_agent (orchestrator)
↓
transfer_to_agent("general_orchestrator")
↓
bigquery_agent (receives delegation)
↓
transfer_to_agent("alyac_family_analyst")
↓
alyac_family_agent (executes)
↓
Result → bigquery_agent → conversational_agent → User
Note: This creates deep nesting. Prefer direct delegation when possible.
# Check for multiple parent assignments
grep -r "sub_agents=\[.*alyac_family" adk-backend/src/adk_backend/agents/
# Should find ONLY in bigquery_agent.py
# Test keyword matching
echo '{"agent_type":"sql","message":"악성 앱 탐지"}' | \
python -c "from adk_backend.services.agent_selector import select_agent_for_request; \
import json, sys; \
data=json.load(sys.stdin); \
info, reason, _ = select_agent_for_request(
agent_type=data['agent_type'],
message=data['message'],
conversation_history=[]
); \
print(f'Selected: {info.key}, Reason: {reason}')"
# Manually trigger SQL error
cd adk-backend
python -c "
from src.adk_backend.tools.bigquery import bigquery_dry_run
try:
bigquery_dry_run('SELECT * FROM table WHERE time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 MONTH)')
except Exception as e:
print(f'Expected error: {e}')
"
Detailed information in reference/ folder:
Complete architecture documentation:
ADK Single Parent Rule explained:
Domain routing and agent selection:
SQL error recovery strategies:
Agent selection verification:
agent_selector.py)adk-backend/src/adk_backend/
├── agents/
│ ├── base/
│ │ ├── bigquery_agent.py (SQL orchestrator, has sub_agents)
│ │ └── conversational_analytics_agent.py (AI orchestrator, no sub_agents)
│ ├── alyac_family_domain_expert.py
│ ├── security_domain_expert.py
│ ├── marketing_domain_expert.py
│ ├── conversion_domain_expert.py
│ └── registry.py (AgentInfo registration)
├── services/
│ └── agent_selector.py (routing logic)
├── tools/
│ ├── bigquery.py (SQL tools)
│ └── conversational_analytics.py (AI analysis tools)
└── api/
└── chat.py (SSE streaming, ReflectAndRetryToolPlugin)
Need to handle agent request?
↓
Q: User mentioned specific domain keywords?
├─ YES → Route to domain expert agent
│ └─ Use agent_selector.py keyword matching
│
└─ NO → Default to conversational_analytics_agent
└─ Let AI decide delegation
Q: Agent architecture change needed?
↓
First check: Does it violate Single Parent Rule?
├─ YES → Redesign to use tools or indirect delegation
└─ NO → Proceed with implementation
Q: SQL errors occurring?
↓
Layer 1: Enhanced instructions (preventive)
├─ Success → Fast response
└─ Fail → Layer 2: ReflectAndRetryToolPlugin (reactive)
└─ Auto-retry with AI correction
ValidationError: already has a parent agent
reference/single_parent_rule.mdAgent not selected for domain keyword
agent_selector.py keyword patternsreference/agent_selection.mdTIMESTAMP_SUB MONTH error
reference/error_recovery.mdFrontend domain selection not working
reference/routing.mdagent_selector.py keywordsSkill Status: Production-ready ✅
Line Count: <500 (follows 500-line rule) ✅
Progressive Disclosure: Detailed docs in reference/ ✅
Last Updated: 2025-11-16
Related Commit: 35470b1 (BigQuery SQL error recovery with dual-layer strategy)
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience