Composable, portable AI agent capsules. Bundle an agent's identity, persona, tools, and transport into a single signed HTML+JS+WASM file (~960 KB) that you can email, embed, or deploy.
Docs: https://docs.gemmapod.com · Live demo: https://gemmapod.com · Discussions: https://github.com/apprider/gemmapod/discussions
POD one signed .html capsule = one agent
├─ TOOLKIT build & sign @gemmapod/toolkit
├─ HOST device runtime @gemmapod/host
│ ├─ MODEL local LLM bridge (Ollama / OpenAI-compatible)
│ └─ BUS pod registry, event stream, conversation store
├─ SIGNAL WebRTC relay @gemmapod/signal
├─ EMBED browser runtime @gemmapod/embed (+ shim, core)
└─ gemmapod unified CLI npm i -g gemmapod
Pods are the agents. The Toolkit builds them. Your Host runs them. The Model thinks for them. Signal lets them reach visitors. Embed lets a webpage hold one.
| path | what |
|---|---|
packages/dartc/ |
@gemmapod/dartc — DARTC v0.2 envelope, topic helpers, AG-UI-shaped UI events. |
packages/core/ |
@gemmapod/core — Rust → WASM. Signed manifest (CBOR + Ed25519). Web + Node. |
packages/shim/ |
@gemmapod/shim — Browser runtime + Preact widget. Two IIFEs from one source. |
packages/embed/ |
@gemmapod/embed — npm/CDN wrapper around the two shim IIFEs. |
packages/gemmapod/ |
gemmapod — Unified CLI: create, run, start, status, list, logs, stop. |
packages/toolkit/ |
@gemmapod/toolkit — Build & sign library used by the CLI. Programmatic API for pipelines. |
packages/host/ |
@gemmapod/host — Local Host runtime: registry, event bus, conversation store, HTTP+dashboard. |
packages/signal/ |
@gemmapod/signal — Signaling broker + pluggable Registry interface. |
apps/docs/ |
Fumadocs site → docs.gemmapod.com. |
examples/ |
hello-pod, script-tag-embed, nextjs-embed, react-headless, copilotkit-style, restaurant-pod, host-minimal, self-host-signaling, raj-card. |
dartc.md |
DARTC protocol spec (canonical). |
runtime.md |
GemmaPodRuntime SDK spec (canonical). |
SECURITY.md |
Threat model + vulnerability reporting flow. |
# Unified CLI (recommended)
npm i -g gemmapod
# Browser SDK for embedding pods in a web page or email
npm i @gemmapod/embed
# Self-host the signaling broker
docker run ghcr.io/gemmapod/signal:latest# One interactive wizard — creates pod.toml, owner.key, and agent.html
gemmapod createThe wizard walks you through name, persona, system prompt, tools, and
model. Your signed .html agent capsule lands in
./my-pod/agent.html.
Go live — stream visitors through your local Ollama over WebRTC:
gemmapod run ./my-podAfter editing pod.toml — rebuild the signed capsule:
gemmapod rebuild ./my-podValidate the manifest before building:
gemmapod doctor ./my-pod/pod.tomlCheck the runtime is healthy:
gemmapod statusRequires Node 22+, pnpm 9+. Rust toolchain only if rebuilding the WASM
core (committed packages/core/pkg{,-node}/ artefacts work otherwise).
pnpm install
pnpm build:core # rebuilds @gemmapod/core (Rust → WASM)
pnpm -r --filter "./packages/*" build
pnpm test # runs @gemmapod/dartc + @gemmapod/signal + @gemmapod/host testsRun the docs locally:
pnpm dev:docs # http://localhost:3002| Variant | Where it runs | Why |
|---|---|---|
| Gemma 4 E2B | Visitor's browser via transformers.js + WebGPU | ~1 GB at q4. Fallback when the Host is offline. |
| Gemma 4 E4B | Owner's Host via Ollama | Primary path over a WebRTC data channel. |
| Gemma 4 31B Dense | Same Ollama endpoint, opt-in per request | "Heavy mode" for deeper reasoning. |
| Gemma 4 26B MoE | Optional sidecar | High-throughput planning / RAG / batch tools. |
- Same Rust code signs and verifies everywhere.
@gemmapod/corebuilds twice:pkg/for browsers (and the shim's IIFE),pkg-node/for the CLI and the Host — so the on-wire signed manifest format cannot diverge between encoder and decoder. - The WASM is inlined inside the shim IIFE as a
data:URL. Packed pods and the live widget run literally the same WASM module. - Signal carries SDP only. Chat bytes flow over the WebRTC data channel directly between visitor and Host. The Signal broker is a thin rendezvous + a static-blob proxy.
- DARTC is the data-channel protocol. Signed JSON envelopes,
topic-multiplexed. A2A Agent Cards exchanged on
a2a.discovery; chat on signedgemmapod.chat.*; UI events ongemmapod.ui.event. - GemmaPodRuntime is the SDK spine. Typed event bus + state store + capability registry + chat API. The default Preact widget is one adapter; CopilotKit-shaped React shells are another.
- Two IIFE builds from one source.
gemmapod-shim.iife.js(full — runtime + Preact widget + boot + signing).gemmapod-runtime.iife.js(runtime + transports only, for bring-your-own-UI hosts). - AG-UI-compatible UI events. Signed
gemmapod.ui.eventenvelopes carry an AG-UI-shaped lifecycle. Field names match;GemmaPod.mapDartcUiEventToAgUi(event)rewrites the discriminator for CopilotKit-shaped UIs. - Manifest signature is enforced before mount. A tampered blob surfaces a visible "gemmapod refused to mount" instead of a silently altered persona.
- Tools are signed and Host-enforced. Packed pods carry the signed manifest inside DARTC hello/chat payloads. The Host verifies it again and exposes only locally-registered tools whose names appear in the signed manifest.
- Pluggable signaling backend.
@gemmapod/signal'sRegistryinterface is four methods.MemoryRegistry+SqliteRegistryship. Bring your own for S3 / R2 / Postgres / Firestore / whatever. - The fallback never auto-downloads. When WebRTC fails and the fallback transport is configured, the UI renders a panel showing cache state and WebGPU availability; the user clicks once to fetch transformers.js + the model.
See CONTRIBUTING.md. The short version: open an
issue → branch → add a changeset (pnpm changeset) for any change that
affects a published package → open the PR. CI runs build, dartc +
signal tests, npm pack dry-runs, and an end-to-end CLI smoke.
MIT — see LICENSE.