Press a real button. Send a ping. Let the story tell you what’s beyond the windows.
Build it with Otherwhere OS. We’ll go from loose parts to a complete scenario, with the configuration beside the thing it controls.
01 Raspberry Pi with a 40-pin header, power supply, and storage
02 Two momentary buttons: action and push-to-talk
03 An LED, a 1 kΩ resistor, breadboard, and jumper wires
04 A supported microphone and powered speaker
This guide uses the reference board, orion.console@3. The wiring is shared by both adventures. Changing the physical layout means defining your own board.
GPIO signals are 3.3 V. Keep 5 V away from these connections, and keep the resistor in series with the LED. Check your Pi’s header orientation ↗
Speaker, microphone, and power
Use a supported powered speaker or amplifier and microphone. The board expects ALSA devices named speaker and microphone; these aliases must match your Pi’s audio setup. The GPIO header does not drive the speaker directly.
The board owns the pins. The scenario asks for a button, a light, a speaker, and a way to talk. That is what lets the same wiring become a different machine.
A button has no permanent sound or story role. Adding another supported button usually means adding a component and binding. New hardware primitives may need a driver.
Write who is aboard and how they respond. Start with an unknown contact. The captain gets to investigate; a button press does not decide what they find.
characters:
orion:
name: Navigator Orion
personality: Observant, patient, and quietly amused by unexpected discoveries.
prompt: You navigate a homemade submarine on an imagined ocean expedition. Help
its captain listen, investigate, and name what they discover. Begin with
an unexplained sound beyond the windows. Let the captain decide whether to
follow it, wait, or ask a question. A whale is one possible encounter, not
a guaranteed result of a button press.
voice: orion_voice
initial_presence: submarine
scenario.yaml · root excerpts
Start from the complete download, then change the character, rules, and starting facts together. Give your version its own scenario identity. Published versions are immutable.
The sounds are included in the download: verified prototype cues from the existing inventory. An asset alias chooses audio; it does not generate it.
Use your own sound
Choose or create a WAV, measure its SHA-256, byte count, and PCM duration, and add it to assets/catalog.json. Its file path is relative to that catalog. Point the scenario’s asset alias to that hash, then rerun the local exercise. The helper checks the actual bytes.
When the ping actually finishes, turn the lamp off, reopen the button, and ask the story for an observation. The response uses the current story and the captain’s earlier choices.
The whale is one illustrated possibility. The real director receives an observation request; discoveries become durable facts through accepted story effects.
What if the story is already speaking?
A non-record input can be accepted as busy_recorded during an active turn. It is recorded without queuing a surprise story action for later. Device observations remain diagnostics; only declared story inputs take this path.
If the ping never completes, an eight-second timeout stops the sound and reopens the button. Talking or reconnecting also clears temporary state. A missing completion never becomes a discovery.
Download the whole build: board, complete scenario, audio, catalog, and interaction trace. Extract the builds folder into your supplied pi-exp checkout.
Use Bun 1.4.0, Python 3.12, and uv 0.12.0. The prototype runtime comes with the supplied checkout; this download contains the build files. Run these commands from the checkout root.
bun --no-env-file tools/install-typescript-dependencies.ts
uv sync --project apps/device-agent --frozen --all-groups
terminal · trace tab shows the opening inputs
The exercise builds the package, verifies the audio, and runs the real reactor with fake hardware. Read each step’s commands, local state, and server intents. Completing a fake sound is explicit; advancing time only drives timers.
With your Pi enrolled against the matching board, upload the audio, publish the scenario, and build its package. Otherwhere OS downloads and verifies the package before activating it.
This prototype uses the supplied installation and enrollment workflow, plus a configured server and authorized admin CLI. Set up and enroll your Pi → Keep credentials in your local runtime file.
Use the actual package UUID returned by the build for PACKAGE_ID, and your enrolled Pi’s UUID for DEVICE_ID. Confirm orion.console@3 is published and matches that device. If you changed the layout or story, publish the new board/scenario identity and use those references instead.
How do I know it is running?
Inspect the package’s exact board, scenario, assets, and hash. After selecting it, inspect the device again and wait for desired and active package IDs to agree. An existing story session can retain its current scenario; preserve it or end it deliberately before switching.
Then try the real button, lamp, speaker, and push-to-talk. The local exercise does not prove physical wiring, microphone capture, server effects, or a heard story response. Package and device reference →