← Case Studies

Detroit Sports Chatbot

An AI agent that answers questions about Detroit sports with live data — not a chatbot wrapper, but a tool-calling agent that decides when to hit the ESPN API, fetches real scores and stats, and synthesizes an answer. Supports two AI providers (Claude Sonnet and Groq), voice input and output, and an automated eval pipeline that improved response quality 28% across four prompt iterations.

Python · Streamlit · Anthropic Claude API · Groq · ESPN API

The Problem

General-purpose AI models have a hard cutoff — they can't tell you tonight's score, who's on the injury report, or what the standings look like after last night's games. Fans who want real-time answers have to cross-reference ESPN, team apps, and search results manually. The goal was an AI that could answer sports questions conversationally while pulling live data exactly when the question required it — and nothing else.

Try It

detroitsportchatbot.onrender.com

No API key needed — a server-side Groq key powers the default model. Switch to Anthropic in the sidebar if you want to use your own Claude key. Open full screen ↗

Mobile Experience

The chatbot is fully responsive — the sidebar collapses to a hamburger menu on small screens so the full chat area is usable. Voice input is especially useful on mobile: tap the mic in the sidebar, ask your question, and the answer streams back and plays as audio automatically. No typing required.

9:41

Mobile view — sidebar collapses, full chat area visible

Tool Architecture

The agent has access to 15 live ESPN API tools covering all four Detroit teams — Lions, Tigers, Red Wings, and Pistons. The model decides which tool to call based on the question. A knowledge question like "who is the greatest Red Wing of all time?" hits no tools. A question like "what's the Lions score?" triggers a live NFL scoreboard fetch. A question like "what does the depth chart look like?" triggers a separate endpoint. The model only calls what the question actually needs.

NFL / NBA / MLB / NHL Scores
Live scores and game status
Standings
Conference standings by sport
Schedule
Next 5 upcoming games
Injuries
Current injury report
Roster
Full roster by position group
News
Latest headlines
Team Stats
Season statistics
Transactions
Recent signings, trades, and cuts
Depth Chart
Starters and backups by position
Leaders
Top performers from current or most recent game
Play-by-Play
Live play-by-play during active games
Box Score
Full box score from current or most recent game

Live Score Sidebar

The sidebar shows live scores for any Detroit game happening today — Lions, Tigers, Red Wings, or Pistons — without the user needing to ask. All four ESPN scoreboards are checked on page load and the results are cached for 5 minutes so the API isn't hit on every Streamlit interaction. Only in-progress and final games are shown; scheduled future games are filtered out to avoid showing upcoming matchups as if they were live. A manual refresh button clears the cache if you want up-to-the-minute data during a close game.

Provider Architecture

Two AI providers — Claude Sonnet and Groq (Llama 3.3 70B) — run through a unified interface using the same tool-calling loop and system prompt. Switching providers swaps the underlying model without changing anything else. Groq is the default: a server-side key on Render means the live demo works for anyone without setup. Bring your own Claude key to compare — the same question through different models shows exactly how tool-calling behavior and response style differ.

Prompt Engineering & Eval Pipeline

Response quality was measured with an automated eval pipeline across four prompt iterations — eight test cases covering live data questions, knowledge questions, hallucination risks, and redirect behavior for non-Detroit questions. Each answer was graded 1–5 by Groq's Llama 3.3 70B with context injected so it could distinguish real ESPN tool output from fabricated responses. 28% improvement from v1 to v4, 3.2 to 4.1. Try it yourself below.

Technical Implementation

Agentic Tool-Calling Loop

The tool-calling loop runs until the model stops requesting tools. On each turn, if the model returns a tool_calls finish reason, the server executes the requested ESPN function, appends the result to the message history, and sends the updated history back to the model. The loop continues until the model produces a final text response. This means a single user question can trigger multiple sequential tool calls if the model decides it needs more than one data source to answer fully.

ESPN Response Caching

Each ESPN endpoint response is cached for 30 seconds using a simple in-memory dictionary keyed by URL. On every tool call, the cache is checked first — if the cached entry is within the TTL, the stored response is returned immediately. This prevents redundant API calls when multiple questions in a session ask about the same endpoint. The 30-second TTL is short enough that live game scores stay current but long enough to absorb bursts of related questions.

Voice Input & Output

Users can ask questions by voice using a mic recorder in the sidebar — audio is transcribed in real time via Groq's Whisper large-v3 model. Voice output via gTTS (Google Text-to-Speech) is available as an opt-in toggle in the sidebar, so users who want audio responses can enable them without it playing automatically for everyone. Voice mode makes the chatbot usable hands-free, which is useful on mobile where typing a sports question mid-game is inconvenient.

Security & Rate Limiting

API keys are stored server-side only — never sent to the browser or exposed in the Streamlit client. Rate limiting is set to 10 requests per minute to protect against API quota exhaustion. If a visitor provides their own key in the sidebar, it is used for that session only and never persisted. The default Groq key is loaded from the server environment, so the live demo works for anyone with no setup.

Context Window Management

The full conversation history is stored in session state and displayed in the UI, but only the most recent 20 messages are sent to the API on each turn. When the trimmed slice would start mid-exchange on an assistant message, the first message is dropped so the API always receives a well-formed conversation beginning with a user turn. This keeps token costs bounded regardless of how long a session runs, while the displayed chat history remains complete for the user.

Streaming

Responses stream word by word to the Streamlit UI as the model generates them. A thinking indicator is displayed while tool calls are executing so the user knows the agent is working. Once the final response starts streaming, the indicator is replaced with the text in real time. Error messages for rate limits, invalid keys, and API failures are handled gracefully with plain-English copy rather than raw exception output.

The Outcome

A deployed AI agent — not a demo, live at detroitsportchatbot.onrender.com — that answers Detroit sports questions with real ESPN data. Response quality improved 28% through iterative prompt engineering measured by an automated eval pipeline, not guesswork. Voice input via Groq Whisper and voice output via gTTS make it usable on any device. The provider abstraction means the same agent runs on Claude or Groq with a single sidebar toggle.