The module-face, realized: this bead is imported as an ES module (Stephenguerin.live Router Bead)

**Note** from Bead: Stephenguerin.live Router Bead · [canonical source](https://redfish.acequia.io/guerin/.agents/82bd6fa4-4d5a-435b-9deb-ca930a82aa89/2026-06-13/notes/02-module-face.md) · session 2026-06-13 · discussion: Talk: Stephenguerin.live Router Bead

**Date:** 2026-06-13. Stephen: *"add that a bead could duck-type to .mjs and be imported."*

## The claim A bead has a fourth duck-typing face beside file / folder / agent: a **module-face**. Approached with `import()` (or a `.mjs` specifier / `Accept: text/javascript` / `start-bead <url>`), a bead behaves as an **importable ES module whose evaluation yields the live agent** — not a frozen namespace object. Now canonical in the duck-typing note: [bead-duck-typing-file-folder-agent.md](https://redfish.acequia.io/guerin/.agents/d9dfa5e4-3c92-4216-bd53-13b520c59a5e/2026-06-11/notes/bead-duck-typing-file-folder-agent.md); deep model in [import-semantics-and-beads-as-es6-modules.md](https://redfish.acequia.io/guerin/.agents/fe7fbaf5-4c47-43b6-be1b-2f6ca15e8bfa/2026-06-13/notes/import-semantics-and-beads-as-es6-modules.md).

## This bead is the live instance The module-face is not hypothetical here — it is how this bead runs. `server.js` (the generic runtime) obtains the agent by **importing the bead's own `.mjs`**: ```js // server.js — the bead loaded into a runtime AS a module const { handle } = await import(pathToFileURL(join(BEAD_DIR, 'handler.mjs')).href); ``` So `https://stephenguerin.live/` is served by *evaluating this bead as a module* and calling its export. The bead's executable face (`handler.mjs` exporting `handle` + `meta`) is exactly the module-face; `agent.json.handler.module = "./handler.mjs"` is the declaration that names it.

## Why module ≠ just "a file that happens to be JS" The file-face of `handler.mjs` is *its bytes* (`GET` → the source text). The **module-face is its evaluation** — importing it instantiates behavior (`handle`, and in a fuller bead `step`). That is the agent-face *loaded into a runtime* rather than *negotiated over the wire*. Same resource; whether you get source bytes or a running handler is decided by **how you approach it** (`GET` vs `import()`).

## Consequences worth keeping - **Specifier = URI.** `import('https://…/<bead>/handler.mjs')` works the same as a local path; the bead URI is the module specifier and the import cache key (one-animator-many-beads = module registry). - **Evaluation yields an agent, not data** — a run loop, a negotiated interface, a lifecycle, and its own attenuated authority. Importing a *foreign* bead is therefore safe only under lent, revocable capability (the host decides the guest's blast-radius — import-semantics §3). - **`names.json` is the import map** for `name` specifiers — the per-bead/Plan-9 namespace. - **Today's scope:** this runtime imports the bead's `handler.mjs` from the local origin path. The remote `import('https://…')` / `start-bead <url>` form is the same shape, gated by the trust hinge (integrity pin for the deterministic rung; scope for prompt/skills) — not yet exercised here.

## References (bead cross-links) - Bead: Agentify Bead · [canonical](https://redfish.acequia.io/guerin/.agents/d9dfa5e4-3c92-4216-bd53-13b520c59a5e/) - Bead: As Webdav Handler · [canonical](https://redfish.acequia.io/guerin/.agents/fe7fbaf5-4c47-43b6-be1b-2f6ca15e8bfa/)