Skip to main content

Turn on LangSmith in one block

LangChain auto-wires tracing when these env vars are present in process.env — the runtime never reads them, only declares them in the base env schema so they show up in qiforge-cli env output.
All four LANGSMITH_* vars are optional() in the base env schema — boot never fails when they’re absent. “Required” above means “required for tracing to work,” not a boot-time requirement.
No code changes needed. Set the vars and every LLM call, tool invocation, and middleware hook produces a span in the LangSmith UI. Unset them to turn it off.

What QiForge gives you out of the box

Three signals — that’s the whole surface. Bring your own log aggregator and metrics.
  1. LangSmith traces — env-driven, covered above.
  2. Plugin status eventsapp.onPluginStatusChange(handler).
  3. Plugin-scoped loggerctx.logger (boot) and rtCtx.logger (per-request).

Subscribe to plugin status events

1

Register a handler after createOracleApp returns

Live example: apps/qiforge-example/src/main.ts.
2

Listen for the matrix plugin transitions specifically

The plugin that reliably emits transitions is matrix — it starts pending at boot and flips to either loaded or failed once Matrix init completes in the background.
Use this to gate operations on Matrix being up, or to alert when it fails.
The event shape:

Capture background errors with onError

source is a short label like 'matrix-init'. Use this for background failures (Matrix sync errors, key setup failures). Boot-time errors (env validation, manifest validation, dependency cycles) throw from createOracleApp itself — your try/catch around the call sees them.

Log the boot resolution snapshot

app.plugins.status() returns the loader’s resolution snapshot — log it once at boot so operators see what came up.
Shape of the snapshot — the PluginStatusReport defined in packages/oracle-runtime/src/bootstrap/create-oracle-app.ts:
The loader tracks an internal cause (feature_false / auto_detect_missing / cascaded) for each excluded plugin, but the public app.plugins.status() report drops it — excluded items are { plugin, reason } only.

Use the plugin-scoped logger

Every PluginContext and RuntimeContext carries a logger field auto-prefixed with the plugin’s name — see Logger in types.ts.
The Logger interface: Use NestJS’s default Logger format in development (pnpm dev shows it nicely); pipe to your aggregator in production. Override the global logger with createOracleApp({ logger }) if you want a custom format — see createOracleApp reference.

UI-facing tool-call events

For showing the user what the agent did, the runtime emits typed events via rtCtx.emit. The bundled clients (Portal, Slack, Matrix) consume these and render the right UI — you only emit them yourself when writing a custom client.
The seven event types are defined on RuntimeContext.emit in types.ts.

Deployment

Logs and probes in production.

Add a middleware

Custom observability via plugin middleware hooks.

Runtime context

Full rtCtx.emit and rtCtx.logger surface.

Environment variables

Every env var the runtime declares.