Auto-Loading Extensions
AgentOS loads extensions from an explicit extensionManifest. There is no hidden “plugin marketplace” behavior in core (no background npm installs, no hot-reload, no implicit caching).
So when we say “auto-loading” in the AgentOS ecosystem, it typically means:
- Automatically build a manifest from whatever curated extension packages are installed.
- Load that manifest during
AgentOS.initialize(), making tool schemas available for tool calling.
Recommended: Build a Curated Manifest
Use @framers/agentos-extensions-registry to build a manifest from installed curated packages. Missing optional dependencies are skipped.
import { AgentOS } from '@framers/agentos';
import { createCuratedManifest } from '@framers/agentos-extensions-registry';
const extensionSecrets = {
'serper.apiKey': process.env.SERPER_API_KEY!,
'giphy.apiKey': process.env.GIPHY_API_KEY!,
};
const manifest = await createCuratedManifest({
tools: 'all',
// Channels can have side effects (connect/poll/webhook). Enable explicitly.
channels: 'none',
secrets: extensionSecrets,
});
const agentos = new AgentOS();
await agentos.initialize({
extensionManifest: manifest,
extensionSecrets,
// ...other required AgentOS config
});
Load Flow
What "Lazy Loading" Means (Today)
You'll see "lazy" used in a few different ways:
- Lazy optional dependencies: the curated registry uses dynamic
import()to include only installed extension packages. - Lazy heavy deps inside tools: a tool's
execute()can dynamicallyimport()heavy libraries on first call. - Lazy heavy deps shared across descriptors:
SharedServiceRegistry.getOrCreate()registers a factory at activation and only constructs the resource on the first call that needs it. Subsequent callers (other tools, the streaming guardrail) share the same instance. - Lazy skills:
SkillRegistryfrom@framers/agentos/skillsexposesskills_list/skills_readtools so the model can fetchSKILL.mdcontent on demand. Curated skill content ships in@framers/agentos-skills.
What AgentOS does not do by default: wait for the model to request a tool and then reveal its schema. Tool calling requires schemas up front, so the host decides which tools to expose for a given session/turn.
End-to-End Walkthrough: A Lazy-Loaded Guardrail Pack
Walking through what actually happens when a host installs the PII redaction guardrail extension and runs a request. This is the same shape every guardrail pack follows.
Step 1. Install only what you need
npm install @framers/agentos @framers/agentos-extensions-registry @framers/agentos-ext-pii-redaction
Nothing else from the 100+ extension catalog enters node_modules. The registry is a small SDK; the catalog of metadata it carries is independent of which packages are installed.
Step 2. Build the manifest
import { AgentOS } from '@framers/agentos';
import { createCuratedManifest } from '@framers/agentos-extensions-registry';
const manifest = await createCuratedManifest({
tools: 'all',
channels: 'none',
secrets: {
// Optional: unlocks the LLM-judge tier in pii-redaction.
'anthropic.apiKey': process.env.ANTHROPIC_API_KEY,
},
});
// → manifest.packs.length === 1 (only the installed pii-redaction pack).
createCuratedManifest() calls import.meta.resolve() on every catalog entry. The 99 entries that are not installed get dropped with no error. The one installed pack lands in manifest.packs.
Step 3. Activate the pack
const agentos = new AgentOS();
await agentos.initialize({ extensionManifest: manifest });
ExtensionManager.loadManifest() runs pack.onActivate(ctx), which registers a pii:ner-model factory in ctx.services (SharedServiceRegistry). The 110MB BERT NER model file does not enter the module graph yet. The factory is the only thing registered.
Step 4. Register descriptors
The pack emits three descriptors:
pii_scan(kind:tool)pii_redact(kind:tool)- The PII redaction guardrail itself (kind:
guardrail, withconfig.canSanitize = trueandconfig.evaluateStreamingChunks = true)
ExtensionManager checks requiredSecrets per descriptor before activating. If anthropic.apiKey was not provided, the optional LLM-judge resolver descriptor is skipped, and the rest of the pack activates.
Step 5. First request loads the model
A user message hits the input pipeline. The two-phase guardrail dispatcher runs:
- Phase 1 (sequential sanitizers). The PII guardrail's
evaluateInput()fires. On this first call, the NER pipeline reaches intoservices.getOrCreate('pii:ner-model', ...)and the model loads. The guardrail returns aSANITIZEresult with redacted text. - Phase 2 (parallel classifiers). Any remaining classifier guardrails run concurrently against the sanitized text via
Promise.allSettled, with worst-action aggregation (BLOCK > FLAG > ALLOW).
Step 6. Streaming output reuses the same model
As the LLM streams tokens, each TEXT_DELTA chunk passes through the guardrail's evaluateOutput(). The NER model is already loaded and cached in SharedServiceRegistry, so chunk evaluation is fast. SANITIZE results returned in Phase 1 chain deterministically; Phase 2 SANITIZE is downgraded to FLAG to keep output deterministic when classifiers run in parallel.
Step 7. Tear-down releases everything
AgentOS.shutdown() calls pack.onDeactivate(ctx) in reverse order. SharedServiceRegistry releases the NER model. The kind-specific registries clear. Future processes start cold.
What changes for the other guardrail packs
The pattern is identical. Only the heavy resource changes:
| Pack | Heavy resource | Lazy via |
|---|---|---|
agentos-ext-pii-redaction | BERT NER model (~110MB) | services.getOrCreate('pii:ner-model', ...) |
agentos-ext-ml-classifiers | ONNX BERT classifiers (toxicity, injection, NSFW) | services.getOrCreate('ml:classifier-orchestrator', ...) |
agentos-ext-grounding-guard | NLI entailment pipeline | services.getOrCreate('grounding:nli-pipeline', ...) |
agentos-ext-topicality | Embedding model + drift tracker | services.getOrCreate('topicality:embedder', ...) |
agentos-ext-code-safety | None (regex-only) | No lazy load needed |
For the dispatcher mechanics and configuration flags, see Guardrails. For the kind-specific registry internals, see Extension Loading.
What Is Not Automatic (Yet)
- No core auto-install (
npm install) of missing extensions. - No core “extension marketplace UI”.
- No hot reload of extension packs.
There is an ExtensionLoader utility in @framers/agentos that experiments with registry scanning and auto-install, but it is not wired into AgentOS.initialize() and should be treated as experimental.