Skip to main content
summer-matchmaking is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Get players into matches with Summer matchmaking: queues, teams, accept prompts, join progress and failures.

When your agent uses it

  • The user wants matchmaking, a lobby, a play button, quick play, ranked or casual modes in a multiplayer Summer game
  • Declaring queues, player counts, teams (2v2, 5v5), rated queues or a ready check in summer.build.json
  • Showing search progress, an Accept/Decline prompt, cancel search or join errors to players
  • The authority needs to know which team or queue each player is on

Install

summer setup installs every skill for your agent. To add only this one:
Swap claude-code for your agent, such as codex or cursor. See Skills for every option.

The skill

Overview

A queue is a game mode players search in: “casual 2–8”, “duel 1v1”, “ranked 2v2”. You declare queues in summer.build.json; Summer matchmaking groups searching players, reserves a server for them, and every player’s Summer.client.join(SummerJoinTarget.queue(...)) completes in the same World. The authority then reads each player’s team from the verified Session. There is no lobby object, invite code or server browser. Friends who want to play together use a party (summer-parties), which enters a queue as one group. Where it works: This skill extends the Courtyard game from multiplayer-project and multiplayer-state. Its client already joins Game.QUEUE and sends a join Command; its authority publishes match_doc.

Steps

1. Declare the queues

Each queue in runtime.queues of summer.build.json names the WorldDefinition its matches run. A casual mode and a 1v1 rated duel:
The fields Summer accepts, and their rules: Don’t add lobby fields or backfill: Summer rejects both when you publish. Teams and acceptance need runtime.interfaces.multiplayer 5 or higher; the project skill’s summer.build.json declares 6.

2. Search, with progress the player can see

Add a status label and two hidden buttons to the client scene, client/main.tscn (position them in the editor as you like):
In client/main.gd, replace the join in _ready(), from var join := through the if not joined.ok: block, with a call to find_match:
and add the matchmaking functions:

3. Accept or decline a found match

With "acceptance": {"mode": "all"}, Summer reserves a server first, then asks every player. The match starts only when all accept before the deadline. The engine never decides for the player: connect acceptance_required, or the join waits until the proposal expires.
After an accept, find_match keeps waiting until everyone accepted. A decline ends it with proposal_declined. A game that always accepts (one “Play” button) connects acceptance_required straight to proposal.accept().

4. Tell players what went wrong

Every failure is a SummerResult with a stable code and retryable:
Other codes: proposal_stale and proposal_already_decided (a second decision), world_waking (a persistent World is restoring), qos_stale, platform_error, and unavailable (Local Play hosts a different queue).

5. Cancel the search, or leave

Summer.client.leave() cancels a search in flight, or leaves the current match. Await it before quitting the game, so the platform knows the player is gone and doesn’t hold a seat for them:
To offer “Play online” only when it can work, read Summer.client.matchmaking.availability.hosted_sessions_available (and hosted_unavailable_reason) before showing the button.

6. Read teams and the queue on the authority

The authority learns each player’s team from the verified Session. In authority/main.gd, give match_doc a "teams": {} entry and add this to _join just before request.accept(...):
Players learn teams only from what the authority publishes, here the shared match document. Summer.get_world().queue on the authority names the queue this match came from, so one authority scene can serve several modes.

7. Test it with Local Play

Local Play stands in for one queue at a time: the first one declared, or the one you name. In the editor and with summer_play, name it with the summer/local_play/queue project setting:
A terminal run ignores that setting; pass the queue instead: <summer> --path . --summer-local-play 2 --summer-local-play-queue duel --summer-local-play-smoke.
  • The client must join the queue Local Play stands in for. Another queue fails with unavailable: “Local Play is hosting queue ‘courtyard’. Start Local Play with queue ‘duel’ to test that queue.”
  • Players are placed at once: progress goes straight to STAGE_CONNECTED, with no search and no Accept/Decline.
  • A team queue seats players round-robin in roster order (player-1 on team 0, player-2 on team 1, and so on), whatever order they connect in.
  • Summer.client.matchmaking.availability reports hosted sessions as available.
Test the accept prompt and rating-based grouping on a hosted staging build.

Checklist

  • Every queue names a WorldDefinition; teams queues have minPlayers = maxPlayers = count × size.
  • The client shows search progress and a readable message for each failure code.
  • Queues with acceptance show Accept/Decline with the deadline; nothing auto-accepts unless the game means to.
  • Cancel and quit both await Summer.client.leave().
  • The authority reads get_participant(session).team and publishes teams to players.
  • Local Play with summer/local_play/queue set runs each queue you declared.

Common mistakes

See also

  • multiplayer — how Summer multiplayer fits together
  • summer-match-results — ending a match and reporting who won
  • summer-leaderboards — ratings and leaderboards for rated queues
  • summer-parties — friends entering a queue together
  • multiplayer-testing — Local Play options and bots

From a shell

No Summer MCP tools in this session? Run each one as a command; when summer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
  • multiplayer: Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next.
  • multiplayer-project: Set up a Summer multiplayer project: entry scenes, World and queue files, joining, a first Local Play.
  • multiplayer-testing: Test a Summer multiplayer game with Local Play: several players, bad network, bots, a passing run.
  • summer-match-results: End a Summer match: report each player’s win, loss or draw, show results on clients, then close the World.
  • summer-leaderboards: Leaderboards in a Summer game: queue ratings from matches, and Game rankings your authority scores.
  • summer-parties: Let a Summer party play together: the leader presses Play, members follow into the same match. Hosted only.

Source: library/skills/summer-matchmaking/SKILL.md, rendered from summer-engine@4.3.0 on npm.