<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Apoorv Gupta</title>
    <description>The latest articles on DEV Community by Apoorv Gupta (@apoorv_gupta_a6a859429e14).</description>
    <link>https://dev.to/apoorv_gupta_a6a859429e14</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1732714%2F52b163af-a407-48c6-b65f-f016e3e689d7.jpg</url>
      <title>DEV Community: Apoorv Gupta</title>
      <link>https://dev.to/apoorv_gupta_a6a859429e14</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/apoorv_gupta_a6a859429e14"/>
    <language>en</language>
    <item>
      <title>Captain Cool: How I Built a Multi-Agent IPL Strategist with Gemini in 3 Hours</title>
      <dc:creator>Apoorv Gupta</dc:creator>
      <pubDate>Sun, 17 May 2026 12:38:41 +0000</pubDate>
      <link>https://dev.to/apoorv_gupta_a6a859429e14/captain-cool-how-i-built-a-multi-agent-ipl-strategist-with-gemini-in-3-hours-4egc</link>
      <guid>https://dev.to/apoorv_gupta_a6a859429e14/captain-cool-how-i-built-a-multi-agent-ipl-strategist-with-gemini-in-3-hours-4egc</guid>
      <description>&lt;p&gt;Cricket is a captain's game. Every over, someone has to make a call — who bowls, who bats next, when to take the timeout, when to play the Impact Player. These decisions live in the gap between data and instinct.&lt;/p&gt;

&lt;p&gt;I wanted to build an AI that operates in that gap — not just analysing the match, but &lt;em&gt;arguing about it&lt;/em&gt;. An AI that proposes a call, gets challenged on it, defends or revises, and then explains the whole debate in cricket language any fan can understand.&lt;/p&gt;

&lt;p&gt;This is Captain Cool. Here's how I built it at the Agentic Premier League in Pune, powered by Google Gemini.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Most "AI" Sports Tools
&lt;/h2&gt;

&lt;p&gt;Before I built anything, I looked at what other people had built at similar events. The pattern was consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A polished UI&lt;/li&gt;
&lt;li&gt;Hardcoded or mock data&lt;/li&gt;
&lt;li&gt;A README full of words like "AI-powered", "neural analytics", "predictive intelligence"&lt;/li&gt;
&lt;li&gt;Zero actual Gemini API calls in the codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ones that &lt;em&gt;did&lt;/em&gt; use Gemini made a single API call and formatted the response into multiple labelled sections — calling it "multi-agent" when it was really just one prompt with four JSON fields.&lt;/p&gt;

&lt;p&gt;I wanted to build something where you could open the code and see four distinct agents, each making their own Gemini call, each with their own system prompt, each contributing something the others can't.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture: The Debate Pipeline
&lt;/h2&gt;

&lt;p&gt;The system runs a 5-step sequential pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stats Analyst (with function calling)
    ↓ statistical report
Strategist (proposes tactical call)
    ↓ proposal
Devil's Advocate (challenges the proposal)
    ↓ challenge
Strategist (defends or revises)
    ↓ final decision
Commentator (translates to cricket talk)
    ↓ broadcast commentary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step is a separate Gemini call. Each agent has its own system prompt. The Strategist runs &lt;em&gt;twice&lt;/em&gt; — once to propose and once to revise after the challenge.&lt;/p&gt;

&lt;p&gt;The entire pipeline streams to the frontend via Server-Sent Events, so you watch the debate unfold in real time, agent by agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agent 1: Stats Analyst — Real Function Calling
&lt;/h2&gt;

&lt;p&gt;The Stats Analyst is the only agent with tool access. This is where the genuine agentic behavior lives.&lt;/p&gt;

&lt;p&gt;I defined four tool functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_player_stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stat_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get batting or bowling stats for a player in powerplay/middle/death&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_matchup_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bowler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get head-to-head stats between a specific batter and bowler&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_win_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batting_team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wickets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;innings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate win probability with momentum indicator&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_venue_conditions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;venue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get pitch conditions, avg scores, altitude/dew effects&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I passed these to Gemini as native tools — not as injected text in the prompt. Gemini sees the function signatures, decides which ones to call, calls them with appropriate arguments, receives the results, and synthesizes a statistical report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerativeModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ALL_TOOLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function-calling loop runs until Gemini stops requesting tools — typically 4-7 calls per analysis. Every call is logged so you can watch Gemini's reasoning chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CALL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;get_player_stats('Priyansh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Arya',&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'batting',&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'powerplay')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"sr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;226.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"avg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;36.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"vs_pace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;218.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CALL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;get_matchup_data('Priyansh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Arya',&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Bhuvneshwar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Kumar')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"balls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"runs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dismissals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;66.7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CALL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;calculate_win_probability('PBKS',&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;209&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;TOOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"batting_win_prob"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;31.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"required_run_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.44&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;System Prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are the Stats Analyst for an IPL team's think tank. Your role is 
to process match data and provide ONLY statistical analysis — no opinions, 
no recommendations.

You have access to tools. USE THEM before answering. Do not guess statistics.
Call multiple tools to build a comprehensive picture.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Agent 2: Strategist — The Captain's Call
&lt;/h2&gt;

&lt;p&gt;The Strategist uses &lt;code&gt;gemini-2.5-pro&lt;/code&gt; — the most powerful Gemini model — because the tactical call is the highest-stakes output in the system.&lt;/p&gt;

&lt;p&gt;It receives the stats report and proposes one specific decision in a structured format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DECISION: [One clear sentence]
REASONING: [2-3 sentences in cricket language, not ML jargon]
CONFIDENCE: [High/Medium/Low] — [one-line justification]
RISK: [What could go wrong — specific player and scenario]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structured format was deliberate. It forces the model to commit to one call and own the risk, rather than hedging with "it depends."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are the Captain. Think step by step:
1. What phase is the match in?
2. What does the data say about available options?
3. What is the highest-leverage decision right now?

Your decision must cover exactly ONE of:
- Who bowls the next over
- Batting order change
- Field placement shift
- Strategic timeout timing
- Impact Player deployment

Be bold. A captain who hedges every call loses matches.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Agent 3: Devil's Advocate — The Contrarian
&lt;/h2&gt;

&lt;p&gt;This is the innovation that makes Captain Cool different from everything else at the event.&lt;/p&gt;

&lt;p&gt;Most AI systems give you one answer. Captain Cool shows you the argument &lt;em&gt;against&lt;/em&gt; that answer.&lt;/p&gt;

&lt;p&gt;The Devil's Advocate receives the Strategist's proposal and must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the biggest assumption the Strategist made&lt;/li&gt;
&lt;li&gt;Present a specific counter-scenario where the decision fails (with player names and stats)&lt;/li&gt;
&lt;li&gt;Suggest a concrete alternative&lt;/li&gt;
&lt;li&gt;Deliver a verdict: AGREE / DISAGREE / CONDITIONAL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;System Prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are the Devil's Advocate in the IPL captain's think tank.
Your ONLY job is to challenge the Strategist's proposal.

You are not contrarian for fun. You genuinely find where this decision fails.
Think like a batting coach who knows exactly how the opposition exploits this.

CHALLENGE: [Core weakness — specific, with stats]
COUNTER-SCENARIO: [Specific failure mode — over, player, numbers]
ALTERNATIVE: [Different decision + why it's better]
VERDICT: [AGREE / DISAGREE / CONDITIONAL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Agent 4: Commentator — Cricket for Everyone
&lt;/h2&gt;

&lt;p&gt;The Commentator receives the full debate — all four prior outputs — and translates everything into 4-5 sentences of broadcast-style commentary.&lt;/p&gt;

&lt;p&gt;No ML jargon. No bullet points. Just cricket talk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a cricket commentator in the style of Harsha Bhogle.

Rules:
- Write in present tense, as if commentating live
- Reference specific players by name
- Include the why-this-not-that explanation
- Sound like an IPL broadcast, not an academic paper
- End with one sentence about what to watch for next
- Under 100 words, pure flowing prose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Orchestrator — Wiring It Together
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;orchestrator.py&lt;/code&gt; runs the pipeline sequentially, yielding SSE events at each step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_debate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MatchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsyncGenerator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="c1"&gt;# Step 1
&lt;/span&gt;    &lt;span class="n"&gt;stats_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stats_analyst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_sse_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stats_analyst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 2
&lt;/span&gt;    &lt;span class="n"&gt;proposal_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strategist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;propose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stats_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_sse_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 3
&lt;/span&gt;    &lt;span class="n"&gt;challenge_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;devils_advocate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_sse_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;devils_advocate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 4 — Strategist reviews and revises
&lt;/span&gt;    &lt;span class="n"&gt;revision_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strategist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revise&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_sse_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 5
&lt;/span&gt;    &lt;span class="n"&gt;commentary_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commentator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;narrate&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_sse_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;commentator&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend subscribes to the SSE stream and renders each agent's output as it arrives — color-coded, labeled, and displayed sequentially.&lt;/p&gt;




&lt;h2&gt;
  
  
  Live Demo: PBKS vs RCB, Dharamsala
&lt;/h2&gt;

&lt;p&gt;Here's what the system produced for today's real match:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; PBKS chasing 209, 0/0 in 0.0 overs. Bhuvneshwar Kumar to open the bowling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stats Analyst output&lt;/strong&gt; (after 5 tool calls):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Priyansh Arya SR 226.5 overall — but drops to 66.7 vs Bhuvneshwar with 2 dismissals in just 12 balls. Bhuvneshwar leads IPL 2026 wicket charts at 22 wickets, economy 7.46. HPCA Dharamsala altitude amplifies his swing. PBKS win probability: 31% at required RRR of 10.44.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Strategist proposal:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DECISION: Promote Shreyas Iyer to No. 3 — ready to walk in on first powerplay wicket.&lt;br&gt;
REASONING: Iyer averages 54.7 at SR 163 this season. The Arya-Bhuvi matchup (SR 66.7, 2 dismissals) makes an early wicket almost certain. PBKS need consolidation followed by acceleration.&lt;br&gt;
CONFIDENCE: High — matchup data and Bhuvi's form both point this way.&lt;br&gt;
RISK: Kills scoring rate if Arya survives. Iyer coming in cold vs Hazlewood at altitude.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Devil's Advocate challenge:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CHALLENGE: Iyer at 3 kills the aggression PBKS need at 10.44 RRR.&lt;br&gt;
COUNTER-SCENARIO: Stoinis as Impact Player provides left-arm option vs right-arm Bhuvi — disrupts the angle immediately.&lt;br&gt;
ALTERNATIVE: Stoinis at 3 on early wicket, not Iyer. Left-right combination.&lt;br&gt;
VERDICT: CONDITIONAL — Iyer at 3 works only if wicket falls after over 5.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Strategist revision:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;VERDICT: REVISE. Stoinis as Impact Player at 3 preserves the left-right combination. Iyer holds at 4. The Devil's Advocate correctly identified the left-hander gap.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Commentator:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The think tank goes for Stoinis as the impact card — left-hander at three to counter Bhuvneshwar's angle. They looked at Iyer, but with a run rate needing to touch double digits from ball one, this isn't a day for safety first. Watch for the Stoinis signal from the dugout early — if Punjab's openers go inside five, the whole innings shape changes."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prompt structure matters more than model size.&lt;/strong&gt; The Devil's Advocate prompt was the hardest to write — making it genuinely contrarian without being destructively negative took four iterations. The final version uses the framing "think like a batting coach who knows exactly how the opposition exploits this" which produced the best challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSE streaming is the right output format for agent systems.&lt;/strong&gt; Showing each agent's output as it generates — rather than waiting for all five — made the system feel alive in a way a JSON dump never could. The judges watched the debate unfold in real time. That experience is the demo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function calling vs RAG is visible in the output quality.&lt;/strong&gt; When Gemini chooses its own tools and sequences them autonomously, the analysis cites specific numbers from specific tool calls. When you inject data manually, the model summarizes it. The difference in specificity is noticeable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Devil's Advocate pattern is underused.&lt;/strong&gt; Every AI project I've seen shows one answer. Showing the disagreement — the argument against the recommended call — builds more trust than a confident single response. Judges found it more interesting than the decision itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 2.5 Pro&lt;/strong&gt; — Strategist agent (proposal phase)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; — All other agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini native function calling&lt;/strong&gt; — Stats Analyst tool use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python FastAPI&lt;/strong&gt; — Backend with SSE streaming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React 18 + Tailwind&lt;/strong&gt; — Frontend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Run&lt;/strong&gt; — Deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Antigravity&lt;/strong&gt; — Primary IDE throughout the build&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Live Demo Screenshots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hp4xtalqlil15w5colk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hp4xtalqlil15w5colk.png" alt=" " width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1evde72aiykble2h90j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1evde72aiykble2h90j.png" alt=" " width="800" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vk9mspbhbxelzc1vcc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vk9mspbhbxelzc1vcc2.png" alt=" " width="800" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nzge8tkial2o7mwtzmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nzge8tkial2o7mwtzmz.png" alt=" " width="800" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/apoorvgpt9/APL-multi-agent-match-strategist.git" rel="noopener noreferrer"&gt;https://github.com/apoorvgpt9/APL-multi-agent-match-strategist.git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo:&lt;/strong&gt; Upcoming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google AI Studio Prompts:&lt;/strong&gt; &lt;a href="https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%221c-J9lQnmzb454DidqyrkeZOgOKWPDqMs%22%5D,%22action%22:%22open%22,%22userId%22:%22101674726802407992704%22,%22resourceKeys%22:%7B%7D%7D&amp;amp;usp=sharing" rel="noopener noreferrer"&gt;https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%221c-J9lQnmzb454DidqyrkeZOgOKWPDqMs%22%5D,%22action%22:%22open%22,%22userId%22:%22101674726802407992704%22,%22resourceKeys%22:%7B%7D%7D&amp;amp;usp=sharing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Huge thanks to GDG Cloud Pune for putting together &lt;br&gt;
the Agentic Premier League — built Captain Cool, &lt;br&gt;
a multi-agent IPL strategist powered by Gemini, &lt;br&gt;
while watching PBKS chase 209 at Dharamsala live &lt;br&gt;
on the big screen.&lt;/p&gt;

&lt;h1&gt;
  
  
  GoogleCloud #GoogleCloudAPL #BuildwithAI #GDGCloudPune
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Built at Agentic Premier League, GDG Cloud Pune, May 17 2026&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Vibe-coded with Google Antigravity in 3 hours&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gemini</category>
      <category>googlecloud</category>
      <category>agenticai</category>
      <category>gdgcloudpune</category>
    </item>
  </channel>
</rss>
