Abyssal Pressure Drone
Lovable AI calculates depth pressure so submarine animators light scenes; the robot program running on the Adamo SDK performs it live.
The move.
The app scaffolds a Python `adamo.Robot` program for underwater acoustics that filmmakers download and run on their robot host — cameras attach, control subscribers fire, and the browser previews the live H.264 feed coming back over the bridge.
Why this kernelA Python `adamo.Robot` program is the right kernel for underwater acoustics: Filmmaking & Animation needs generative behaviour running on the machine itself, close to the actuators and cameras, with the browser only there to preview cameras and hand out `robot.py`.
Run the bridge first.
Start the bridge on your laptop before pasting the prompt below. The Lovable app never holds the Adamo key.
The build prompt.
Paste into a fresh Lovable project. Make sure the bridge above is running first. read the bridge protocol →
Build "Abyssal Pressure Drone" as a ONE-SHOT Lovable build **from a phone**. The participant
has only 5 credits and only a mobile browser — this single message must ship a
working demo with zero follow-ups and zero laptop steps. Physical AI on Adamo.
CONCEPT
Lovable AI calculates depth pressure so submarine animators light scenes; the robot program running on the Adamo SDK performs it live.
Discipline: film-animation (underwater acoustics).
Kernel: Simulate (sandbox simulation).
Why this kernel: A Python `adamo.Robot` program is the right kernel for underwater acoustics: Filmmaking & Animation needs generative behaviour running on the machine itself, close to the actuators and cameras, with the browser only there to preview cameras and hand out `robot.py`.
MOBILE-ONLY, SANDBOX-BACKED — READ THIS FIRST
Adamo's SDK is Python-only. Cloudflare Workers cannot import it. The
participant is on a phone; there is no laptop bridge. The ONLY place inside
this Lovable session where the SDK runs is the Linux build sandbox. So:
- Every Adamo call happens in a Python script the agent runs ONCE at
build time in the sandbox.
- The script writes a JSON proof artifact into `public/` that the
deployed mobile web app fetches at runtime.
- The deployed app itself never imports adamo, never holds
ADAMO_API_KEY, never opens a QUIC/Zenoh socket, never calls a
server function that tries to.
- The runtime robot performance happens later at the physical showcase,
off-device. The mobile app AUTHORS, the sandbox VERIFIES, the operator
PLAYS BACK.
SECRETS
Request `ADAMO_API_KEY` via the add-secret tool (format hint `ak_...`).
Never reference it in .ts/.tsx code, never in `import.meta.env`, never in
a `createServerFn` handler. It lives only in the sandbox process env.
BUDGET (5 CREDITS, ONE-SHOT)
- ONE TanStack Start app, one primary route (`src/routes/index.tsx`).
- ONE mobile-first surface (touch targets >=44px, thumb-reachable primary
action, no hover-only affordances, no drag-only interactions).
- Lovable AI Gateway allowed for text (default `google/gemini-3-flash-preview`),
called from a server fn.
- NO database, NO auth, NO Lovable Cloud, NO extra pages, NO tests.
- Libraries: template defaults + `ai` + `@ai-sdk/openai-compatible` + `zod`.
VERIFIED ADAMO SDK SURFACE (adamo >= 0.4.42)
import adamo
session = adamo.connect(api_key=os.environ["ADAMO_API_KEY"])
session.put(key, payload_bytes)
sub = session.subscribe(key, callback=fn) # kwarg-only, NOT positional
session.get(key, timeout_ms=5000) # returns list[Sample]
session.live_tokens("**/alive") # discovery (returns live tokens)
session.alive(token_key) # DECLARES a token; not discovery
session.close()
Footguns: subscribe callback is kwarg-only; `alive()` declares, `live_tokens`
discovers; `connect` requires `api_key=` (keyword).
STEP 1 — SMOKE TEST (mandatory, every build)
Write this to `scripts/adamo_smoke.py` verbatim:
```python
"""Verify ADAMO_API_KEY from the Lovable sandbox and write proof to
public/adamo-smoke.json. Run once during the build."""
from __future__ import annotations
import json, os, sys, time, threading
from datetime import datetime, timezone
from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "public" / "adamo-smoke.json"
OUT.parent.mkdir(parents=True, exist_ok=True)
def write(p): OUT.write_text(json.dumps(p, indent=2) + "\n"); print(json.dumps(p))
def main() -> int:
key = os.environ.get("ADAMO_API_KEY")
if not key:
write({"ok": False, "error": "ADAMO_API_KEY missing"}); return 2
try:
import adamo
except Exception as e:
write({"ok": False, "error": f"adamo import failed: {e!r}"}); return 2
out = {"ok": False, "at": datetime.now(timezone.utc).isoformat(),
"sdk_version": getattr(adamo, "__version__", "unknown"),
"roundtrip_ms": None, "alive": [], "error": None}
s = None
try:
t0 = time.time()
s = adamo.connect(api_key=key)
out["connect_ms"] = int((time.time() - t0) * 1000)
k = f"lovable/smoke/{int(time.time()*1000)}"
got = threading.Event(); seen = {}
def on(sample):
try: seen["v"] = json.loads(bytes(sample.payload).decode())
except Exception: seen["v"] = None
got.set()
sub = s.subscribe(k, callback=on)
time.sleep(0.2)
sent = time.time()
s.put(k, json.dumps({"ping": sent}).encode())
if got.wait(3.0):
out["roundtrip_ms"] = int((time.time() - sent) * 1000)
out["ok"] = True; out["echo"] = seen.get("v")
else:
out["error"] = "roundtrip timeout"
try: sub.undeclare()
except Exception: pass
try: out["alive"] = sorted({str(t) for t in (s.live_tokens("**/alive") or [])})
except Exception as e: out["alive_error"] = repr(e)
except Exception as e:
out["error"] = f"{type(e).__name__}: {e}"
finally:
try:
if s is not None: s.close()
except Exception: pass
write(out)
return 0 if out["ok"] else 1
if __name__ == "__main__":
sys.exit(main())
```
Then in the sandbox run:
python -m pip install --no-cache-dir adamo
python scripts/adamo_smoke.py
Commit the resulting `public/adamo-smoke.json`.
STEP 2 — KERNEL JOB (Simulate)
SANDBOX JOB — scripts/adamo_simulate.py
After the smoke test succeeds, write a second script that:
1. `adamo.connect(api_key=os.environ["ADAMO_API_KEY"])`
2. Loads a small JSON program authored by the mobile UI (embed a
placeholder at `public/program.json` so the sandbox can read it).
3. `session.put(f"sim/film-animation-abyssal-pressure-drone-22", payload_bytes)` a few times, spaced 200ms.
4. `session.subscribe(f"sim/film-animation-abyssal-pressure-drone-22", callback=fn)` and records ~2 s
of echoed samples.
5. Writes `public/adamo-take.json` with { ok, samples: [...], at }.
Run it once at build time. The app renders `/adamo-take.json` on screen so
the participant sees "sandbox verified the program roundtrips" without
touching a robot.
STEP 3 — MOBILE APP
- `src/routes/index.tsx` renders the Simulate surface for "Abyssal Pressure Drone".
- Include an `<AdamoProof />` card that `fetch("/adamo-smoke.json")` on
mount and shows: "Sandbox verified at HH:MM · Xms roundtrip · N tokens
live". Empty state: "No proof yet — re-run scripts/adamo_smoke.py".
- Mobile-first layout: single column, 16-24px padding, primary CTA fixed
or bottom-anchored within thumb reach. NO desktop-only grids as the
main surface.
- Empty state copy when no robot is connected: "Your key is verified in
the sandbox. The operator will replay this on the robot at the
showcase." — never "start the bridge" or "install Python".
- Tailwind + shadcn. Editorial industrial look: gold accent, dark
background, one strong headline, one primary action.
- Footer: "Built during the Physical AI & Creative Robotics Hackathon
organised by StreetKode Fam during Indian Krump Festival 14".
BRAIN — Lovable AI Gateway (already provisioned, no key prompt)
```ts
// src/lib/ai-gateway.server.ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
export function gateway() {
return createOpenAICompatible({
name: "lovable",
baseURL: "https://ai.gateway.lovable.dev/v1",
headers: {
"Lovable-API-Key": process.env.LOVABLE_API_KEY!,
"X-Lovable-AIG-SDK": "vercel-ai-sdk",
},
});
}
```
Call `generateText` inside `createServerFn` handlers only.
DO / DON'T
| Do | Don't |
| ----------------------------------------------- | ---------------------------------------------- |
| Run adamo only in scripts/ (sandbox) | `import adamo` from a server fn or route |
| Read `/adamo-smoke.json` from the browser | Read ADAMO_API_KEY from `import.meta.env` |
| `session.subscribe(k, callback=fn)` | `session.subscribe(k, fn)` (positional fails) |
| `session.live_tokens("**/alive")` for discovery | `session.alive()` for discovery |
| Design for a phone in portrait first | Ship a desktop dashboard as the primary UI |
SUCCESS
On first load on a phone, the participant sees the Simulate surface for
"Abyssal Pressure Drone", the AdamoProof card shows a green "sandbox verified" line with
a real roundtrip number, and the primary action is reachable with the
thumb. That is the demo.
Market sizing.
Indicative figures for hackathon pitches — refine with your own research before raising.