Skip to content

Instantly share code, notes, and snippets.

@pavlovmilen
Created May 11, 2025 10:44
Show Gist options
  • Save pavlovmilen/d328c083c02e9dd90c17b92d9ad83f6c to your computer and use it in GitHub Desktop.
Save pavlovmilen/d328c083c02e9dd90c17b92d9ad83f6c to your computer and use it in GitHub Desktop.
complete_example.py
import os
import sys
from dotenv import load_dotenv
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.base import TaskResult
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.messages import BaseChatMessage
from autogen_agentchat.teams import SelectorGroupChat
from autogen_core import SingleThreadedAgentRuntime
from autogen_core.tools import FunctionTool
from autogen_ext.models.openai import AzureOpenAIChatCompletionClient
load_dotenv()
gpt_model_client = AzureOpenAIChatCompletionClient(
model="gpt-4.1-mini-2025-04-14",
api_version="2024-06-01",
azure_deployment="gpt-4.1-mini",
azure_endpoint=os.environ.get("AZURE_OPEN_AI_API_ENDPOINT_SWEDEN"),
#azure_ad_token_provider=token_provider, # Optional if you choose key-based authentication.
api_key=os.environ.get("AZURE_OPEN_AI_API_KEY_SWEDEN"),
)
notebook_dir = os.path.abspath('.')
app_dir = os.path.abspath(os.path.join(notebook_dir, '..'))
if app_dir not in sys.path:
sys.path.insert(0, app_dir)
from tools.valuation_modeling_tool import collect_valuation
from tools.tools import get_finance_data
from tools.fomc_files_service import download_fomc_summary
from tools.tools import get_finance_data
from tools.alpha_vantage_api import alpha_vantage_news_sentiment, fetch_company_data
from tools.file_upload_service import upload_ai_report
runtime = SingleThreadedAgentRuntime()
doji_tool = FunctionTool(get_finance_data, description="Download last 60 days of OHLCV data")
doji_agent = AssistantAgent(
name="doji_agent",
model_client=gpt_model_client,
description="Spot daily doji patterns",
system_message="""
You retrieve OHLCV data via doji_tool and detect doji candlesticks.
A daily bar is a doji when abs(Open – Close) ≤ 0.10 × (High – Low).
Steps: (1) call the tool, (2) run the test, (3) return a list of dates or an empty list if none.
Output strictly: comma-separated ISO dates. Provide explanations for the doji dates""",
tools=[doji_tool])
news_sentiment_data_tool= FunctionTool(alpha_vantage_news_sentiment, description="Searches for information from Alpha Vantage api about a stock.")
alpha_vantage_news_sentiment_agent = AssistantAgent(
name="alpha_vantage_news_sentiment_agent",
model_client=gpt_model_client,
description="Search for a news sentiment about a stock using the search tool",
system_message="You are a helpful assistant that can search and analyze news sentiment about a stock using alpha vantage api.",
tools=[news_sentiment_data_tool],
)
company_info_tool = FunctionTool(fetch_company_data, description="Retrieves stock data using the alpha vantage api.")
alpha_vantage_company_info_agent = AssistantAgent(
name="alpha_vantage_company_info_agent",
model_client=gpt_model_client,
description="Retrieve company data using the Alpha Vantage API",
system_message="You are a helpful assistant that can retrieve and analyze company data using alpha vantage api.",
tools=[company_info_tool],
)
fomc_summary_fetch_tool = FunctionTool(download_fomc_summary, description="Fetch FOMC file summary")
fomc_summary_fetch_agent = AssistantAgent(
name="fomc_summary_fetch_agent",
model_client=gpt_model_client,
description="Fetch FOMC file summary and analyze it for the current stock ticker",
system_message="You are a helpful assistant that can fetch and analyze FOMC file summary for the current stock ticker.",
tools=[fomc_summary_fetch_tool]
)
peer_valuation_modeling_tool = FunctionTool(collect_valuation, description="Get valuation model for a stock ticker")
peer_valuation_modeling_agent = AssistantAgent(
name="peer_valuation_modeling_agent",
model_client=gpt_model_client,
system_message="""
You are Valuation-Summariser-Bot.
Input → a ValuationBundle JSON (see keys below).
Goal → produce a concise, facts-only digest that can be dropped verbatim into the final equity report. No recommendations, no formatting beyond plain text bullets.
ValuationBundle keys you’ll receive
• symbol – target ticker
• multiples – list of dicts with ticker, PE, EV/EBITDA, P/Sales
• multiples_median – peer medians for those three ratios
• pre_dcf – {per_share, date} or null
• sensitivity – dict of WACC-terminal-g grid; access with sensitivity["Value"] once converted back to DataFrame if needed
Tasks (keep strictly to this order)
State the ticker and peer count.
For each ratio (P/E, EV/EBITDA, P/Sales) say whether the target is above, inline, or below its peer median and give the numeric difference in % (one decimal).
Quote the FMP simple DCF per-share value and its date, if available.
Pick the sensitivity table value at WACC = 9 % & terminal-g = 2 % (if that coordinate exists) and label it “central sensitivity” value.
End with one sentence describing overall valuation stance (e.g., “Shares trade at a notable premium across all multiples while the DCF central point implies modest upside.”).
Output format – plain text, exactly five bullet points (•), each ≤ 25 words. No extra lines, no JSON, no markdown.""",
description="Get peer valuation model for a given stock ticker",
tools=[peer_valuation_modeling_tool]
)
report_generator_agent = AssistantAgent(
name="report_agent",
model_client=gpt_model_client,
description="Generate an answer based the search and results all of the previous agents from the team",
system_message="""
You are **Equity-Report-Assembler**.
**Objectives**
1. Create a report for the ticker provided in all payloads.
2. Write in tight, professional prose; no marketing fluff.
3. Section order:
1) *Technical Snapshot Doji Patterns* summarise `doji_agent` also include the doji dates and the signal.
2) *News & Sentiment* summarise top 5 headlines and net bias.
3) *Fundamentals Company Snapshot* key numbers from `alpha_vantage_company_info_agent with detailed analysis.
4) *Macro Context* 3-sentence digest from `fomc_summary_fetch_agent`.
5) *Valuation Modeling*
• Compare target vs peer medians for P/E, EV/EBITDA, P/S (state % prem/discount).
• Quote FMP simple DCF per-share and its date.
• Give central-point value from sensitivity table (WACC = 9 %, g = 2 %).
• Provide analysis and explanation of the valuation model.
6) *Integrated View* comprehensive analysis of the stock; issue Buy/Hold/Sell, highlight upside or downside drivers.
4. Use plain Markdown headings (`###`) and short sentences.
5. Numerical formats: integers with commas, decimals with two digits.
6. Output **only** the finished Markdown report—no JSON, no metadata, no commentary.
7. If any of the agents fail to provide data, make sure its mentioned in the report.
""",
)
report_upload_tool = FunctionTool(upload_ai_report, description="Uploads summary provided by report agent to azure blob storage. Start with PlanningAgent to create an action plan first.")
report_upload_agent = AssistantAgent(
name="report_upload_agent",
model_client=gpt_model_client,
description="Upload the {ticker}_report file to azure blob storage",
tools=[report_upload_tool]
)
planning_agent = AssistantAgent(
"PlanningAgent",
description="An agent for planning tasks, this agent should be the first to engage when given a new task.",
model_client=gpt_model_client,
system_message="""
You are a planning agent.
Your job is to break down complex tasks into smaller, manageable subtasks.
Your team members are:
doji_agent: Identify doji patterns in stock data using doji_tool
alpha_vantage_news_sentiment_agent: Search for a news sentiment about a stock using the search tool
alpha_vantage_company_info_agent: Retrieve company data using the Alpha Vantage API
fomc_summary_fetch_agent: Fetch FOMC file summary and analyze it for the current stock ticker
valuation_modeling_agent: Get valuation model for a given stock ticker
report_agent: Generate report based on doji patterns, alpha vantage news sentiment, company data, valuation model and fomc summary.
report_upload_agent: Upload the report to azure blob storage using report_upload_tool.
You only plan and delegate tasks - you do not execute them yourself.
When assigning tasks, use this format:
1. <agent> : <task>
After all tasks are complete, summarize the findings. Only when all tasks are complete, complete the workflow by responding with "TERMINATE".
""",
)
text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_termination
selector_prompt = """Select an agent to perform task.
{roles}
Current conversation context:
{history}
Read the above conversation, then select an agent from {participants} to perform the next task.
Make sure the planner agent has assigned tasks before other agents start working.
Only select one agent at a time.
"""
market_reserarch_agents_team = SelectorGroupChat(
[planning_agent, doji_agent, alpha_vantage_news_sentiment_agent, alpha_vantage_company_info_agent, fomc_summary_fetch_agent, peer_valuation_modeling_agent, report_generator_agent, report_upload_agent],
termination_condition=termination,
allow_repeated_speaker=True,
model_client=gpt_model_client,
selector_prompt=selector_prompt)
runtime.start()
message_count = 0
total_prompt_tokens = 0
total_completion_tokens = 0
async for message in market_reserarch_agents_team.run_stream(task="Hello, I would like to know if a stock with ticker=MSFT is a good pick for me to invest in this year?"):
if isinstance(message, TaskResult):
print("Stop Reason:", message.stop_reason)
if isinstance(message, BaseChatMessage):
message_count += 1
print(f'.................Message {message_count}.....................')
print(f"\033[93m........ Source: {message.source}\033[0m")
print(f"\033[94m{message.content}\033[0m")
if hasattr(message, 'models_usage') and message.models_usage is not None:
prompt = getattr(message.models_usage, 'prompt_tokens', 0)
completion = getattr(message.models_usage, 'completion_tokens', 0)
total_prompt_tokens += prompt
total_completion_tokens += completion
print(f"\033[91mInput tokens so far: {total_prompt_tokens}\033[0m")
print(f"\033[92mOutput tokens so far: {total_completion_tokens}\033[0m")
print(f"\033[91mTotal input tokens: {total_prompt_tokens}\033[0m")
print(f"\033[92mTotal output tokens: {total_completion_tokens}\033[0m")
await market_reserarch_agents_team.reset()
await runtime.stop()
print(f"\033[91mPrice of input tokens: £{total_prompt_tokens * 0.30 / 1000000}\033[0m")
print(f"\033[92mPrice of output tokens: £{total_completion_tokens * 1.20 / 1000000}\033[0m")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment