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.

The runtime merges every loaded plugin’s configSchema onto a base schema, validates process.env at boot, and exposes the result on ctx.config.
1

Declare the schema with Zod

Prefix every variable with your plugin’s name in SHOUT_SNAKE_CASE to avoid collisions across plugins.
import { z } from '@ixo/oracle-runtime';

const configSchema = z.object({
  WEATHER_DEFAULT_UNITS: z.enum(['celsius', 'fahrenheit']).default('celsius'),
});
Bundled plugins follow the same rule (MEMORY_MCP_URL, SLACK_BOT_OAUTH_TOKEN, …). See memory.plugin.ts for a required-field example.
2

Attach it as configSchema on the plugin class

The composer merges this schema with the base schema and every other loaded plugin’s schema, then validates process.env.
import { OraclePlugin } from '@ixo/oracle-runtime';

export class WeatherPlugin extends OraclePlugin {
  override readonly configSchema = configSchema;
}
Boot fails fast on missing or invalid values: [boot-error] Plugin 'weather' env validation failed for 'WEATHER_DEFAULT_UNITS'. See weather.plugin.ts.
3

Read typed values from ctx.config

ctx.config is typed as MergedConfig (Record<string, unknown>). Parse it through your schema to get a typed view — this can’t fail at runtime because boot already validated.
override getTools(ctx: PluginContext): PluginTool[] {
  const units = configSchema.parse(ctx.config).WEATHER_DEFAULT_UNITS;
  return [buildCurrentWeatherTool(units)];
}
Same on RuntimeContext.config inside getRequestTools and tool handlers.
4

Gate the plugin on env with autoDetect (optional)

Implement autoDetect to make the plugin opt-in. Pair it with autoDetectHint so boot logs explain why it was skipped.
override autoDetect(env: NodeJS.ProcessEnv): boolean {
  return Boolean(env.MEMORY_MCP_URL);
}

override readonly autoDetectHint = 'MEMORY_MCP_URL';
Without autoDetect, a plugin is on by default. See memory.plugin.ts.
5

Force-toggle from your oracle's main.ts

Forks override autoDetect via the features map passed to createOracleApp.
const app = await createOracleApp({
  config,
  features: {
    weather: true,    // force on, skip autoDetect
    slack: false,     // force off
    composio: 'auto', // explicit auto (the default)
  },
});
FeatureToggle is boolean | 'auto'. See plugin-loader.ts.

What to know before shipping

  • Use .default(value) and .coerce.number() freely — env values are strings, so coerce explicitly.
  • Disabling a plugin (via features or autoDetect) automatically removes its env requirements.
  • Two plugins declaring the same env-var name fail boot. Follow the naming convention to avoid this.
  • To read a variable your plugin doesn’t own, declare a separate optional sibling schema and safeParse it — don’t require it through your own configSchema.
  • Required boot-time fields stay in configSchema; per-call settings belong elsewhere (e.g. request headers, manifest defaults).

Enable bundled plugins

Features map, autoDetect, and the bundled set’s defaults.

Environment variables reference

Every base var and per-plugin var.