Egglets

An Egglet is a first-class app that runs inside Egg. The platform provides storage, tools, an LLM router, Gateway services, cross-Egglet messaging, refs, credentials, and headless fetch through a single SDK surface. Each Egglet declares which of those it uses, and the runtime enforces that contract.

If you are familiar with progressive web apps, an Egglet is the closest analogy. The difference is that Egglets are not built on a sandboxed third-party origin: they are first-party code shipped with Egg, with direct access to a richer set of platform services than a browser can safely give a website. In return for that access, every Egglet ships a manifest that declares what it touches.

What is an Egglet

An Egglet is a self-contained app that ships inside Egg. Feed (the RSS and social aggregator), People (the contacts directory), Studio (the media generator), Explore (the research canvas), and Agent (the chat surface) are all Egglets. Each one owns a top-level route, has its own page in the chrome, shows up in the Eggs menu, and has a card in Settings.

You build an Egglet when you want to add a first-class app to Egg, not a website that runs in a tab. The user installs Egg and gets your Egglet alongside everything else.

When to use an Egglet

Both Egglets and ordinary web apps run on the user’s machine. The differences are about where they live, what services they get, and how the user finds them.

DimensionWeb appEgglet
Where it runsIn any browser, isolated by originOn the user’s hardware, inside Egg, with platform access
How users find itA URL, a bookmark, a search resultThe Eggs menu, the Egg landing page, a card in Settings
DistributionYou host and maintain it; the user visitsShips with Egg; updates with the app
Background workService Worker, subject to OS suspensionScheduled pollers driven by the Gateway daemon, survive a closed window
Where data livesIndexedDB or localStorage in the browser, or your own backendLocal SQL on the user’s disk, never leaves the device unless the user opts into sync
LLM accessBring your own provider, your own API key, your own billingThe user’s configured model slot, often a local Ollama install with zero per-call cost and nothing leaving the machine
Network identityDatacenter IP from your server, or the user’s IP from a tabThe user’s real residential IP for both ctx.fetch and headless fetches, so sites do not block you as scraper traffic
Cross-app surfacespostMessage between same-origin framesTools the agent can call, IPC to other Egglets, shared @kind:id refs
AuthenticationCookies, OAuth flows you implementUser-authorized credential vault, accessed by declared source name

Pick a web app when your audience is the open web and the standard browser surface is enough. Pick an Egglet when the work has to happen on the user’s hardware: their disk holds the data, their machine runs the model (often a local Ollama install, no per-call cost, nothing leaves the device), and their browser does the fetching from a real residential IP that sites do not block as scraper traffic. The agent’s tool catalog, cross-Egglet refs, and cross-device sync are bonuses on top of that local-first foundation.

Chrome extensions answer a different question. They exist to modify other people’s websites in real time. An Egglet cannot do that, but it has a much bigger surface for everything else.

DimensionChrome extensionEgglet
Where it runsSandboxed inside someone else’s browser (Chrome, Edge, Brave)First-class app inside Egg, on the user’s hardware
Page injectionCan inject content scripts into any URL pattern the user grantsCannot inject. Page-level work goes through Browser Automation and the agent’s URL-pattern firewall
UI surfaceA popup, a sidebar, a devtools panel, optional new-tab overrideA full route in the chrome with its own page, its own card in Settings, its own place in the Eggs menu
Background workService worker, killed after about 30 seconds of idle under MV3Scheduled pollers driven by the Gateway daemon, survive a closed window
DistributionChrome Web Store review, per-user installShips with Egg; updates with the app
API surfacechrome.* APIs, intentionally restricted; MV3 removed many capabilitiesctx.* SDK with structured storage, an LLM router, refs, IPC, credentials, and headless fetch
Databasechrome.storage with small quotas, or IndexedDBLocal SQL on the user’s disk, with optional cross-device sync
LLM accessBring your own API key, your own server, your own billingThe user’s configured slot, often a local Ollama install with zero per-call cost
Cross-app communicationchrome.runtime.sendMessage between extensions, rarely used in practiceEgglet IPC, shared refs, and a shared tool catalog. Designed for collaboration.

Pick a Chrome extension when your job is to modify other people’s websites in real time. That is the one thing Egglets cannot do. Pick an Egglet for everything else.

Structurally, an Egglet is a folder with a manifest.json and an index.ts. The host loads both at app launch, calls the entry’s activate(), and the Egglet registers its tools, mounts its page, and starts whatever work it needs. The next sections cover what goes in the manifest, what the runtime hands you, and the contract between the two.

What the platform provides

An Egglet receives a single ctx object on activation. Every backing it can reach is on that object, grouped below into four tiers plus one escape hatch. The SDK reference documents each in full.

Primitives

The universal toolkit. Every Egglet uses these, and none carry product semantics.

SurfaceWhat it does
ctx.logTagged logger scoped to the Egglet’s id.
ctx.routesMount the Egglet’s top-level React view at its declared route.
ctx.toolsRegister named tools the agent or other Egglets can call.
ctx.databaseRead and write the Egglet’s own tables. SQL placeholders resolve to physical names.
ctx.scheduleRegister pollers and other recurring work the platform drives.
ctx.fetchIn-process outbound HTTP through the platform’s HTTP client.
ctx.headlessHidden-browser page fetches for SPAs and login-walled feeds.
ctx.filesSandboxed per-Egglet file storage — read, write, list, remove — plus listing and serving daemon-generated files.
ctx.credentialsRead user-authorized credentials for declared sources.
ctx.refsResolve and own @kind:id refs that travel between Egglets.
ctx.eggletIpcFire-and-forget messaging between Egglets.
ctx.tierThe user’s tier and per-capability availability and quotas.
ctx.setupPreflight the Egglet’s declared manifest.setup dependencies against current Gateway state, so it can gate its core UI and degrade optional features.

Capabilities

Model, media, and browser-extension access. Platform capabilities, not tied to one app.

SurfaceWhat it does
ctx.aiModel surface: text (chat / embed / rerank), image, audio (speech), video.
ctx.mediaffmpeg / ffprobe operations: probe, transcode, concat, mux, extract audio / clip / frame, download.
ctx.extensionDrive the Egg Chrome Extension: capture URLs in the user’s real browser and read back what it captured.

Runtime services

The Gateway’s always-on background machinery.

SurfaceWhat it does
ctx.jobsThe generic deferred-work queue: enqueue work of a known kind and get a Job handle (wait / subscribe / cancel / children).
ctx.thinkingBackground contemplation — commission a dialectical session whose findings flow into the agent’s memory.

Egg domains

Data domains a built-in Egg app owns the UX for, exposed here so any Egglet can build on them. They are always present because the Gateway ships them.

SurfaceWhat it does
ctx.feedsAggregated feeds (RSS, social, scraped sites) and their items.
ctx.explorationsHub-and-spoke exploration graphs (the Ponder / Explore domain).
ctx.peopleThe contacts domain — the single write surface for the People tables (entity, profiles, work history, education).
ctx.artifactsLong-lived domain artifacts (code, docs, diagrams).
ctx.agentThe persistent Egg agent’s own state: chat, calendar, personality, memory, workspaces, tools, skills. Distinct from ctx.ai (inference).

Escape hatch

SurfaceWhat it does
ctx.gatewayLow-level authorized fetch against the local Gateway, for first-party Egglets hitting an endpoint not yet wrapped by a typed surface. Same token scoping as every other ctx call. Prefer a typed surface where one exists.

Most surfaces have a corresponding declaration in the manifest’s uses block; the host refuses calls to surfaces the manifest did not declare. ctx.manifest (a read-only view of the Egglet’s own manifest) is always present.

Declaring what you use

Every Egglet’s manifest declares the platform surfaces it uses: which LLM slot, which Gateway services, whether it makes outbound HTTP, whether it sends messages to other Egglets. Those declarations live in a uses block at the top level of the manifest.

This is not a documentation hint. The host checks every ctx.* call at runtime and throws if the manifest did not declare the matching surface. An Egglet that calls ctx.fetch without uses.network.fetch fails on its first call with a clear error naming the field to add.

// Excerpt from a manifest that uses the LLM router and a daemon-driven scheduler.
{
  "id": "myEgglet",
  "version": "0.1.0",
  "label": "My Egglet",
  "route": "/my",
  "entry": "./index.ts",
  "uses": {
    "llm": { "role": "agent-secondary", "capability": "text" },
    "gateway": { "schedules": true, "writes": true }
  }
}

The reason for the rigor is user trust. When someone looks at an Egglet’s card in Settings, they should see a truthful picture of what it does, not a pinky-promise. Making every backing a declared field, then enforcing the declaration where the call happens, means the manifest is something the user (and the platform) can rely on without reading the code.

Full reference for every field in the uses block is on the Manifest page.

Quickstart

The smallest Egglet is a folder with two files. Create them under src/egglets/hello/.

// src/egglets/hello/manifest.json
{
  "id": "hello",
  "version": "0.1.0",
  "label": "Hello",
  "icon": "egg",
  "description": "Demo Egglet with a greeting tool.",
  "route": "/hello",
  "entry": "./index.ts"
}
// src/egglets/hello/index.ts
import { defineEgglet } from "@egg/sdk";

export default defineEgglet({
  async activate(ctx) {
    ctx.log.info("activated v" + ctx.manifest.version);

    ctx.routes.mount(() => import("./HelloPage"));

    ctx.tools.register<{ name?: string }, { greeting: string }>(
      "hello.greet",
      async ({ name } = {}) => ({
        greeting: `Hello, ${name ?? "world"}!`,
      }),
    );
  },
});
// src/egglets/hello/HelloPage.tsx
export default function HelloPage() {
  return <div>Hello from inside Egg.</div>;
}

That is a complete, working Egglet. On the next launch the host discovers manifest.json, calls activate(), mounts the page at /hello, and registers hello.greet as a callable tool. Settings shows the Egglet under the Egglets section, and the route is reachable from the Egg menu.

The example uses no platform backings beyond log, routes, and tools (none of which require a uses declaration). To call the LLM, write to a table, fetch a URL, or send a message to another Egglet, declare the corresponding entry under uses in the manifest first.

Where to go next

The Manifest page is the field-by-field reference, including the full uses block and validation rules. The SDK reference covers every ctx.* surface with signatures and examples. The Database, Integrations, and Lifecycle pages go into specific topics in more depth. On the web covers running a portable Egglet as a standalone web app in any browser and listing it in the public gallery.