Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ixo.world/llms.txt

Use this file to discover all available pages before exploring further.

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'.
import { createOracleApp } from '@ixo/oracle-runtime';
import { config } from './config.js';

const app = await createOracleApp({
  config,
  features: {
    composio: true,       // force on (set COMPOSIO_API_KEY)
    slack: false,         // force off
    firecrawl: 'auto',    // same as omitting — runs autoDetect
  },
  plugins: [],            // your own plugins go here
});

await app.listen();
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]:
type FeatureToggle = boolean | 'auto';

features?: Partial<Record<string, FeatureToggle>>;
ValueBehaviour
trueForce the plugin on. If its autoDetect(env) returns false, boot fails with boot.plugin.env_missing.
falseForce the plugin off. Skip autoDetect entirely.
'auto' (or omitted)Run plugin.autoDetect(env). Include if true, exclude otherwise.
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'.
PluginAuto-detects whenNotes
memoryMEMORY_MCP_URL and MEMORY_ENGINE_URL setVisibility always
portalalways onVisibility on-demand
firecrawlFIRECRAWL_MCP_URL setVisibility on-demand
domain-indexeralways onVisibility always
composioCOMPOSIO_API_KEY setVisibility on-demand
sandboxSANDBOX_MCP_URL setVisibility always
skillsalways onVisibility always; depends on sandbox
editoralways onNeeds matrixClient — instantiate explicitly
aguialways onVisibility on-demand
slackSLACK_BOT_OAUTH_TOKEN setVisibility silent (transport)
tasksREDIS_URL setStub
creditsalways onVisibility silent; pass redis for production
callsalways onStub
user-preferencesalways onVisibility always
matrix-group-chatsalways onVisibility on-demand; gating middleware + tools fire only in Matrix group rooms (memberCount > 2)
Full per-plugin env vars: plugin catalog and environment variables reference.

Opt out of a plugin

1

Set the feature flag to false

const app = await createOracleApp({
  config,
  features: {
    composio: false,
    'domain-indexer': 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

const app = await createOracleApp({
  config,
  features: {
    composio: 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:
boot.plugin.env_missing: plugin 'composio' enabled via features but precondition failed (COMPOSIO_API_KEY).
Set the required env or disable: features: { composio: false }
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:
import { createOracleApp, EditorPlugin, CreditsPlugin } from '@ixo/oracle-runtime';
import * as sdk from 'matrix-js-sdk';
import Redis from 'ioredis';

const matrixClient = sdk.createClient({
  baseUrl: process.env.MATRIX_BASE_URL!,
  userId: process.env.MATRIX_ORACLE_ADMIN_USER_ID!,
  accessToken: process.env.MATRIX_ORACLE_ADMIN_ACCESS_TOKEN!,
});

const redis = process.env.REDIS_URL ? new Redis(process.env.REDIS_URL) : null;

const app = await createOracleApp({
  config,
  plugins: [
    new EditorPlugin({ matrixClient }),
    ...(redis ? [new CreditsPlugin({ redis, network: 'devnet' })] : []),
  ],
});
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.

Inspect what loaded

1

Read app.plugins.status() after boot

const status = app.plugins.status();
// {
//   loaded: ['memory', 'domain-indexer', 'editor', 'user-preferences', 'weather'],
//   excluded: [
//     { plugin: 'composio', reason: 'auto-detect precondition not met (COMPOSIO_API_KEY)', cause: 'auto_detect_missing' },
//     { plugin: 'slack',    reason: 'feature flag set to false',                              cause: 'feature_false' },
//   ],
//   softDepGaps: [],
// }
cause is one of 'feature_false', 'auto_detect_missing', 'cascaded'. Surface this in your boot logs so operators see what came up.
2

Or use the CLI

qiforge inspect
Same data, formatted for the terminal. See the CLI reference.

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.