| name | adk-debug |
| description | Diagnose và fix các vấn đề liên quan đến Google ADK agents, tools, session state, multi-agent communication trong dự án MemRAG. |
Khi được gọi với /adk-debug, thực hiện theo đúng quy trình sau:
Bước 1 — Xác định loại vấn đề
Hỏi user (hoặc đọc từ context) lỗi thuộc nhóm nào:
| Nhóm | Triệu chứng điển hình |
|---|
| A. Tool không được gọi | Agent trả lời không dùng data từ Qdrant/mem0 |
| B. Sub-agent không nhận đúng request | DocsAgent/MeetingAgent tìm sai thông tin |
| C. Session state bị mất | user_id undefined, memories không persist |
| D. 429 RESOURCE_EXHAUSTED | Gemini API rate limit |
| E. Context / summary sai | Summary mất thông tin, truncation không mong muốn |
| F. AgentTool trả về rỗng | Sub-agent chạy nhưng Root không nhận được kết quả |
Bước 2 — Diagnose theo nhóm
Nhóm A: Tool không được gọi
Kiểm tra:
async def search_documents(query: str, tool_context: ToolContext) -> dict:
agent.tools
Đọc log để xem tool có được trigger:
docker compose logs backend -f | grep "qdrant_search_done\|meeting_search_done\|memories_retrieved"
Nhóm B: Sub-agent không nhận đúng request
Nguyên nhân phổ biến: Root Agent formulate request quá chung chung.
Kiểm tra system prompt của Root Agent:
backend/app/core/llm_config.yaml → prompts.system_instruction
Root phải ghi rõ trong request: thông tin cần gì + mục đích để trả lời câu hỏi gì.
Kiểm tra AgentTool được khai báo đúng:
AgentTool(agent=get_docs_agent(), skip_summarization=True)
Nhóm C: Session state bị mất
AgentTool copy state từ parent sang sub-agent (confirmed từ ADK source):
state_dict = {k: v for k, v in tool_context.state.to_dict().items()
if not k.startswith('_adk')}
Kiểm tra user_id có trong session state khi session được tạo:
state={"user_id": user_id, "max_context_messages": max_context_messages}
Nếu tool không đọc được user_id:
user_id = tool_context.state.get("user_id")
user_id = tool_context.state.get("user_id", "default_user")
Nhóm D: 429 RESOURCE_EXHAUSTED
Kiểm tra config:
Model names hợp lệ (cập nhật 2026-04):
llm:
model: "gemini-2.5-flash"
retrieval_model: "gemini-2.0-flash"
summary_model: "gemini-2.0-flash"
Retry được implement tự động trong gemini_utils._with_retry():
- Max 3 attempts, exponential backoff 1s/2s/4s + jitter
Nhóm E: Context / summary sai
Kiểm tra các thresholds:
max_context_messages: int = 20
summary_threshold: int = 22
summary_keep_recent: int = 10
Background summarization (lần re-summary):
- Lần đầu chưa có summary → blocking (phải chờ)
- Lần sau đã có summary → fire-and-forget (không block LLM)
Kiểm tra summary được lưu đúng:
callback_context.state["conversation_summary"]
callback_context.state["summary_covered_count"]
Nhóm F: AgentTool trả về rỗng
Từ source code ADK agent_tool.py:266-275:
if last_content is None or last_content.parts is None:
return ''
merged_text = '\n'.join(p.text for p in last_content.parts
if p.text and not p.thought)
Nguyên nhân thường gặp:
- Sub-agent chỉ gọi tool nhưng không generate text response cuối
- Sub-agent raise exception → bị catch và trả
''
skip_summarization=False → ADK overwrite content với summary rỗng
Fix: đảm bảo sub-agent instruction yêu cầu nó luôn trả lời bằng text sau khi dùng tool.
Bước 3 — Kiểm tra nhanh toàn bộ agent stack
cd /home/minhdd/pet_proj/proj2/backend
uv run python -c "
from app.agents.root_agent import get_root_agent
agent = get_root_agent()
tools = [(t.__class__.__name__, getattr(t, 'agent', None) and t.agent.name or getattr(t, '__name__', '?')) for t in agent.tools]
print('Root tools:', tools)
print('Root model:', agent.model)
from app.agents.docs_agent import get_docs_agent
da = get_docs_agent()
print('DocsAgent model:', da.model)
print('DocsAgent tools:', [t.__name__ for t in da.tools])
from app.agents.meeting_agent import get_meeting_agent
ma = get_meeting_agent()
print('MeetingAgent model:', ma.model)
print('MeetingAgent tools:', [t.__name__ for t in ma.tools])
"
uv run pytest tests/ -v --tb=short
uv run ruff check .
Bước 4 — Files quan trọng cần đọc khi debug
| Vấn đề | File |
|---|
| Agent tools, model config | backend/app/core/llm_config.yaml |
| Agent prompts (system, docs, meeting) | backend/app/core/llm_config.yaml |
| Root / Docs / Meeting agent setup | backend/app/agents/{root,docs,meeting}_agent.py |
| Context filter & summarization | backend/app/agents/plugins/context_filter_plugin.py |
| Qdrant search tool | backend/app/agents/tools/qdrant_search_tool.py |
| Meeting search tool | backend/app/agents/tools/meeting_search_tool.py |
| Memory tools | backend/app/agents/tools/mem0_tools.py |
| Gemini utils + retry | backend/app/utils/gemini_utils.py |
| Session state setup | backend/app/services/chat_service.py → _ensure_session() |
ADK Gotchas quan trọng (từ source code)
-
AgentTool tạo InMemorySessionService mới cho mỗi invocation — sub-agent sessions là ephemeral, KHÔNG lưu DynamoDB.
-
State sharing: Parent state được copy sang sub-agent. State delta từ sub-agent được propagate ngược về parent.
-
skip_summarization=True là bắt buộc — nếu False, ADK tự summarize output sub-agent trước khi trả Root, có thể mất chi tiết.
-
Một agent chỉ có thể là sub_agents của một parent — nhưng AgentTool là pattern khác, không có giới hạn này.
-
Model deprecated: gemini-2.0-flash-lite → 404. Dùng gemini-2.0-flash.