Skip to main content

Copy-paste recipe

The whole API is a features map handed to createOracleApp. Each key is a bundled plugin name, each value is true / false / 'auto'.
That’s the whole surface. The runtime pre-loads every bundled plugin instance from BUNDLED_PLUGINS; features only controls which ones survive resolution. Reference oracle: apps/qiforge-example/src/main.ts.

How resolution works

1

The runtime starts with the bundled list

BUNDLED_PLUGINS is a fixed 15-plugin tuple — memory, portal, firecrawl, domain-indexer, composio, sandbox, skills, editor, agui, slack, tasks, credits, calls, user-preferences, matrix-group-chats.You do not import or instantiate the plugins you want at defaults — they are already there.
2

Each plugin gets a feature decision

For every bundled plugin, resolvePlugins reads features[plugin.name]:
3

Your own plugins are added next

Plugins from the plugins: [] array are always loaded — they’re not gated by features. If a name collides with a bundled plugin, your instance wins (the loader dedupes by name).
4

Hard-dep cascades resolve transitively

If a loaded plugin has dependsOn: ['removed-plugin'] and that dep ended up excluded, the dependent cascades off too. Soft deps (softDependsOn) only log a warning.

What every bundled plugin does by default

Each plugin’s autoDetect predicate decides whether to opt in when you leave it on 'auto'. Full per-plugin env vars: plugin catalog and environment variables reference.

Opt out of a plugin

1

Set the feature flag to false

The plugin is dropped before autoDetect runs. Its configSchema is also removed from the merged env schema, so its env vars become optional.
2

Check for dependents

If another loaded plugin lists the disabled plugin in its dependsOn, boot fails with a boot.plugin.dep_missing error naming both. Disable the dependent too, or keep the dependency loaded.

Force a plugin on

1

Set the feature flag to true

The plugin loads even if autoDetect would skip it.
2

Set every env var the plugin needs

With features: { composio: true } and no COMPOSIO_API_KEY, the runtime throws at boot:
See the plugin’s page in the plugin catalog for its full env requirements.

Plugins that need constructor args

Two bundled plugins take a live runtime object you provide — instantiate explicitly and pass them via plugins:
Live example: apps/qiforge-example/src/main.ts.
The bundled editorPlugin and creditsPlugin instances boot in stub form (for testing). For production behaviour, instantiate them yourself and pass the live objects in.

Retune a bundled plugin’s manifest

features decides whether a bundled plugin loads. To change how it’s advertised — most usefully its visibility tier, but also summary, tags, or whenToUse — use manifestOverrides instead of forking the plugin. The override is shallow-merged onto the plugin’s own manifest at boot, validated like any authored manifest, and seen by every downstream reader (Tier-1 prompt, list_capabilities / load_capability, visibility index).
Override keys that don’t match a loaded plugin are logged (boot.plugin.manifest_override_unknown) and ignored — so disabling a plugin via features and leaving its override entry behind is safe.

Inspect what loaded

1

Read app.plugins.status() after boot

Each excluded entry is { plugin, reason } — surface the reason in your boot logs so operators see why a plugin came up missing. (softDepGaps entries are { plugin, missing }.)

Plugin catalog

Every bundled plugin in detail.

Environment variables

Core vars plus per-plugin vars.

createOracleApp reference

Every option, exhaustively.

Write a plugin

Build your own next to the bundled set.