中文
← Back to tutorials

Building Live Match Commentary and Data Reporting with an LLM Agent (2026 Hands-On)

Let an LLM fetch live scores, query stats, and generate commentary via tool calls — the right answer for the real-time scenarios RAG cannot handle

Building Live Match Commentary and Data Reporting with an LLM Agent

In the RAG knowledge base article I kept stressing one thing: RAG handles static knowledge; live data needs tool calling. This article fills in the live half — using an LLM Agent to build an assistant that reports scores live and generates commentary.

The key distinction first: RAG is "retrieve fixed material, then answer," while an Agent is "the model decides which tool to call for data." Ask "what's the score now?" and the Agent recognizes this needs live data, calls the score API, then organizes the result into commentary. This "model autonomously deciding to invoke external capabilities" is the essence of tool calling (function calling). For Agent fundamentals, see the complete guide to AI Agents.

Why live scenarios require an Agent

Consider the kinds of questions a user asks:

  • "How many World Cups has Brazil won?" → static knowledge, RAG suffices.
  • "What's the score in this match right now?" → must query live; data in the vector DB is guaranteed stale.
  • "How many meters has Messi covered this match?" → live stats, requires a data API call.
  • What the last two share: the answer keeps changing, and the only correct path is to let the model fetch the latest data at the moment of answering. That's the reason Agent + tool calling exists.

    Step 1: Define the tools

    Tools are a set of functions you expose to the model. The key is writing clear descriptions — the model relies on them to decide when to call.

    python
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_live_score",
                "description": "Get the live score and basic events for an in-progress match. "
                               "Call when the user asks the current score, who scored, or which "
                               "minute the match is in.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "home_team": {"type": "string", "description": "home team name"},
                        "away_team": {"type": "string", "description": "away team name"},
                    },
                    "required": ["home_team", "away_team"],
                },
            },
        },
        {
            "type": "function",
            "function": {
                "name": "get_match_stats",
                "description": "Get detailed stats for a match: possession, shots, distance "
                               "covered, etc. Call when the user asks for specific metrics.",
                "parameters": {
                    "type": "object",
                    "properties": {"match_id": {"type": "string"}},
                    "required": ["match_id"],
                },
            },
        },
    ]
    

    Tool descriptions should read like instructions to a colleague: when to use it, what parameters it needs. Vague descriptions make the model call when it shouldn't, or fail to call when it should.

    Step 2: The Agent main loop

    An Agent runs as a loop: the model decides to call a tool → you execute it → feed the result back → the model continues, until it gives a final answer.

    python
    import json
    from openai import OpenAI

    client = OpenAI()

    In a real implementation these functions hit actual sports-data APIs

    def get_live_score(home_team, away_team): # Call a third-party live-score API (e.g. API-Football) return {"home": home_team, "away": away_team, "score": "1-0", "minute": 67}

    DISPATCH = {"get_live_score": get_live_score}

    def run_agent(user_msg): messages = [ {"role": "system", "content": "You are a live World Cup commentary assistant. " "Be vivid and conversational, but every score and " "stat must come from a tool return — never fabricate."}, {"role": "user", "content": user_msg}, ] while True: resp = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, ) msg = resp.choices[0].message if not msg.tool_calls: return msg.content # model gives the final answer, done

    messages.append(msg) for call in msg.tool_calls: args = json.loads(call.function.arguments) result = DISPATCHcall.function.name messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(result, ensure_ascii=False), })

    print(run_agent("What's happening in the Brazil match right now?"))

    → Agent calls get_live_score, gets 1-0 at minute 67, then generates commentary

    This loop is what every Agent framework (LangGraph, AutoGen, etc.) does under the hood. Understand the bare loop and you'll see exactly what the frameworks manage for you. To manage more complex state with a framework, see LangGraph stateful Agents complete guide.

    Hallucination prevention: the number-one risk in live scenarios

    The most dangerous failure mode of a live Agent: the API hasn't returned yet, and the model "imagines" a score on its own. Ways to suppress it:

  • A hard order in the system prompt: "every score and stat must come from a tool return; if the tool hasn't returned, say you haven't got it yet."
  • Tell the model explicitly when a tool fails: on API timeout, return {"error": "data source temporarily unavailable"} so the model relays it truthfully instead of falling back to making things up.
  • Double-check key numbers: for scores, have the model attach the raw tool-returned figure to its answer for easy verification.
  • For writing more robust Agent system prompts, see AI Agent system prompt engineering.

    Cost and latency: don't ignore them

    An Agent may call the model and APIs multiple times per round, and live commentary is latency-sensitive. A few optimizations:

  • Use a small model where you can: for routing decisions like "which tool to call," gpt-4o-mini is plenty — saving money and time.
  • Cache slow-changing data: there's no need to query basic team info live every time; cache it.
  • Call tools in parallel: if one round needs several matches queried, fire them off in parallel rather than serially.
  • Assembling the complete match assistant

    By now you hold two puzzle pieces:

  • RAG (previous article) — answers static knowledge like history, rules, teams.
  • Agent tool calling (this article) — answers live scores and instant data.
  • Combine them: a user's question first passes a router deciding "is this static knowledge or a live question," then goes to RAG or the Agent accordingly. That's the skeleton of a production-grade match assistant.

    For the full picture of all applications and how they string into a product, see the AI and 2026 World Cup roundup. From a practice standpoint, get the single-tool call loop working first — mastering this bare loop pays off more than reaching for a framework on day one.

    Also available in 中文.