Post

πŸ† Hackapizza 2.0 - Winning an AI Agents Hackathon

πŸ† Hackapizza 2.0 - Winning an AI Agents Hackathon

what a weekend!! on february 28th and march 1st, our team β€œCavalli al trotto πŸŽβ€ won πŸ† Hackapizza 2.0: Agent Edition, the hackathon organized by Datapizza in Milan β€” one of the most intense and stimulating competitions i’ve ever taken part in.

24 hours non-stop designing, testing and stress-testing advanced agentic systems, competing against 120 selected participants from all over Italy.

the team was composed of Giacomo Pacini, Dario Cioni, Alessio Chen and me.

hackapizza2

πŸ• The Challenge

the hackathon track was β€œgalactic” themed, building on the first edition: participants had to build a fully autonomous virtual restaurant β€” no human intervention allowed.

the AI agents had to independently:

  • purchase ingredients through a blind auction
  • define the menu and prices dynamically
  • exchange ingredients between competing teams
  • serve incoming clients, managing queues and priorities
  • read a blog with β€œnews” and market trends
  • analyze competitors and the market to maximize revenue

the competition used the datapizza-ai open-source agentic framework, with API inference provided by Regolo.ai, a european LLM inference provider.


πŸ€– System Architecture

we built a real-time multi-agent system that simulates running a restaurant in an alien universe. five specialized AI agents compete against other restaurants to maximize profit through intelligent decision-making.

Agents

agentphasepurpose
menu agentspeaking / waitingdecide dishes and pricing
bid agentclosed_biddetermine ingredient bids
allergy agentservingextract allergies & intolerances from order text
service agentservingmatch client order to a safe dish
memory agentstoppedgenerate turn summaries and lessons learned

Turn Structure

each game turn progresses through five sequential phases:

phasepurposekey actions
speakingplanning & diplomacyopen restaurant, decide menu, negotiate
closed bidingredient procurementsubmit blind bids in auction
waitingstrategic adjustmentadjust menu based on actual inventory
servingcustomer servicecook and deliver dishes to clients
stoppedend-of-turn analysisgenerate summary, clear transient state

critical rule: ingredients expire at the end of each turn β€” unsold inventory is lost. this pushed us to design a bidding agent that estimated demand carefully rather than over-buying.


βš™οΈ How It Works

the system is entirely event-driven: an SSE loop is the heartbeat, and every game event triggers a handler that updates in-memory state and schedules background work without blocking the loop.

1
2
3
4
5
6
7
8
9
10
11
12
game server (SSE)
      β”‚
      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   game_phase_changed    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SSE loop   β”‚ ──────────────────────► β”‚         orchestrator (background task)   β”‚
β”‚  (main.py)  β”‚                         β”‚                                          β”‚
β”‚             β”‚   client_spawned        β”‚  speaking  ──► menu_agent  ──► save_menu β”‚
β”‚             β”‚ ──────────────────────► β”‚  closed_bid ──► bid_agent  ──► closed_bidβ”‚
β”‚             β”‚   preparation_complete  β”‚  waiting   ──► menu_agent  ──► save_menu β”‚
β”‚             β”‚ ──────────────────────► β”‚  serving   ──► per-client flow           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β”‚  stopped   ──► memory_agent ──► db summaryβ”‚
                                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Per-Client Serving Flow

when a client_spawned event arrives, the orchestrator processes the client in a dedicated async task:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
client_spawned { clientName, orderText }
        β”‚
        β–Ό
1. allergy_agent ──► detect allergies from free-form order text
        β”‚
        β–Ό
2. pre-filter menu ──► remove any dish containing a forbidden ingredient
        β”‚
        β–Ό
3. service_agent ──► pick the best safe dish from the filtered menu
        β”‚              (defense-in-depth re-check if LLM picked unsafe dish)
        β–Ό
4. prepare_dish (MCP) ──► wait for preparation_complete SSE event
        β”‚
        β–Ό
5. serve_dish (MCP) ──► meal delivered, logged to DB

if any step fails, the orchestrator falls back to a deterministic dish picker that also enforces allergy constraints.


🧩 Key Architectural Decisions

Long-Term Memory

one of the main challenges of the hackathon was managing long-term memory across game turns. the memory agent generates structured turn summaries β€” lessons learned, bidding outcomes, competitor behavior β€” that are persisted to MySQL and fed back into the next turn’s planning.

State Persistence

every decision and tool call is persisted to MySQL in real time:

1
2
3
4
5
6
7
8
9
10
allergy_agent decision  ─┐
menu_agent decision     ────► decisions table
bid_agent decision      ──
service_agent decision  β”€β”˜

prepare_dish / serve_dish ─┐
save_menu / closed_bid     β”€β”˜β”€β”€β–Ί mcp_calls table (with latency_ms)

game_phase_changed ─┐
client_spawned      β”€β”˜β”€β”€β–Ί sse_events table

Deterministic Fallbacks

every AI agent has a deterministic fallback path β€” this was critical to avoid losing turns when LLM calls timed out under high concurrency during the competition.


πŸ“ Project Structure

1
2
3
4
5
6
7
8
9
10
11
12
hackapizza2.0/
β”œβ”€β”€ main.py                  # entry point: SSE listener & event dispatcher
β”œβ”€β”€ hackapizza/
β”‚   β”œβ”€β”€ agents.py            # AI agents (menu, bid, service, memory, allergy)
β”‚   β”œβ”€β”€ context.py           # AppContext & GameState singleton
β”‚   β”œβ”€β”€ db.py                # MySQL persistence layer
β”‚   β”œβ”€β”€ http_client.py       # game API HTTP client
β”‚   β”œβ”€β”€ mcp_actions.py       # MCP tool invocation client
β”‚   └── orchestrator.py      # phase coordinator & agent orchestrator
β”œβ”€β”€ hackapizza-dashboard/    # git submodule: monitoring dashboard
β”œβ”€β”€ recipes-analysis/        # 900+ recipes dataset & analysis
└── docker-compose.yml       # MySQL + Redis + dashboard services

πŸ› οΈ Tech Stack

  • language: Python 3.12+ (async/await)
  • AI framework: datapizza-ai
  • LLM provider: Regolo.ai (OpenAI-compatible, european)
  • networking: aiohttp (SSE + HTTP), JSON-RPC
  • database: MySQL 8.4, Redis 7 (Docker)
  • dependency management: uv

🎬 Conclusion

this was one of the most technically demanding competitions i’ve experienced. the combination of multi-agent orchestration, real-time event-driven architecture, complex game theory decisions and very tight time constraints made every hour count.

beyond the technical side, it was great to meet and exchange ideas with other AI enthusiasts and professionals from all over Italy β€” discussing architectural patterns, agent design choices and future directions for AI systems.

a special thanks to the entire Datapizza team for organizing such an impeccable event, and to the jury: Simone Rizzo, Enrico Mensa, Giuseppe Gullo, and Giacomo Ciarlini.

πŸ”— GitHub Repository

visit the project repository here for accessing the full codebase (if you enjoyed this content, please consider leaving a star ⭐).

πŸ“Έ Photos

hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2 hackapizza2
This post is licensed under CC BY 4.0 by the author.