Ambient Bed logo

Ambient Bed

Organization
SummerEngine
ambient-bed

Generate a long looping location ambience (forest, dungeon, city, cave) on the Ambient bus.

Overview

PublisherSummerEngine
Repositorysummer
Skill nameambient-bed
Stars
91
Forks
8
Bundled files
1
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by SummerEngine on GitHub. Read the source before you install it.

Installation

Install the Ambient Bed AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/SummerEngine/summer/tree/main/library/skills/ambient-bed
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/SummerEngine/summer.git /tmp/summer
mkdir -p .claude/skills
cp -r /tmp/summer/library/skills/ambient-bed .claude/skills/ambient-bed
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ambient Bed in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ambient Bed on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ambient Bed is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

/ambient-bed — Long Looping Location Ambience

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. Use assets.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

Read .summer/audio-bible.md

The bible's 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:

forest at dawn, gentle wind through leaves, distant bird calls every 6 seconds,
soft creaking branches, no music, no human sound, 22s seamless loop

stone dungeon corridor, distant water drip, low rumble, faint draft, no music,
no creature sound, 22s seamless loop

spaceship corridor, low hum at 60Hz, occasional electronic chirp, ventilation
whoosh, no human voices, 22s seamless loop

medieval marketplace at noon, distant chatter, footsteps on stone, occasional
horse, distant blacksmith hammer, no recognisable words, 22s loop

ocean cave, slow waves entering, low rumble, water drip echoes, no seagulls,
22s seamless loop

night swamp, crickets, distant owl, slow water lapping, occasional frog,
22s seamless loop

abandoned office building, fluorescent hum, distant air conditioning, faint
paper rustle from a vent, no human sound, 22s loop

Prompts that DON'T work:

Bad promptFailure mode
forest ambienceNo time / weather / sources. Returns generic forest with random energy spikes.
creepy dungeonVibe word, not a description. Model adds horror stings you don't want.
peaceful background musicTriggers musical interpretation. Use SFX-shaped prompts.
loud bustling marketEnergy too high for a bed; use as a one-shot SFX layer instead.
forest with wolves howlingWolf howl is an event, not a bed; promotes itself in the mix.

4. Density — keep it low

A bed should be boring. Ask for sparse events.

  • every 6 seconds rather than often.
  • occasional not frequent.
  • distant not close.
  • low not loud.

If the user wants a busier bed (market, party), still prevent foreground events: no recognisable words, no individual loud sounds, general crowd murmur.

5. Generate at the duration ceiling

assets.generate_audio({
  capability: "sound_effects",
  modelId: "eleven_text_to_sound_v2",
  loop: true,
  text: "forest at dawn, gentle wind through leaves, distant bird calls every 6 seconds, soft creaking branches, no music, no human sound, 22s seamless loop",
  durationSeconds: 22
})
// Then: summer_import_from_url(url: "<asset.fileUrl>", path: "res://audio/ambient/forest_dawn.wav")

Name 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 from music-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:

SettingValue
Edit > Loop ModeForward
Edit > Loop Begin0
Edit > Loop End-1 (end of file)

The .import file:

[params]
edit/loop_mode = 2
edit/loop_begin = 0
edit/loop_end = -1

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:

gdscript
# scripts/audio/AmbientBed.gd
extends Node
@export var stream: AudioStream
@export var fade_seconds: float = 1.5
@export var bus: StringName = &"Ambient"
@export var volume_db: float = -12.0
var _a: AudioStreamPlayer
var _b: AudioStreamPlayer
var _active: AudioStreamPlayer

func _ready() -> void:
	_a = _make_player()
	_b = _make_player()
	_active = _a
	_active.play()
	_schedule_next()

func _make_player() -> AudioStreamPlayer:
	var p := AudioStreamPlayer.new()
	p.stream = stream
	p.bus = bus
	p.volume_db = volume_db
	add_child(p)
	return p

func _schedule_next() -> void:
	var len := stream.get_length()
	var t := get_tree().create_timer(len - fade_seconds)
	t.timeout.connect(_crossfade)

func _crossfade() -> void:
	var next := _b if _active == _a else _a
	next.volume_db = -60.0
	next.play()
	var tw := create_tween().set_parallel(true)
	tw.tween_property(next, "volume_db", volume_db, fade_seconds)
	tw.tween_property(_active, "volume_db", -60.0, fade_seconds)
	tw.chain().tween_callback(func() -> void: _active.stop())
	_active = next
	_schedule_next()

This eliminates the click and adds variation through phase-overlap (the loop overlaps itself by 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):

summer_run_script(scenePath="res://levels/level_01.tscn", source="""
func run(ctx):
    ctx.add_node("AudioStreamPlayer", "AmbientBed", ctx.find("Level"), {
        "stream": load("res://audio/ambient/forest_dawn.wav"),
        "bus": "Ambient",
        "volume_db": -12.0,
        "autoplay": true,
    })
    ctx.save_scene()
""")

Or attach the script in step 7 to a Node, set its 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

This is more expensive (3 generations) but produces a bed that doesn't sound like a 22-second loop. Reserve for hub locations or extended scenes.

Reference card — prompts by environment

Forest dawn:        forest at dawn, gentle wind, distant birds every 6s,
                    creaking branches, 22s loop
Forest night:       forest at night, crickets, distant owl every 10s, soft
                    breeze, no music, 22s loop
Stone dungeon:      stone dungeon, distant water drip every 4s, low rumble,
                    faint draft, no creatures, 22s loop
Cave:               wet cave, water drip echoes, low air movement, distant
                    rumble, 22s loop
Spaceship:          spaceship corridor, 60Hz hum, occasional electronic chirp,
                    ventilation whoosh, no voices, 22s loop
Marketplace:        medieval marketplace at noon, distant chatter no recognisable
                    words, footsteps on stone, occasional horse, distant
                    blacksmith, 22s loop
Tavern:             medieval tavern interior, low chatter, fireplace crackle,
                    distant lute, occasional mug clink, 22s loop
Ocean cave:         ocean cave, slow waves, low rumble, water drip echoes,
                    no seagulls, 22s loop
Office:             empty office at night, fluorescent hum, distant AC,
                    faint paper rustle, 22s loop
Snowy plain:        snowy plain in wind, low howling wind, faint distant
                    branches, no music, no creatures, 22s loop
Underwater:         underwater, low rumble, distant bubbles, soft mid hum,
                    no marine life, 22s loop
Boss arena:         vast stone arena, low ominous drone, distant rumble,
                    occasional debris fall, no melody, 22s loop

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 dB on its bus. Beds belong under everything; default is -12 dB to -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, distant to 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 AudioStreamPlayer3D with max_distance matching 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; the summer-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

Bed forest_dawn.wav wired to Level/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 class
  • sound-effect — short event SFX layered over the bed
  • music-track — melodic music layered over the bed
  • adaptive-music — state-driven crossfades use the same pattern

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.

In this skillCommand
assets.generate_audio, summer_assets_generate_audiosummer assets generate-audio
summer_assets_searchsummer assets search
summer_add_nodesummer engine add-node
summer_import_from_urlsummer engine import-from-url
summer_inspect_nodesummer engine inspect-node
summer_run_scriptsummer engine run-script
summer_set_propsummer engine set-prop

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Ambient Bed AI skill do?

Generate a long looping location ambience (forest, dungeon, city, cave) on the Ambient bus.

Why use Ambient Bed on TypingMind?

Because you install it once and use it with any model. Ambient Bed is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ambient Bed in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/SummerEngine/summer/tree/main/library/skills/ambient-bed. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Ambient Bed?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ambient Bed?

As many as you like. As long as a model supports skills, you can use Ambient Bed with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ambient Bed AI skill free?

Yes. It is published on GitHub by SummerEngine under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇