omarcevi.dev / workshops / match-day-agents / 3 · Scouting Dept

Step 3 · Scouting Department

The pattern: a ParallelAgent starts its sub-agents at the same time, each writing its own state key. A SequentialAgent around it lets a report writer merge the results afterwards.

Step 3: inside a SequentialAgent, a ParallelAgent runs attack_scout, defense_scout and discipline_scout at once, then report_writer merges attack_report, defense_report and discipline_report
Three scouts at once, one writer after. Tap to open full size.

One scout covers Gaziantep's attack, one their defence, one cards and the referee. None needs the others' work, so there's no reason to wait:

steps/step3_scouting_dept/agent.py
    report_writer = LlmAgent(
        name="report_writer",
        model=MODEL,
        instruction="""Merge three scouting reports into one brief for Trabzonspor's coaches.
Attack report: {attack_report}
Defense report: {defense_report}
Discipline report: {discipline_report}
Write four short sections: Threats, Weaknesses to attack, Discipline and referee, Three key takeaways.
Use only facts from the reports; if they disagree, say so.""" + HOUSE_RULES,
        output_key="scouting_brief",
    )
    scouts = ParallelAgent(name="scouts", sub_agents=[attack_scout, defense_scout, discipline_scout])
    return SequentialAgent(name=name, description=description, sub_agents=[scouts, report_writer])

The scouts' instructions don't name the opponent; each starts with get_match_info to find out. No instruction in this repo hardcodes a fact from the data, so a new fixture is just new JSON.

I asked: "Scout Gaziantep for us."

The three scouts made ten tool calls between them, all at once, and the writer merged their reports in 43 seconds. From the brief, trimmed:

Weaknesses to Attack

  • Second-half defensive collapse (last 10 matches – 15 goals conceded, 1.5 avg, 1.63 avg xGA across 9 matches with xG data):
    • 10 of 15 goals conceded (67%) came in the second half.
    • Vulnerability peaks heavily in 46–60 min (4 conceded, 27%) and 76–90 min (5 conceded, 33%).

Three Key Takeaways

  1. Exploit the decimated backline: Gaziantep's defensive anchor Myenty Abena is suspended, while starting goalkeeper Kacper Tobiasz and three central defenders (Meleke, Kızıldağ, Sangaré) are doubtful with muscle injuries. …

Use it when you have independent questions about the same thing: three searches, three reviewers, three data sources.

Avoid it when one task needs another's answer, or when the parallel work writes to the same state key.

The gotcha: something has to merge the results. A ParallelAgent gives you three answers in whatever order they finished, not one. Give every parallel agent its own output_key, then add a step that reads them all. Parallel also means more requests per second, which is where a free key starts hitting rate limits.