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.
Boot errors
Every boot error names the offending plugin and a remediation hint. They print to stderr via the configured logger, prefixed with[boot-error].
Missing required env var
configSchema requires a variable that isn’t in process.env.
Fix:
- Set the variable in
.env. - Or opt the plugin out:
features: { memory: false }(only if you don’t need its functionality). - Or if the plugin has an
autoDetect, make sure the detection var is set so the plugin opts in only when ready.
LLM provider key missing
ORACLE_ENTITY_DID empty
ORACLE_ENTITY_DID=did:ixo:entity:... in .env. Run qiforge-cli create-entity if you don’t have one.
Hard dependency missing
dependsOn lists another plugin that isn’t loaded.
Fix: Set the required env var for the dependency, or disable the dependent plugin via features.
Dependency cycle
dependsOn are not allowed.
Tool name collision
name. Flat namespace.
Fix: Rename one. Convention is to prefix tool names with a domain hint (slack_send_message).
Shared-state key collision
getSharedState() return.
Manifest validation failed
summary is non-empty, whenToUse has entries when visibility isn’t silent, and every examples[].tool matches a registered tool.
Matrix issues
Matrix init fails
- Check
MATRIX_BASE_URL,MATRIX_ORACLE_ADMIN_USER_ID,MATRIX_ORACLE_ADMIN_PASSWORD,MATRIX_ORACLE_ADMIN_ACCESS_TOKEN. - Run
qiforge-cli create-entityto re-provision if the credentials are stale.
/health, /docs, plugin and host exclusions) stay reachable.
Boot warns: UCAN signing key not loaded
Boot warns: No P-256 encryption key found
qiforge-cli setup-encryption-key. Until then, rtCtx.secrets.getValues() returns nothing — acceptable degraded mode, but plugins that depend on user secrets won’t work.
Lost Matrix store after restart
Symptoms: Boot is slow; old threads aren’t visible; encrypted messages can’t be decrypted. Cause: The Matrix store directory wasn’t persisted across restarts. Fix: Mount a volume atMATRIX_STORE_PATH (and SQLITE_DATABASE_PATH). See Deployment.
Plugin loading
A plugin I expected isn’t loaded
Check the boot log:autoDetectHint — the env var that, when set, would opt the plugin in.
Fix:
- Set the var.
- Or force the plugin on via
features: { composio: true }(you’ll then need to provide whatever vars itsconfigSchemarequires).
A plugin loaded that I didn’t want
Two reasons it might load:- It has no
autoDetectand is on by default. Disable viafeatures: { name: false }. - Its
autoDetectreturnedtruebecause the relevant env var is set. Either unset the var or force off viafeatures.
The agent doesn’t call my tool
Most common causes:- Plugin is
on-demandbut hasn’t been loaded by the agent in this thread. The agent has to calllist_capabilitiesandload_capabilityfirst. Either:- Promote to
visibility: 'always'(costs Tier-1 tokens — only if the agent needs it most turns). - Improve the manifest’s
whenToUseso the agent picks it up faster.
- Promote to
- Manifest
whenToUseis too vague. Add specific trigger phrases. - Tool description doesn’t match the user’s intent. The agent reads the description verbatim — write it like a docstring for the LLM.
- Tool isn’t in the bound list. Check
app.plugins.status().loadedto confirm the plugin is loaded. Ifon-demand, checkstate.loadedPlugins.
Soft-dep gap warning at boot
softDependsOn is missing. This is informational — the plugin will branch on availablePlugins.has('memory') and degrade gracefully. If you want the full behaviour, also load the missing plugin.
Auth
Every protected request returns 401
Likely causes:- Matrix init still pending. The runtime needs Matrix up to validate UCANs. Watch for
[plugin] matrix pending → loadedbefore retrying. - Signing mnemonic not loaded (see Matrix issues above). Auth middleware can’t mint downstream invocations.
- UCAN delegation expired or malformed. Check the
x-ucan-delegationheader. x-diddoesn’t match the delegation. The middleware verifies the audience.
My webhook hits 401
Plugin and host webhooks need to be opted out ofAuthHeaderMiddleware:
- Plugin-side:
getAuthExcludedRoutes()returns[{ path: 'my-route', method: RequestMethod.POST }]. - Host-side: pass
authExcludedRoutes: [{ path: '...', method: ... }]tocreateOracleApp.
path is the full path the controller mounts at (webhooks/incoming, not incoming). Leading slash optional.
Runtime errors
OracleApp.listen called twice.
You called app.listen() more than once. The framework allows it only once — after that, the app’s listening state is fixed.
setFileProcessingProvider not configured
This is wired by createOracleApp itself before NestJS boots — you shouldn’t see it. If you do, you’re using internal modules in an unusual order. Stick to createOracleApp.
Concurrent model-timing middleware logs are interleaved
If you wrote a middleware with closure-scoped timing state, concurrent LLM calls share the same closure. For accurate per-call timing, push start times onto a stack keyed byrunId (from the runtime), or use the standard tracing path.
When in doubt
- Check
app.plugins.status()—loaded,excluded(with reason),softDepGaps. - Check the Swagger UI at
/docs— the live route list. - Run
qiforge inspect(once TASK-33 ships) for a structured registry dump. - Open the LangSmith trace for the failing turn.
Where to read next
Environment variables
What needs to be set for each plugin.
Plugin catalog
Default state, dependencies, env vars per plugin.
Deployment
Volume layout, probes, signal handling.