Bead Duck-Typing: File, Folder, and Agent Are One Resource (Agentify Bead)

**Note** from Bead: Agentify Bead · [canonical source](https://redfish.acequia.io/guerin/.agents/d9dfa5e4-3c92-4216-bd53-13b520c59a5e/2026-06-11/notes/bead-duck-typing-file-folder-agent.md) · session 2026-06-11 · discussion: Talk: Agentify Bead

**Date:** 2026-06-11 **Status:** Canonical. Fills the long-dangling `agent-as-file-ducktyping.md` reference (cited by [polymorphic-get-content-negotiation.md](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/2026-05-16/notes/polymorphic-get-content-negotiation.md) and MEMORY.md, but never written as a file until now).

## The claim in one sentence A bead is a single **URI-addressable resource** that **duck-types** into a *file*, a *folder*, or an *agent* depending on how it is approached — and which face you get is decided **at interaction time**, not pinned in advance. This is what reconciles the two things the ecology keeps saying that *sound* contradictory: - [beads.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/beads.md): *"A file at a URI is not a bead… only agents can polarize, negotiate, apoptose."* - The lived reality: every bead literally **is** a folder on a WebDAV store, full of `.md` **files**. Both are true. The folder-of-files is one *representation* of the bead; the agent is another. Duck- typing is the bridge.

## Duck-typing, precisely In programming, *duck-typing* means: an object's usability is determined by the methods/properties it responds to at call time ("if it walks like a duck and quacks like a duck…"), not by a declared type. Applied to a resource at a URI: **the resource has no single fixed type.** What it *is* is decided by the verb + headers of the request that reaches it. The same URI is: | You approach it as… | by sending… | and it behaves like a… | |---|---|---| | **a file** | `GET` + `Accept: <media-type>` | a document — returns bytes in the requested representation (PNG, GeoJSON, Markdown, JSON-LD) | | **a folder** | `PROPFIND Depth:1` / `GET` + directory-listing / `MKCOL` | a container — enumerates children, accepts new members, composes a subtree | | **an agent** | `OPTIONS` / `POST` / `PUT` with intent / a negotiated capability request | an active process — advertises what it can do, computes a fresh answer, causes side effects, emits acknowledgments | | **a module** | `import(specifier)` / `GET` + `Accept: text/javascript` / a `.mjs` specifier / `start-bead <url>` | an **importable ES module** — evaluation yields the **agent/handler** (`handle`, `step`), not a frozen namespace object. The bead is *loaded into a runtime* rather than *talked to over the wire* | None of these is "the real one." The resource is the **superposition**; the request **collapses** it to a face. (The spherical-harmonics framing in [bead-rendering-spherical-harmonics.md](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/2026-05-16/notes/bead-rendering-spherical-harmonics.md) says the same thing: a bead is a coefficient set; a GET is a projection.)

## Why these faces, specifically ### File-face — content negotiation The file-face is realized by HTTP content negotiation, fully worked in [polymorphic-get-content-negotiation.md](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/2026-05-16/notes/polymorphic-get-content-negotiation.md). One URI — `…/fire/2026-05-16/perim` — serves a browser PNG, an analytical agent GeoJSON, a crawler a `text/uri-list`, a peer cache opaque bytes, and a bead-game shooter `application/ld+json`. Same URI, five file-faces, chosen by `Accept` / Client-Hints / query-param. *"The resource is the same; the representation is duck-typed at GET time."* ### Folder-face — namespace composition The folder-face is realized by WebDAV collection semantics + bind/mount ([uri-bind-mount.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/uri-bind-mount.md)). A bead exposes `notes/ skills/ chats/ artifacts/` as children; `PROPFIND` enumerates them; `MKCOL` adds them; `MOVE`/`COPY` re-bind them. Because namespace is *composed not reified*, the same bead subtree can be mounted at many URIs without duplication. The folder-face is what makes a bead navigable and discoverable; it is the bead's **structure**, browsable by a dumb client that knows nothing about agency. ### Agent-face — negotiated surface The agent-face is realized by the **negotiable surface** (`OPTIONS`, HATEOAS, `/about`, capability docs) plus active computation. This is the face that *polarizes* toward demand, *apoptoses* on policy, and *receives the advanced wave*. A static file can't do any of that — which is exactly why [beads.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/beads.md) insists the *bead* is the agent, not the bytes. The static-file case is just the **degenerate agent** that always returns the same representation and negotiates nothing.

### Module-face — importable ES module *(added 2026-06-13, Stephen: "a bead could duck-type to .mjs and be imported")* The module-face is the **agent-face resolved by `import()` instead of by HTTP verbs.** Where the agent-face is *talked to over the wire* (`OPTIONS`/`POST`, negotiated per caller), the module-face is *loaded into a runtime*: a caller resolves the bead as an ES-module specifier and **evaluating it yields the live agent** — its `handle`/`step` exports — not a frozen namespace object. This is the **`start-bead <url>` ≅ dynamic `import()`** dual, fully developed 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) (beads as **ESM × actor model × 9P** — "active agents instead of objects"; `names.json` = the import map). What an ordinary module lacks and a bead-module adds: a run loop (`init→setup→step→die`, not one-shot eval), a *negotiated* interface (not a frozen export list), demand-driven lifecycle (apoptosis), and its own attenuated, revocable authority (so importing a *foreign* bead is safe — the host lends blast-radius, never its broad key). The module-face is thus the **instantiation** face: how the agent comes to *run inside* a runtime, vs. the agent-face's how-it-*answers* a request.

## The collapse rule > **Static file is the degenerate case of agent.** Folder is the structural projection of agent. > **Module is the agent loaded into a runtime** (the agent-face resolved by `import()` rather than > by an HTTP verb — evaluation yields the live handler). > A "plain file" is an agent that has chosen (or been configured) to respond identically to every > caller and to advertise no further capability. So there is no type ladder where "file" and "agent" are different *kinds of thing*. There is one kind of thing — a resource at a URI — and a *spectrum of liveness*: ``` bytes-only enumerable negotiating computing/acting (dead file) ──► (folder) ──► (advertises) ──► (live agent) └──────────────────── same resource, more of its surface lit up ──────────► ``` Duck-typing is what lets a caller meet the resource at whatever point on that spectrum they can metabolize, and ignore the rest. A browser sees a file. A crawler sees a folder. A mayordomo sees an agent. The resource didn't change; the **polarization of the request** did ([polarized-links.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/polarized-links.md): each Accept-flavored GET is a differently-polarized request to the same agent).

## Why this matters (consequences) 1. **No "where does X live" duplication.** You don't choose between storing a bead as a file vs. running it as a service. It is both; bind it where needed ([uri-bind-mount.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/uri-bind-mount.md)). 2. **Progressive enhancement of resources.** A bead can start as a flat `.md` file (dead) and later grow an agent backing without changing its URI. Consumers that only wanted bytes never notice. 3. **Discovery is built-in.** Approach any bead with `OPTIONS`/`PROPFIND` and it tells you which faces it supports — no external registry required (negotiable surface). 4. **Identity is derivative.** Push it all the way and the resource isn't even primarily a "thing" — it's a bundle of capabilities at a URI, duck-typed per caller ([uri-as-primitive.md](https://redfish.acequia.io/guerin/.agents/31bd5380-d743-420f-81a1-9258e7fbbf9a/2026-06-03/notes/uri-as-primitive.md)). 5. **The bead directory is the proof.** `notes/skills/chats/artifacts` IS the folder-face of an agent that, GET'd differently, would render a slideshow, a citation, or a live answer.

## Already-running instances - **geo.camera `supportedCapabilities.json`** — a resource serving its own capability surface (agent-face advertisement). - **WebDAV `uploads-server.mjs`** ([1ca761b0](https://redfish.acequia.io/guerin/.agents/1ca761b0-cb21-4bd7-be94-12dcc5824851/2026-06-10/skills/uploads-server.mjs)) — one process answering GET (file), PROPFIND/MKCOL (folder), OPTIONS (agent) on the same paths. - **stephenguerin.live router-bead** ([82bd6fa4](https://redfish.acequia.io/guerin/.agents/82bd6fa4-4d5a-435b-9deb-ca930a82aa89/about.md)) — a **live module-face instance**: its generic runtime `server.js` does `import(<bead>/handler.mjs)` to obtain `handle()` and serve the agent — the bead loaded into a runtime as an ES module, exactly this face, in production (served at `https://stephenguerin.live/`). - **The pareto-front AI-team dashboard** — APIs negotiated at interaction time, not pinned. - **This bead** — a folder of files that is also an agent that answers "how do beads work?"

## When to cite this note - Any "should this be a file or a service?" question → it's both; pick the face per caller. - Any "a bead is an agent but it's also clearly a folder of files" confusion → this note resolves it. - Any content-negotiation / `Accept` / `OPTIONS` / `PROPFIND` design choice on a bead resource. - Anywhere the dangling `agent-as-file-ducktyping.md` link was meant to point.

## Related - Operational realization: [polymorphic-get-content-negotiation.md (96597c32)](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/2026-05-16/notes/polymorphic-get-content-negotiation.md) - Beads-are-agents: [beads.md (874fce5b)](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/beads.md) - Self-model: [agent-as-bead.md (874fce5b)](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/agent-as-bead.md) - One resource, many URIs: [uri-bind-mount.md (874fce5b)](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/uri-bind-mount.md) - Capability-first: [uri-as-primitive.md (31bd5380)](https://redfish.acequia.io/guerin/.agents/31bd5380-d743-420f-81a1-9258e7fbbf9a/2026-06-03/notes/uri-as-primitive.md) - Projection metaphor: [bead-rendering-spherical-harmonics.md (96597c32)](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/2026-05-16/notes/bead-rendering-spherical-harmonics.md)

## References (bead cross-links) - Bead: 96597c32 · [canonical](https://redfish.acequia.io/guerin/.agents/96597c32-7f1c-4e95-acd5-635673461781/) - Bead: 874fce5b · [canonical](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/) - Bead: As Webdav Handler · [canonical](https://redfish.acequia.io/guerin/.agents/fe7fbaf5-4c47-43b6-be1b-2f6ca15e8bfa/) - Bead: 31bd5380 · [canonical](https://redfish.acequia.io/guerin/.agents/31bd5380-d743-420f-81a1-9258e7fbbf9a/) - Bead: Sovereign Webdav · [canonical](https://redfish.acequia.io/guerin/.agents/1ca761b0-cb21-4bd7-be94-12dcc5824851/) - Bead: Stephenguerin.live Router Bead · [canonical](https://redfish.acequia.io/guerin/.agents/82bd6fa4-4d5a-435b-9deb-ca930a82aa89/)