DEV Community

Shreyas Nalawade
Shreyas Nalawade

Posted on

# 🏏 Captain Cool: How I Built a Multi-Agent IPL Strategist on Gemini in 3 Hours

🏏 Captain Cool: How I Built a Multi-Agent IPL Strategist on Gemini in 3 Hours

"Cricket is not just a sport. It's a chess match at 140 km/h." — and now, it has an AI captain.

title: "🏏 Building \"Captain Cool\": A Multi-Agent IPL Cricket Strategist Powered by Google Gemini & FastAPI"
published: true
tags: python, gemini, ai, webdev
canonical_url: https://dev.to/shreyasn01/building-captain-cool-a-multi-agent-ipl-cricket-strategist-powered-by-google-gemini-fastapi-3ad1

cover_image: https://raw.githubusercontent.com/ShreyasN01/Captain-Cool-Agent/main/readme_banner.png

The Problem: Cricket Decisions Happen in Seconds

🏏 Building "Captain Cool": A Multi-Agent IPL Cricket Strategist Powered by Google Gemini & FastAPI

A T20 captain makes 10–15 high-stakes tactical calls every match — who bowls the death over, when to bring in the Impact Player, whether to attack or defend against a left-hander on a dew-soaked pitch. These decisions carry the weight of a franchise's season, and they have to be made in under 30 seconds.
What if you had a virtual IPL cricket captain sitting in your dugout, making real-time tactical decisions like MS Dhoni, Rohit Sharma, or Hardik Pandya?
I wanted to build something that could replicate that cognitive pressure — not just with a chatbot wrapper, but with genuine agent debate, tool use, and cricket-grade explainability.
In cricket, the best captains don't just rely on gut feeling or raw stats alone. They look at the weather, analyze head-to-head match-ups, calculate win probabilities, and debate tactics with their coaching staff before making a call.
The result: Captain Cool — a multi-agent IPL strategist built entirely on Google Gemini. Here's how it works, and how I built it in 3 hours.

To replicate this, I built Captain Cool — an agentic AI system that orchestrates a 5-turn debate between four specialized AI agents to deliver real-time, context-aware tactical decisions during a live IPL match.

Here is a deep dive into how I built it using the Google Gemini 2.5 Flash, FastAPI (Server-Sent Events), and a mobile-first stadium-themed UI.

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                        USER INPUT                           │
│   (innings, over, score, wickets, pitch, bowlers, etc.)    │
└───────────────────────┬─────────────────────────────────────┘
                        │
                        ▼
          ┌─────────────────────────┐
          │    STATS ANALYST        │  ← Tool call: live cricket API
          │  (Gemini 2.5 Flash)     │     / win-probability model
          └───────────┬─────────────┘
                      │ enriched context
                      ▼
          ┌─────────────────────────┐
          │      STRATEGIST         │  ← Proposes the next decision
          │  (Gemini 2.5 Pro)       │
          └───────────┬─────────────┘
                      │ initial proposal
                      ▼
          ┌─────────────────────────┐
          │   DEVIL'S ADVOCATE      │  ← Challenges with counter-strategy
          │  (Gemini 2.5 Flash)     │
          └───────────┬─────────────┘
                      │ pushback
                      ▼
          ┌─────────────────────────┐
          │      STRATEGIST         │  ← Defends or revises
          │   (multi-turn loop)     │
          └───────────┬─────────────┘
                      │ final call
                      ▼
          ┌─────────────────────────┐
          │   MATCH COMMENTATOR     │  ← Translates to fan-friendly language
          │  (Gemini 2.5 Flash)     │
          └─────────────────────────┘
                      │
                      ▼
             🎙️ FINAL OUTPUT
     Decision + Reasoning + Dissent
Enter fullscreen mode Exit fullscreen mode

Four named agents. One real tool call. A genuine back-and-forth debate. Let me walk through each.

The Four Agents

🏗️ The Multi-Agent Architecture

1. Stats Analyst 📊

Role: Enrich the raw match state with historical and real-time context.
Rather than asking a single LLM to make a decision, Captain Cool uses a cooperative multi-agent debate loop where agents challenge and refine each other's ideas:
System Prompt:

You are a professional cricket data analyst. Given a match state, your job is to:
1. Call the get_player_stats tool to fetch relevant bowler/batter matchup data.
2. Estimate the current win probability based on run rate, wickets, and overs remaining.
3. Identify any pitch or weather factors that statistically affect outcomes.
Return structured JSON with enriched context for the Strategist.
┌──────────────────────────────────────────────────────────┐
│               Captain Cool — 5-Turn Debate               │
│                                                          │
│  📊 Stats Analyst  →  Real function calling              │
│     ↓ Stats Report (live weather + player stats)         │
│  🧠 Strategist v1  →  Proposes tactical call             │
│     ↓                                                    │
│  😈 Devil's Advocate → Challenges the call               │
│     ↓                                                    │
│  🧠 Strategist v2  →  Revises or defends                 │
│     ↓                                                    │
│  🎙️ Commentator    →  Fan-friendly final verdict          │
└──────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Tool used: get_player_stats — a Gemini function-calling tool that fetches recent form, economy rates, and head-to-head matchup stats from a cricket stats API.

Here are the 4 named agents and their roles:

1. 📊 The Stats Analyst (The Tool Caller)

The Analyst has no opinions. It is completely data-driven. Using Gemini's Native Function Calling (Tools), it automatically fetches:

  • Live Weather Data: Real-time relative humidity, dew spread, and temperature using the Open-Meteo API.
  • IPL Player Stats: Granular batting/bowling statistics.
  • Match-up Data: Head-to-head records (e.g., batsman vs. bowler).
  • Win Probability: Computed using a run-rate sigmoid model. ### 2. Strategist 🧠 Role: The captain's brain. Proposes the next tactical move. ### 2. 🧠 The Strategist (The Captain's Brain) Runs twice in the debate. Its system prompt changes dynamically depending on your selected captain persona:
  • Dhoni Style 🧊: Ice-cool, calculated, defensive risk management.
  • Rohit Style ⚡: Aggressive, matchup-focused, chasing wickets.
  • Hardik Style 🔥: Bold, instinctual, backing high-risk impact plays. System Prompt:
You are an IPL captain with the strategic instincts of Dhoni, the aggression awareness of Rohit, 
and the situational reading of Hardik Pandya. Given the match state and analyst context, 
propose ONE specific tactical decision for the next over. 
Explain your reasoning in cricket language — not data science jargon.
Format: DECISION | REASONING | CONFIDENCE (%)
Enter fullscreen mode Exit fullscreen mode

3. 😈 The Devil's Advocate (The Challenger)

This agent's sole job is to tear the Strategist's plan apart. It looks for weaknesses, critiques bowling choices, and warns of dew factors or batting depth.
The Strategist receives the enriched match state and outputs a clear, cricket-literate proposal — e.g., "Bring Bumrah back for the 18th. Powerplay's over, pitch has slowed, and their 4-down batter has a 42% dot-ball rate against length deliveries outside off."

4. 🎙️ The Commentator (The Synthesizer)

Takes the entire debate, synthesizes it, and delivers a final verdict in pure, colorful cricket language along with an overall tactical Confidence Score (%).

3. Devil's Advocate 😈

Role: Challenges the Strategist's call. Argues for the alternative.

🛠️ The Tech Stack

System Prompt:

You are a contrarian cricket analyst. Your ONLY job is to find the strongest possible 
argument AGAINST the Strategist's proposed decision. You must:
- Propose a specific alternative
- Give cricket-language reasoning for why it's better
- Call out any risks the Strategist may have overlooked
Be sharp, specific, and grounded in the match state. Not for the sake of argument — 
for the sake of winning the match.
Enter fullscreen mode Exit fullscreen mode
  • AI Engine: gemini-2.5-flash using the new official google-genai Python SDK.
  • Backend: FastAPI serving SSE (Server-Sent Events) to stream the debate in real-time.
  • Frontend: Vanilla HTML5/JS styled with Tailwind CSS and custom CSS (Intensity Design System: HSL orange/gold gradients, obsidian surfaces, and Sora typography). This is where it gets interesting. The Devil's Advocate doesn't just poke holes — it proposes a concrete alternative. If the Strategist says "bowl Bumrah", the Devil's Advocate might say: "Bumrah's already bowled 3 overs on this pitch. He's shown his hand. Bring in the leggie — they haven't faced him yet, and he gets more turn at this end." --- ### 4. Match Commentator 🎙️ Role: Translates the final decision into broadcast-quality cricket commentary. ## 💡 Code Highlights System Prompt:
You are a seasoned IPL commentator. You've just heard the captain's final tactical decision 
and the internal debate that led to it. Your job:
1. Announce the decision like you're on Star Sports.
2. Explain the reasoning in a way a casual fan understands.
3. Mention what the dissenting view was — and why the captain overruled it.
Keep it punchy, warm, and cricket-smart. No ML terms. No percentages in the output.
Enter fullscreen mode Exit fullscreen mode

⚡ Dynamic Tool Wrapper (Capturing Gemini Function Calls)

When using Gemini's automatic_function_calling=True, the intermediate tool execution logs are handled under the hood. To report exactly which tools were called back to our frontend UI, I implemented a dynamic Python decorator that intercepts and logs tool executions on the fly:

tool_calls_log = []
## The Multi-Turn Reasoning Loop
# Intercept tool calls dynamically to record them for the UI
def wrap_tool(fn):
    def wrapper(*args, **kwargs):
        tool_calls_log.append({
            "tool": fn.__name__,
            "args": kwargs if kwargs else (args[0] if args else {})
        })
        return fn(*args, **kwargs)
    wrapper.__name__ = fn.__name__
    wrapper.__doc__ = fn.__doc__
    wrapper.__annotations__ = fn.__annotations__
    return wrapper
This is the part I'm most proud of. The debate isn't cosmetic  it actually changes the output.
Here's the flow in code terms:
Enter fullscreen mode Exit fullscreen mode


javascript
// Round 1: Strategist proposes
const proposal = await strategistAgent.generate(matchState + analystContext);
// Round 2: Devil's Advocate challenges
const challenge = await advocateAgent.generate(matchState + proposal);
// Round 3: Strategist revises or defends
const finalCall = await strategistAgent.generate(
matchState + proposal + challenge + "Now make your final call. If the Devil's Advocate raised a valid point, revise. Otherwise, defend your decision with more conviction."
);
// Round 4: Commentator wraps it up
const commentary = await commentatorAgent.generate(finalCall + challenge);
wrapped_tools = [wrap_tool(t) for t in tools]

The conversation history is passed explicitly at each step — no memory tricks, just clean multi-turn context management.
### 📡 Real-Time SSE Debate Streaming
To make the application feel alive, the FastAPI backend streams the debate agent-by-agent as they speak using **Server-Sent Events (SSE)**. Here is how the orchestrator yields events:
---
## A Real Example: CSK vs MI, Over 17
**Match Input:**
Enter fullscreen mode Exit fullscreen mode


python
async def run_debate(match_state: dict):
# Turn 1: Stats Analyst
yield sse_event("agent_start", {"turn": 1, "agent": "Stats Analyst", "emoji": "📊", "message": "Analyzing pitch & weather..."})
stats_report = await stats_analyst(match_state)
yield sse_event("agent_done", {
"turn": 1,
"agent": "Stats Analyst",
"emoji": "📊",
"content": stats_report["report"],
"tool_calls": stats_report["tool_calls"]
})

# ... successive turns (Strategist, Devil's Advocate, Commentator) ...

yield sse_event("complete", {"status": "done"})
Enter fullscreen mode Exit fullscreen mode
Innings: 2 | Over: 17 | Score: 142/4 | Target: 178
Strike: Hardik Pandya (34 off 22) | Non-striker: Tim David (11 off 8)
Bowlers left: Bumrah (2 overs), Boult (1 over), Pollard (1 over)
Pitch: Wankhede, flat with dew. Powerplay done.
Enter fullscreen mode Exit fullscreen mode

markdown

Stats Analyst output:

Hardik vs Bumrah: 14 balls, 18 runs, 1 dismissal. Hardik attacks short-pitch deliveries (SR 210 on back-of-length). Tim David vs left-arm pace: 8 balls, 22 runs. Wankhede dew factor: 8/10. Win probability for batting side: 61%.

🎨 Premium Mobile-First UI


The UI is built with a dark dugout-themed aesthetic (Deep Obsidian #131313 with vibrant Orange #ff8a00 accents).
Strategist proposes:
BOWL BOULT NOW. Save Bumrah for 19th and 20th. With dew, Boult will struggle to swing it — but his yorker accuracy is high, and Tim David has historically struggled vs left-arm seam in the first 3–4 balls of a new bowler. Use Boult to tie down Tim David this over, set up Bumrah for the kill in 19. CONFIDENCE: 72%.
It is divided into two distinct screens:

  1. Command Center: The tactical input dashboard to configure the live match situation (innings, score, wickets, batsman, available bowlers, venue, and pitch properties).

2. War Room: The multi-agent debate view with a real-time progress bar, typing indicators, and beautiful cards displaying each agent's contribution.

Screen 1: Command Center (Inputs)
Command Center
Devil's Advocate challenges:
Wrong. Dew means Boult loses his biggest weapon — swing. He becomes a full-price medium pacer at Wankhede tonight, and Tim David eats medium pace for breakfast. Worse: Hardik is on 34, not yet in the 40s. He's calculating, not yet in destruction mode. Bowl Bumrah NOW. Catch him before he accelerates. Save Boult for over 19 — he can bowl tight yorkers even without swing. The upside of getting Hardik out in over 17 is worth burning Bumrah early.
Screen 2: War Room (The Live Agent Debate)

War Room

Strategist defends/revises:
The Devil's Advocate raises a legitimate point about dew neutralizing Boult's swing. REVISED CALL: Bring Bumrah on now. Target Hardik with back-of-length deliveries outside off — his data shows he mistimes those. Set a 5-3 off-side field. Use Boult for 19, Pollard as floater in 18 for a change of pace.

🚀 Try It Yourself!


The code is open-source and ready to run locally!
Match Commentator:
"And the captain makes the move — Bumrah is back! The thinking here is simple: Hardik is dangerous but hasn't exploded yet. Get him now before it's too late. The alternative was to hold Bumrah back, but with the dew taking the shine off Boult's swing, the captain decided attack is the best form of defense. If Bumrah can get Hardik in the next six balls, this chase is very much alive. Big over coming up."

1. Clone the repository

git clone https://github.com/ShreyasN01/Captain-Cool-Agent.git
cd Captain-Cool-Agent
Enter fullscreen mode Exit fullscreen mode

2. Configure environment

Create a .env file in the root directory:

GEMINI_API_KEY=your_free_api_key_from_google_ai_studio
Enter fullscreen mode Exit fullscreen mode

Tech Stack

3. Run with virtual environment

python3 -m venv venv
source venv/bin/activate
pip install -r backend/requirements.txt
cd backend
python main.py
Enter fullscreen mode Exit fullscreen mode
Component What I Used
LLM Gemini 2.5 Pro (Strategist) + Gemini 2.5 Flash (others)
Agent Framework Google ADK (Agent Development Kit)
Tool Calling Gemini function calling → cricket stats REST API
Prompt Prototyping Google AI Studio
IDE Google Antigravity (vibe-coded the whole session)
Frontend Minimal web form + JSON output panel

Open http://localhost:8000 in your browser and start making calls like Dhoni!

What I Learned in 3 Hours

🧠 Key Learnings

  1. Multi-Turn Reasoning Beats One-Shot: Letting LLM agents challenge their own plans (e.g. Strategist vs Devil's Advocate) results in much safer, highly nuanced decisions.
  2. Synchronous Tool Isolation: When using LLM function calling in async environments, keeping external tool lookups synchronous isolates API networks and avoids complex thread clashes.
  3. UX is Everything for Agentic Apps: Streaming agents in real-time makes the AI's internal reasoning process completely transparent, turning a slow API call into a highly engaging user experience. 1. Agent roles need hard constraints, not soft ones. My first version had all agents "collaborate openly." That produced mush. Once I gave each agent a clear prohibition ("your ONLY job is to challenge"), the outputs sharpened dramatically. If you liked this project, don't forget to star the repository on *GitHub! Let me know in the comments: which captain persona is your favorite?* 🏏 **2. Passing full conversation history is expensive but necessary. The multi-turn loop works because each agent sees exactly what the others said. This costs tokens. For production, Gemini context caching would be the fix. 3. The Commentator agent is the secret weapon. Users don't want to read JSON. They want to feel the decision. The Commentator agent transforms a structured output into something fans actually want to read — and it costs almost nothing to add. 4. Cricket language is a quality signal. I specifically tested whether the output used cricket terminology ("leggie," "back-of-length," "death overs," "pinch-hitter") vs generic language ("the bowler," "the strategy"). The system prompt phrase "explain in cricket language a real captain would use" was doing a lot of heavy lifting. --- ## What's Next
  4. Real-time mode: Paste a Cricbuzz URL, let Gemini's URL context tool scrape the live state
  5. Voice interface: Web Speech API + Gemini Live for an actual talking captain
  6. Confidence + counterfactuals: "If you'd bowled X instead, win prob drops 8%"

- Memory across overs: Gemini context caching so the agent remembers its own decisions from over 1

Try It / Read the Code

🔗 GitHub: github.com/ShreyasN01/Captain-Cool-Agent
The repo includes:

  • All four agent system prompts
  • The multi-turn orchestration loop
  • The Gemini function-calling tool definition for cricket stats
  • Google Antigravity traces (.antigravity/ folder) from the build session

- A sample match scenario you can run end-to-end

Built in 3 hours. Fueled by chai and the memory of Dhoni's 2011 World Cup final six.

If you're into cricket + AI, drop a comment or connect — would love to talk shop.

Tags: #gemini #googleai #multiagent #cricket #ipl #hackathon #adk #javascript

Top comments (0)