ambient-bed 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. Generate a long looping location ambience (forest, dungeon, city, cave) on the Ambient bus.
When your agent uses it
- Generating a long looping location ambience — forest at dawn, dungeon air, city street, spaceship hum, cave drip — non-melodic and low-energy
- A location feels silent and needs a continuous soundscape beneath the score and effects
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
An ambient bed is the air of a place. Forest at dawn, dungeon corridor, spaceship hum, market street, ocean cave. It plays at low energy under everything else and is never melodic. Players rarely notice a bed, but they notice the silence when a level has none. This is not music. Useassets.generate_audio({ capability: 'sound_effects' }), not { capability: 'music' }: the SFX model renders texture, the music model renders melody.
Generated at 15–22 seconds (the SFX duration ceiling) and looped with a Summer
Engine import loop point and optional crossfade.
When to use
- Location bed for a level, room, biome, or zone.
- Background hum / drone under dialogue scenes.
- Atmosphere layer that complements a music track.
When NOT to use
- Short event SFX (<5s) →
sound-effect. - Music with melody / chord progression →
music-track. - Voice barks →
voice-line.
Steps
1. Read the audio bible
Ambient layer SFX class names the character — usually “continuous, low presence, no looping melody”. Honor it. The mix rules sit ambient at the bus level the bible defined (typically Ambient bus around -12 dB).
2. Identify the location
Ask if it’s not pinned by context:Which location’s ambience? Be specific — “forest at dawn with light wind and distant birds” beats “outdoors”. The model needs the time of day, the weather, and 2–3 sound sources.
3. Build the prompt — environment + time + weather + 2–3 sources + density + duration
The SFX model renders ambient texture well when the prompt names sound sources, not moods. Prompts that work:4. Density — keep it low
A bed should be boring. Ask for sparse events.every 6 secondsrather thanoften.occasionalnotfrequent.distantnotclose.lownotloud.
no recognisable words, no individual loud sounds, general crowd murmur.
5. Generate at the duration ceiling
modelId: "eleven_text_to_sound_v2" with loop: true: it is the only sound-effect model that makes seamless loops, and without a modelId the person’s default sound-effect model runs, which may not loop. sound_effects reads from text, not prompt — without text the call is refused (text_required). (prompt is the music capability’s field.) The clip comes back as WAV, so a .wav target path is correct.
22s is the SFX ceiling. Always generate at the ceiling for ambient — longer cycle means less recognized repetition.
If the model returns a clip with a loud event near the start or end (a sudden bird right at 0:00), regenerate. That kills loop seamlessness.
6. Mark the seamless loop in Summer Engine’s Import dock
WAV and MP3 use different importers with different option names — do not copy the MP3 block frommusic-track here. The WAV importer has no loop / loop_offset; it has an edit/loop_mode enum plus sample-frame bounds.
In Summer Engine, select the .wav and open the Import dock:
The
.import file:
edit/loop_mode is 0 = Detect From WAV, 1 = Disabled, 2 = Forward, 3 = Ping-Pong, 4 = Backward — Forward is 2, not 1. edit/loop_begin / edit/loop_end are integer sample frames, not seconds; to skip a 0.5 s fade-in artifact at 44.1 kHz set edit/loop_begin = 22050.
After changing, click Reimport.
7. Crossfade-loop pattern for seamlessness
Generated SFX clips are not gapless. Even with the loop mode set, you will often hear a small click at the loop point. Fix it with a two-player crossfade in code:fade_seconds so the bed never repeats identically).
8. Wire the bed as AudioStreamPlayer on the Ambient bus
For most beds, non-positional is correct (the player is in the place; the bed isn’t an emitter):
stream to the imported audio, and skip the AudioStreamPlayer node — the script provides its own.
For positional beds (ambience emitting from a fountain, a campfire, a vent) use AudioStreamPlayer3D with attenuation. The bible’s 3D attenuation: inverse-square, 25m rule applies.
9. Layer multiple beds for depth
Real places have layered ambiences. A forest at dawn might be:- Bed A (loud): wind through leaves loop,
-12 dB - Bed B (medium): distant bird calls loop,
-18 dB - Bed C (occasional): one-shot SFX of a single bird call, fired by a Timer with random 8–20s interval
Reference card — prompts by environment
Anti-patterns
- Using
assets.generate_audio({ capability: 'music' })for an ambient bed. Music model adds melody. You don’t want melody. - Foreground events in the bed. A wolf howl, an explosion, a clear word — these promote themselves and the bed becomes annoying.
- Bed louder than
-10 dBon its bus. Beds belong under everything; default is-12 dBto-15 dB. - No loop point set. The clip plays once and silence follows.
- Single-clip looping without crossfade. Audible click every 22s.
- Same bed everywhere. Different rooms / biomes need different beds. The transition (room A → room B) is what sells the world.
Edge cases
- Bed too busy on regen. Add
sparse,quiet,low,distantto the prompt. - Bed has musical content you didn’t ask for. Add
no music, no melody, no chords. - Bed has voices when you wanted abstract. Add
no voices, no recognisable words. - Loop click after import dock setup. Use the crossfade script (step 7).
- Need positional bed (a campfire crackle). Use
AudioStreamPlayer3Dwithmax_distancematching the campfire’s reasonable hearing radius (4–8m typical). - Multi-room transitions. Use Areas; on player enter, fade in destination bed and fade out source bed over 1.5s.
Without Summer Engine
In a session without Summer Engine tools (the assets profile; thesummer-assets skill has the whole loop), do steps 1-5 and stop when the bed exists. Skip steps 6-9: the loop point, the crossfade script and the AudioStreamPlayer are Summer Engine work. Save the file where the person asked with out (the summer-assets skill says how), and tell them the path and format. Tell the person it is a long bed made to loop: their engine either loops it with a short crossfade or plays two copies that overlap.
Fallback (no MCP)
Print the SFX prompt and the import dock settings. User runs via the Summer dashboard and imports manually.Handoff
Bedforest_dawn.wavwired toLevel/AmbientBed, looping with crossfade. Next:
- Generate the night counterpart for time-of-day transitions.
- Add a layered occasional bird-call SFX with a randomized Timer for depth.
- For multi-room transitions, gate beds with Area3D triggers and fade with the same crossfade pattern.
See also
audio-direction— defines the Ambient layer classsound-effect— short event SFX layered over the bedmusic-track— melodic music layered over the bedadaptive-music— state-driven crossfades use the same pattern
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.
Source:
library/skills/ambient-bed/SKILL.md, rendered from summer-engine@4.3.0 on npm.
