summer-friends 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. Summer friends in a game: a consented friends list, profile and chat screens, direct messages. Hosted only.
When your agent uses it
- Showing a friends list, who is online or which friends are playing this Summer game
- Opening a player’s Summer profile, friends list or chat screen from inside a game
- Reading or writing a player’s direct messages, or a friends call fails with permission_undeclared or permission_declined
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Overview
Friendships belong to the player’s Summer account. The Summer app owns the social graph itself:- friend requests;
- blocking;
- the friends list screen;
- profiles;
- chat.
Summer.client.friends
- Two screens need no consent:
show_friends()andshow_chat(user_id). They ask the Summer app to show its own screen over the game. show_profile(user_id)is the same. The profile includes add friend, message, invite to party and report, so it is the social feature most games need.- With consent, it reads the list: each friend’s name, handle and whether they are
offline,online,in_this_gameorin_other_game. Another game is never named.
Summer.client.messages
- Reads and sends the player’s direct messages, with a separate consent for each kind of access.
- Prefer
show_chat(user_id)unless chat is central to your game.
- The Build declares the permission in
summer.build.json. - The player grants it in the Summer app’s consent sheet, which your game asks for with
request_access.
- Engine release. This needs an engine release that includes
SummerClientFriends. On older engines,Summer.client.friendsdoes not exist and scripts that use it fail to parse. Check the class reference forSummerClientFriendsbefore using this skill. - Hosted only.
is_available()isfalsein Local Play and editor runs, for guests, for accounts the platform keeps out of social features (age_restricted, under 13), and in Summer apps withoutplayer.friends@1(friends) orplayer.messaging@1(messages). - Overlays. The screens need the Summer app to offer friends and parties; otherwise they fail with
capability_unavailableorui_unavailable.
Steps
1. Declare the permissions you use
Add a top-levelpermissions array to summer.build.json, next to schema
and gameId. List only what the game uses; each entry is an upper bound on
what you may ask for.
Unknown or duplicate entries are rejected when you publish. Without a
declaration,
get_access() reports undeclared, and request_access() fails
at once with permission_undeclared.
2. The friends node
client/friends.gd, a child Friends of Main. In client/main.gd’s _ready(), call
$Friends.start() right after Summer.initialize succeeds:
- When the list is read again. With a handler on
changed, the engine re-reads the list on every change hint, after a consent decision, onrefresh(), and about every 60 seconds while the game is in front. Never poll yourself. - Statuses. Show
in_this_gamefriends first.unknownmeans presence couldn’t be read; it is notoffline. - Rows. Key them by
user_id; each read replaces theSummerFriendobjects. - Profiles of other players. For the people in the current match, use the user ids your authority publishes (the
playersmap insummer-world-chat, step 1) and callshow_profile(user_id). Your own id fails withinvalid_argument. - Inviting a friend into a match. Use the party invite sheet (
summer-parties).
3. Direct messages (only if chat is central)
- Read a page. Ask for
social.messages.read, thenmessages.list_messages(user_id). Readop.messages, newest page first; passop.next_cursorfor older pages. - Catch up. After
messages_changed, calllist_messages_after(user_id, last_sequence). Todaymessages_changedfires only after a stream resync, so also reload when the chat screen opens. - Mark read.
mark_read(user_id, sequence)needssocial.messages.read_state.write. It marks the thread read on every device. - Send rules.
sendtakes 1–4000 characters and no control characters except newline and tab. Each call is one message; the engine never sends it twice.
4. Failure codes
5. Test
Local Play has no accounts, so check the hidden path locally:is_available()isfalse;- buttons are hidden;
- there are no script errors.
access_changed.
Checklist
- The engine’s class reference lists
SummerClientFriends. -
summer.build.jsondeclares exactly the permissions the code asks for. - Local Play: friends features are hidden, with no script errors.
- Declining consent leaves the game fully playable, and the button can ask again later.
- Hosted: a friend playing the game shows
in_this_game;show_profileopens for another player in the match. - No polling timer: updates come from
changed.
Common mistakes
See also
summer-parties: playing together, the invite sheetsummer-world-chat: chat inside a matchmultiplayer-publish:summer.build.jsonand publishing a Buildmultiplayer-testing: what Local Play can and can’t test
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --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.
Related skills
multiplayer: Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next.multiplayer-testing: Test a Summer multiplayer game with Local Play: several players, bad network, bots, a passing run.summer-parties: Let a Summer party play together: the leader presses Play, members follow into the same match. Hosted only.summer-world-chat: Add match chat to a Summer game: one World channel shared by everyone in the match. Hosted only.
Source:
library/skills/summer-friends/SKILL.md, rendered from summer-engine@4.3.0 on npm.
