System Overview
This system is a financial advisory system utilizing a multi-agent architecture. The main agent (Financial Advisor) coordinates three specialized sub-agents to provide comprehensive investment analysis.
Financial Advisor (Main Agent)
├── Data Analyst (Basic Data Collection)
├── Financial Analyst (Financial Statement Analysis)
├── News Analyst (News Search and Analysis)
└── save_advice_report (Save Final Report)
Real-world Example: AAPL Stock Analysis Request
Explaining the case where a user asks, "Give me investment advice for AAPL stock."
Detailed Step-by-Step Process
Step 1: Receiving User Request and Initial LLM Call
User Input
"Give me investment advice for AAPL stock"
Main Agent LLM Call #1
Call Location: financial_advisor agent in financial_advisor/agent.py LLM Model: openai/gpt-4o (Call via LiteLlm) Request Sent from Google ADK → OpenAI GPT-4o API:
{
"model": "openai/gpt-4o",
"messages": [
{
"role": "system",
"content": "You are a Professional Financial Advisor... [Entire content of PROMPT from prompt.py]"
},
{
"role": "user",
"content": "Give me investment advice for AAPL stock"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "data_analyst",
"description": "Gathers and analyzes basic stock market data..."
}
},
{
"type": "function",
"function": {
"name": "financial_analyst",
"description": "Analyzes detailed financial statements..."
}
},
{
"type": "function",
"function": {
"name": "news_analyst",
"description": "Uses Web Search tools to search and scrape real web content..."
}
},
{
"type": "function",
"function": {
"name": "save_advice_report",
"description": "Save comprehensive reports as artifacts..."
}
}
]
}
Generator: Google ADK (Main Agent System) Receiver: OpenAI GPT-4o API
Role and Impact of this JSON: This JSON serves as the Entry Point of the system, passing the user request to the LLM for the first time.
Role in the Overall Process:
- Context Setting: Provides the LLM with the Financial Advisor role and behavioral guidelines (prompt).
- Tool List Provision: Introduces the 4 tools available to the LLM (3 Sub-agents + save_advice_report).
- User Intent Delivery: Conveys the actual user request ("Give me investment advice for AAPL stock").
What happens via this JSON:
- OpenAI GPT-4o API receives this request and passes it to the LLM model.
- The LLM reads the prompt to understand the Financial Advisor role.
- The LLM analyzes the user request and reviews the available tools.
- The LLM secures all information needed to decide the next step (which tool to call).
Impact:
- Directly influences the LLM's next decision (which sub-agent to call).
- The content of the prompt determines the LLM's behavior pattern.
- Tools not in the list cannot be used by the LLM (provides constraints).
Confusing Parts:
- The tools array does not show parameter schemas here because Google ADK handles sub-agents internally.
- system.content actually contains the entire 55 lines from prompt.py, but is abbreviated in the documentation for readability.
Response received by Google ADK from OpenAI GPT-4o API:
{
"tool_calls": [
{
"id": "call_123",
"type": "function",
"function": {
"name": "data_analyst",
"arguments": "{\"ticker\": \"AAPL\"}"
}
}
],
"finish_reason": "tool_calls"
}
Generator: OpenAI GPT-4o LLM Receiver: Google ADK (Main Agent System)
Role and Impact of this JSON: This JSON is the result of the LLM's decision-making after analyzing the initial request.
Role in the Overall Process:
- Decision Result: Expresses the LLM's decision to "call the data_analyst first."
- Next Step Trigger: When Google ADK receives this response, it initiates the execution of the data_analyst sub-agent.
- Chain Start Point: Signal to start the first step of the entire multi-agent process.
What happens via this JSON:
- Google ADK parses the tool_calls array to recognize the need to call data_analyst.
- Google ADK extracts the ticker: "AAPL" parameter from arguments.
- Google ADK executes the Data Analyst sub-agent, passing ticker="AAPL".
- The Data Analyst sub-agent begins its task.
Impact:
- Process Branching Point: At this point, the flow of the main agent branches into the Data Analyst sub-agent.
- Sequential Execution Decision: The LLM decided to execute sequentially rather than calling multiple tools at once (influenced by "ANALYSIS METHODOLOGY" in the prompt).
- Context Transfer: "AAPL" from the user input is passed to the sub-agent, clarifying the analysis target.
Confusing Parts:
- finish_reason: "tool_calls" means the LLM finished responding with a tool call instead of generating text.
- The reason arguments is in JSON string format ("{\"ticker\": \"AAPL\"}") is that it is the standard format for OpenAI API.
- Why call only data_analyst? → Because the LLM read the prompt and selected a sequential approach.
Detailed Explanation of the arguments Field Generation Process: arguments: "{\"ticker\": \"AAPL\"}" was automatically generated by the LLM. The process is as follows:
- Google ADK passes sub-agent information to the LLM:
- When registering AgentTool(agent=data_analyst) as a tool, Google ADK passes the data_analyst agent's description and name to the LLM.
- In code: data_analyst = LlmAgent(name="DataAnalyst", description="Gathers and analyzes basic stock market data...")
- LLM analyzes User Input:
- User Input: "Give me investment advice for AAPL stock"
- The LLM recognizes "AAPL" as a stock ticker symbol.
- LLM selects tool and generates parameters:
- The LLM reads "ANALYSIS METHODOLOGY" in the prompt and determines that data must be gathered first.
- It understands that the data_analyst tool collects stock data.
- It extracts "AAPL" from the user input to use as the ticker parameter.
- Google ADK automatically infers standard parameters like ticker or identifies necessary parameters based on the agent's description when calling sub-agents.
- LLM generates arguments in JSON format:
- The LLM generates the parameters required for the function call in a JSON string format.
- ticker is recognized as a standard parameter meaning stock ticker symbol.
-
JSON
"arguments": "{\"ticker\": \"AAPL\"}"
Summary: arguments are not explicitly stated in the prompt but are automatically generated by the LLM by analyzing user input, referencing the description of available tools, and extracting necessary parameter values.
Interpretation:
- LLM reads the prompt and understands the analysis process.
- Based on "ANALYSIS METHODOLOGY" in the PROMPT, it decides to collect basic data first.
- It extracts "AAPL" from the user input to use as the ticker parameter.
- Decides to call data_analyst sub-agent and generates arguments.
Step 2: Executing Data Analyst Sub-agent
2-1. Data Analyst Agent Initialization and LLM Call #2
Call Location: data_analyst agent in financial_advisor/sub_agents/data_analyst.py Request Sent from Google ADK → OpenAI GPT-4o API:
{
"model": "openai/gpt-4o",
"messages": [
{
"role": "system",
"content": "You are a Data Analyst who gathers stock information using 4 specialized tools:\n\n1. **get_company_info(ticker)** - Learn about the company...\n2. **get_stock_price(ticker, period)** - Get current pricing...\n3. **get_financial_metrics(ticker)** - Check key financial ratios..."
},
{
"role": "user",
"content": "Analyze ticker: AAPL"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_company_info",
"description": "Retrieves basic company information for a given stock ticker..."
}
},
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Fetches historical stock price data..."
}
},
{
"type": "function",
"function": {
"name": "get_financial_metrics",
"description": "Retrieves key financial metrics and valuation ratios..."
}
}
]
}
Generator: Google ADK (Data Analyst Sub-agent System) Receiver: OpenAI GPT-4o API
Role and Impact of this JSON: This JSON is the request where the Data Analyst sub-agent calls its own dedicated LLM upon initial activation.
Role in the Overall Process:
- Sub-agent Activation: The Data Analyst starts working independently after receiving delegation from the Main Agent.
- Specialization: Provides only the Data Analyst-specific prompt and tools, ensuring focus solely on data collection.
- Domain Separation: Unlike the Main Agent's complex prompt, this provides simple and clear data collection instructions.
What happens via this JSON:
- The Data Analyst-dedicated LLM instance is activated (separate from the Main Agent).
- The LLM understands the Data Analyst role and grasps the functions of the 3 tools.
- The LLM receives the task instruction "Analyze AAPL".
- The LLM is ready to decide the next step (which tool to call).
Impact:
- Expertise: The Main Agent doesn't need to do everything; it delegates to an agent specialized in data collection.
- Work Distribution: Reduces the burden on the Main Agent, allowing each sub-agent to focus on its area of expertise.
- Scalability: Adding new data collection tools only requires modifying this agent.
Confusing Parts:
- user.content: "Analyze ticker: AAPL" is the natural language conversion of the ticker: "AAPL" parameter passed by the Main Agent.
- system.content is the content specified in the instruction parameter when defining the data_analyst agent (different from the Main Agent's prompt).
- description in the tools array is automatically parsed from the Python function's docstring.
Response received by Google ADK from OpenAI GPT-4o API (LLM Response #2):
{
"tool_calls": [
{
"id": "call_456",
"type": "function",
"function": {
"name": "get_company_info",
"arguments": "{\"ticker\": \"AAPL\"}"
}
},
{
"id": "call_457",
"type": "function",
"function": {
"name": "get_stock_price",
"arguments": "{\"ticker\": \"AAPL\", \"period\": \"1y\"}"
}
},
{
"id": "call_458",
"type": "function",
"function": {
"name": "get_financial_metrics",
"arguments": "{\"ticker\": \"AAPL\"}"
}
}
]
}
Generator: OpenAI GPT-4o LLM (for Data Analyst Agent) Receiver: Google ADK (Data Analyst Sub-agent System)
Role and Impact of this JSON: This JSON is the result of the Data Analyst LLM deciding to collect all 3 required data points.
Role in the Overall Process:
- Tool Call Decision: The LLM determines that company_info, stock_price, and financial_metrics are all needed.
- Parallel Execution Instruction: Calls multiple tools at once for efficient data collection.
- Parameter Decision: Determines parameter values to pass to each tool (ticker: "AAPL", period: "1y", etc.).
What happens via this JSON:
- Google ADK parses the tool_calls array and recognizes 3 tool calls.
- Google ADK executes each tool in parallel (improving efficiency).
- Each Python function (get_company_info, get_stock_price, get_financial_metrics) calls the Yahoo Finance API.
- Actual data is collected and returned to Google ADK.
Impact:
- Efficiency: Parallel calls reduce time compared to sequential calls.
- Data Completeness: The LLM decides to collect all necessary data at once, preventing incomplete analysis.
- Parameter Optimization: The LLM selecting period: "1y" indicates it judged this as an appropriate period for analysis.
Confusing Parts:
- Why call 3 at the same time? → Because the LLM judged that all 3 pieces of information are needed (influenced by instruction).
- How was period: "1y" decided? → The LLM looked at the function docstring explanation ("1y: 1 year") and judged it suitable for general analysis.
- Is sequential calling possible? → Yes, but in this case, the LLM judged parallel calling to be more efficient.
Interpretation:
- Data Analyst LLM decided to call 3 tools simultaneously (parallel execution).
- Each tool is executed as an actual Python function.
2-2. Actual Tool Function Execution (No LLM Call, Direct Execution)
Function Execution 1: get_company_info("AAPL")
# Actual API call using yfinance library
stock = yf.Ticker("AAPL")
info = stock.info # Yahoo Finance API call occurs
# Return Value (Python Function → Returned to Google ADK)
{
"ticker": "AAPL",
"success": True,
"company_name": "Apple Inc.",
"industry": "Consumer Electronics",
"sector": "Technology"
}
Generator: Python function get_company_info (Receiving data from Yahoo Finance API) Receiver: Google ADK (Data Analyst Sub-agent System)
Function Execution 2: get_stock_price("AAPL", "1y")
stock = yf.Ticker("AAPL")
history = stock.history(period="1y") # Requesting 1 year of price data
# Return Value (Python Function → Returned to Google ADK)
{
"ticker": "AAPL",
"success": True,
"history": "{\"Open\": {...}, \"High\": {...}, \"Low\": {...}, \"Close\": {...}, \"Volume\": {...}}",
"current_price": 175.43
}
Generator: Python function get_stock_price (Receiving data from Yahoo Finance API) Receiver: Google ADK (Data Analyst Sub-agent System)
Function Execution 3: get_financial_metrics("AAPL")
stock = yf.Ticker("AAPL")
info = stock.info
# Return Value (Python Function → Returned to Google ADK)
{
"ticker": "AAPL",
"success": True,
"market_cap": 2700000000000, # 2.7 Trillion USD
"pe_ratio": 28.5,
"dividend_yield": 0.0052, # 0.52%
"beta": 1.23
}
Generator: Python function get_financial_metrics (Receiving data from Yahoo Finance API) Receiver: Google ADK (Data Analyst Sub-agent System)
2-3. Data Analyst LLM Call #3 (Result Analysis)
Request Sent from Google ADK → OpenAI GPT-4o API (Previous conversation + Tool execution results):
{
"messages": [
{
"role": "system",
"content": "You are a Data Analyst..."
},
{
"role": "user",
"content": "Analyze ticker: AAPL"
},
{
"role": "assistant",
"content": null,
"tool_calls": [...]
},
{
"role": "tool",
"content": "{\"ticker\": \"AAPL\", \"success\": true, \"company_name\": \"Apple Inc.\", ...}"
},
{
"role": "tool",
"content": "{\"ticker\": \"AAPL\", \"success\": true, \"history\": \"{...}\", \"current_price\": 175.43}"
},
{
"role": "tool",
"content": "{\"ticker\": \"AAPL\", \"success\": true, \"market_cap\": 2700000000000, ...}"
}
]
}
Generator: Google ADK (Data Analyst Sub-agent System - Includes previous chat history and tool execution results) Receiver: OpenAI GPT-4o API
Role and Impact of this JSON: This JSON is a request for the Data Analyst to analyze the collected raw data and convert it into meaningful text.
Role in the Overall Process:
- Maintaining Conversation History: Includes previous requests (user) and responses (assistant's tool_calls) so the LLM understands context.
- Data Delivery: Provides the LLM with the actual data (JSON) collected from the 3 tools.
- Analysis Task Instruction: Requests the LLM to "analyze this data and convert it into text the user can understand."
What happens via this JSON:
- The LLM checks the tools it previously called (tool_calls) and their results (tool messages).
- The LLM comprehensively analyzes the collected data (company info, stock price, financial metrics).
- The LLM interprets the raw data and generates structured analysis text.
- The generated text is returned to Google ADK and automatically saved to the state based on the output_key setting.
Impact:
- Data → Insight Conversion: Converts raw JSON data into a human-readable analysis report.
- State Storage: The analysis result is saved in state["data_analyst_result"], making it available for the Main Agent later.
- Process Progression: The Data Analyst's task is complete, allowing the Main Agent to proceed to the next step (calling Financial Analyst).
Confusing Parts:
- The role: "tool" message is the way tool function return values are passed to the LLM (OpenAI API standard format).
- Reason content is a JSON string: The dictionary returned by the tool function is serialized into JSON.
- Why call the LLM again? → Raw data has no meaning on its own; the LLM must interpret it to derive insights.
Response received by Google ADK from OpenAI GPT-4o API (LLM Response #3 - Final Analysis Text):
"**Company Overview:**
Apple Inc. is a technology company in the Consumer Electronics industry...
**Current Pricing:**
Current price: $175.43
Market Cap: $2.7 trillion
P/E Ratio: 28.5 (indicating premium valuation)
1-year price range: $164.08 - $198.23
**Financial Metrics:**
Dividend Yield: 0.52% (moderate income component)
Beta: 1.23 (slightly more volatile than market)"
Generator: OpenAI GPT-4o LLM (for Data Analyst Agent) Receiver: Google ADK State Storage: Google ADK automatically saves to state["data_analyst_result"] according to output_key="data_analyst_result" setting
Role and Impact of this JSON (Text Response): This text is the final output of the Data Analyst sub-agent, the result of analyzing the raw data.
Role in the Overall Process:
- Analysis Result Output: Generates structured analysis text by interpreting collected data.
- State Storage: Automatically saved to state according to output_key setting, making it usable by other agents.
- Task Completion Signal: The Data Analyst's task is complete, and control is returned to the Main Agent.
What happens via this text:
- Google ADK receives this text and checks the output_key="data_analyst_result" setting.
- Google ADK automatically saves state["data_analyst_result"] = "Text Content".
- The Data Analyst sub-agent's task is finished.
- The Main Agent sees this result and decides the next step (calling Financial Analyst).
Impact:
- Data Sharing: Saved in state so the Main Agent and other functions (save_advice_report) can access it.
- Process Chain: The Main Agent looks at this result to decide whether to call the next sub-agent.
- Final Report Composition: Later, the save_advice_report function will include this text to create the comprehensive report.
Confusing Parts:
- Why is it in text format? → LLM output is always text, and state can only store strings.
- Why is it automatically saved to State? → Because the output_key parameter is set (Code: data_analyst = LlmAgent(..., output_key="data_analyst_result")).
- How is this text passed to the Main Agent? → Indirectly via State (The Main Agent reads from the state).
Step 5: Main Agent's Final Analysis and Advice
5-1. Main Agent LLM Call #10 (Comprehensive Analysis)
Request Sent from Google ADK → OpenAI GPT-4o API:
{
"messages": [
{
"role": "system",
"content": "[PROMPT content - including asking for user preferences]"
},
{
"role": "user",
"content": "Give me investment advice for AAPL stock"
},
{
"role": "assistant",
"content": null,
"tool_calls": [{"name": "data_analyst", ...}]
},
{
"role": "tool",
"content": "[data_analyst result]"
},
{
"role": "assistant",
"content": null,
"tool_calls": [{"name": "financial_analyst", ...}]
},
{
"role": "tool",
"content": "[financial_analyst result]"
},
{
"role": "assistant",
"content": null,
"tool_calls": [{"name": "news_analyst", ...}]
},
{
"role": "tool",
"content": "[news_analyst result]"
}
]
}
Generator: Google ADK (Main Agent System - Includes results from all sub-agents) Receiver: OpenAI GPT-4o API
Role and Impact of this JSON: This JSON represents the stage where the Main Agent synthesizes the analysis results from all sub-agents before generating the final advice.
Role in the Overall Process:
- Conversation History Accumulation: Full conversation record from user request to all sub-agent calls and results.
- Context Integration: Enables comprehensive judgment by including results from Data Analyst, Financial Analyst, and News Analyst.
- Preparation for Final Decision: Preparation to generate advice tailored to the user based on all analysis data.
What happens via this JSON:
- The LLM reviews the entire conversation history to understand the situation.
- The LLM checks the analysis results of all 3 sub-agents.
- The LLM checks "INVESTMENT RECOMMENDATION PROCESS" in the prompt.
- The LLM determines that user preferences (investment goal, risk tolerance, time horizon) are needed.
- The LLM generates text to ask the user.
Impact:
- Tailored Advice: By asking for user preferences first, personalized investment advice can be provided.
- Process Delay: The process is paused as it must wait for the user's additional response.
- Conversational Interaction: Provides a personalized service through dialogue rather than simple one-way advice.
Confusing Parts:
- [data_analyst result] in the role: "tool" message is the return value of the sub-agent call, not the value read from the state.
- Why ask the user at this point? → Because there is an instruction in the prompt: "Before providing any BUY/SELL/HOLD recommendation, you MUST: Ask about..."
- Reason for including all sub-agent results: The LLM needs all information to make a comprehensive judgment.
Response received by Google ADK from OpenAI GPT-4o API (LLM Response #10 - User Preference Question):
"Before providing investment advice, I need some information:
1. **Investment Goal**: Do you want growth investing, income investing, or short-term trading?
2. **Risk Tolerance**: Do you have a conservative, neutral, or aggressive investment preference?
3. **Time Horizon**: Short-term (under 1 year), Medium-term (1-3 years), or Long-term (over 3 years)?
If you provide this information, I will provide a tailored investment recommendation for AAPL."
Generator: OpenAI GPT-4o LLM (for Main Agent) Receiver: Google ADK → Displayed to User
5-2. User Response (Example)
"Investment Goal: Growth Investing
Risk Tolerance: Neutral
Time Horizon: Long-term (over 3 years)"
5-3. Main Agent LLM Call #11 (Final Advice Generation)
Request Sent from Google ADK → OpenAI GPT-4o API (Including User Response):
{
"messages": [
... (Entire previous conversation),
{
"role": "user",
"content": "Investment Goal: Growth Investing\nRisk Tolerance: Neutral\nTime Horizon: Long-term (over 3 years)"
}
]
}
Generator: Google ADK (Main Agent System - User response added) Receiver: OpenAI GPT-4o API
Role and Impact of this JSON: This JSON is the request to generate the final investment advice by adding the user's preference information.
Role in the Overall Process:
- User Input Addition: Adds the preference information provided by the user to the conversation history.
- Preparation for Comprehensive Judgment: Preparation to generate final advice based on all analysis data (sub-agent results) + user preferences.
- Process Completion Phase: Generating the final output with all information collected.
What happens via this JSON:
- The LLM checks the user's preference information (Growth, Neutral, Long-term).
- The LLM synthesizes the analysis results of the 3 sub-agents and the user preferences.
- The LLM decides BUY/SELL/HOLD according to "RECOMMENDATION REQUIREMENTS" in the prompt.
- The LLM generates specific advice text (including strengths, risk factors, target price, etc.).
Impact:
- Final Output Generation: The investment advice, the core purpose of the system, is completed.
- Tailored Result: Provides personalized advice tailored to the user's preferences.
- Process Completion: Major analysis tasks are completed, and the result is provided to the user.
Confusing Parts:
- ... (Entire previous conversation) actually includes hundreds of lines of conversation history (abbreviated here).
- Why is the entire previous conversation needed? → So the LLM can understand the context and generate a consistent response.
- Reason user response is added as role: "user": To maintain the continuity of the conversation.
Response received by Google ADK from OpenAI GPT-4o API (LLM Response #11 - Final Investment Advice):
"**AAPL (Apple Inc.) Investment Recommendation: BUY**
**Comprehensive Analysis Summary:**
**Strengths:**
- Strong Financial Health: Free Cash Flow $99.6B, Good Debt Ratio
- Stable Profitability: Operating Margin 30.2%, Net Income $97B
- Services Segment Growth: 15% YoY increase
- Premium Valuation: P/E 28.5 (Reflecting growth expectations)
**Risk Factors:**
- Exposure to the Chinese market
- Potential short-term volatility due to premium valuation
**Investment Recommendation (Neutral Risk, Long-term Growth):**
BUY - Target Price: $210 (12 months)
AAPL is suitable for long-term growth investment. Strong financial health and growth in the services sector are expected to continue."
Generator: OpenAI GPT-4o LLM (for Main Agent) Receiver: Google ADK → Displayed to User