A plugin system is healthy when “built in” is provenance, not a secret handshake.
1. Motivation
A central branch makes the first provider easy and the fiftieth one political:meta.yaml; a Context installs and inspects those records; typed facades resolve behavior when needed. Built-in and external items share the same descriptor, Registry, resolver, validation, lifecycle, and contract shape.
2. Separate the Extension Concepts
An Extension is one Registry record kind; it is not the Registry itself. Backends, handlers, logical types, strategies, query operations, serializers, and profiles are peer record kinds rather than fields on a giant Extension object.
3. Understand the Built-In Foundation and Roots
Catalog and MetaSchema are fixed workspace-foundation entities. No Extension can replace them.
Capsule is the required Extension root. Toolkit and Prompt are packaged default roots. Agent, Memory, and Database are optional roots that applications enable deliberately. Each Extension declares exact requires identifiers; reopening a workspace recomputes the hard dependency closure from the workspace’s requested roots.
4. Declare a Distributable Module Folder
A minimal external entity Extension can use this layout:source: path targets are relative to the module folder. Keep their imports within the captured root or use stable absolute public APIs.
5. Install, Inspect, Resolve, and Enable
install() captures local executable files into a verified content-addressed artifact and returns an exact receipt. inspect() reads inert record data. enable_extension() resolves the Extension and its declared Entity records through the workspace’s Context before registering canonical classes.
Use modules.uninstall(receipt) only when you intentionally want to remove that installed generation. Uninstalling a module does not delete application workspace data.
6. Attach a Workspace-Bound API
An Extension may attach one domain service throughapi and api_name. The factory receives the workspace, so the service inherits the correct Context, canonical Entity classes, and lifecycle.
heavenbase.executable target in the Extension definition. After enablement, application code uses the attached API, such as ws.notes.list(), while CLI and MCP surfaces remain thin adapters.
Programmatic Extension(...).register(resolver=...) remains useful for local or generated definitions. A published package should prefer one meta.yaml so inspection, installation receipts, compatibility, and artifacts remain explicit.
7. Extend Physical Behavior Through Registered Roles
Advanced authors usehb.ext and owning packages for backend types, handlers, strategies, logical types, query operations, Toolkit families, profiles, serializers, and related Registry-backed roles.
The rule is the same for every open family:
- Publish one canonical record through the target Context’s resolver.
- Keep implementation loading behind the typed facade.
- Declare exact dependencies and compatibility.
- Test built-in/external parity through install, inspect, resolve, use, and uninstall.
8. Inspect Claims Without Overpromising
explain() for that execution decision.
9. Use the Extension Checklist
- Give the module, every record, and every Extension a stable identifier.
- Keep one exact
meta.yamlat the cohesive module root. - Declare dependencies instead of relying on import order.
- Keep path targets inside the captured module root.
- Attach domain behavior through one workspace API when identity or lifecycle is real.
- Namespace MCP tools and scope profiles to the exact tools, entities, Skills, and serializer they need.
- Test a fresh Context restore, inert inspection, activation, ordinary use, and exact-receipt uninstall.
- Treat installed executable source as trusted code.
Summary
- Built-in and external modules use one
meta.yamlfolder protocol. - Registry records are inspected before implementations are imported.
- Workspace Extensions attach domain behavior through explicit roots and dependencies.

