Description
Cron jobs assigned to agents using custom Ollama providers (configured via models.providers with "api": "ollama") fail with:
No API provider registered for api: ollama
The error originates from @mariozechner/pi-ai's resolveApiProvider() in stream.js, which checks the apiProviderRegistry for a registered ollama API handler.
Root Cause
The ollama API provider is registered lazily via ensureCustomApiRegistered() → registerProviderStreamForModel() → resolveProviderStreamFn(). This registration only happens during model preparation (prepareModelForSimpleCompletion).
In the cron execution path (src/cron/isolated-agent/run.ts), the model is resolved via resolveCronModelSelection() and passed directly to runEmbeddedPiAgent() — without calling the model preparation step that triggers lazy registration. The embedded agent then calls pi-ai's stream(), which throws because the ollama API was never registered.
Built-in providers (Anthropic, OpenAI, Google, etc.) work fine because they are registered eagerly at module load via registerBuiltInApiProviders() in pi-ai/dist/providers/register-builtins.js.
Reproduction
- Configure a custom Ollama provider:
"models": {
"providers": {
"ollama-spark": {
"baseUrl": "http://10.x.x.x:11434",
"api": "ollama",
"models": [{ "id": "nemotron-3-super:120b", "name": "Nemotron" }]
}
}
}
- Set an agent's primary model to
ollama-spark/nemotron-3-super:120b
- Create a cron job assigned to that agent with
sessionTarget: "isolated"
- Run the cron job:
openclaw cron run <id>
- Result:
No API provider registered for api: ollama
Interactive sessions with the same agent and model work fine.
Additional Issue
Even when payload.model is explicitly set on the cron job (via --model), the agent's config-level model (agents.list.<agent>.model.primary) still takes precedence in the embedded agent bootstrap, causing LiveSessionModelSwitchError if they differ. The cron --model override should be authoritative.
Workaround
Reconfigure the custom Ollama provider to use "api": "openai-completions" with "baseUrl": "http://host:11434/v1" (Ollama's OpenAI-compatible endpoint). This uses a built-in transport that is registered eagerly and works in cron context.
Suggested Fix
Either:
- Call
registerProviderStreamForModel() for all configured custom providers during gateway startup (before cron starts)
- Add
ollama to the built-in provider registry in pi-ai
- Ensure the cron execution path calls the model preparation step before invoking the embedded agent
Environment
- OpenClaw version: 2026.3.28 (stable)
- OS: macOS 26.3.1 (arm64)
- Node: 22.22.1
Description
Cron jobs assigned to agents using custom Ollama providers (configured via
models.providerswith"api": "ollama") fail with:The error originates from
@mariozechner/pi-ai'sresolveApiProvider()instream.js, which checks theapiProviderRegistryfor a registeredollamaAPI handler.Root Cause
The
ollamaAPI provider is registered lazily viaensureCustomApiRegistered()→registerProviderStreamForModel()→resolveProviderStreamFn(). This registration only happens during model preparation (prepareModelForSimpleCompletion).In the cron execution path (
src/cron/isolated-agent/run.ts), the model is resolved viaresolveCronModelSelection()and passed directly torunEmbeddedPiAgent()— without calling the model preparation step that triggers lazy registration. The embedded agent then callspi-ai'sstream(), which throws because theollamaAPI was never registered.Built-in providers (Anthropic, OpenAI, Google, etc.) work fine because they are registered eagerly at module load via
registerBuiltInApiProviders()inpi-ai/dist/providers/register-builtins.js.Reproduction
ollama-spark/nemotron-3-super:120bsessionTarget: "isolated"openclaw cron run <id>No API provider registered for api: ollamaInteractive sessions with the same agent and model work fine.
Additional Issue
Even when
payload.modelis explicitly set on the cron job (via--model), the agent's config-level model (agents.list.<agent>.model.primary) still takes precedence in the embedded agent bootstrap, causingLiveSessionModelSwitchErrorif they differ. The cron--modeloverride should be authoritative.Workaround
Reconfigure the custom Ollama provider to use
"api": "openai-completions"with"baseUrl": "http://host:11434/v1"(Ollama's OpenAI-compatible endpoint). This uses a built-in transport that is registered eagerly and works in cron context.Suggested Fix
Either:
registerProviderStreamForModel()for all configured custom providers during gateway startup (before cron starts)ollamato the built-in provider registry inpi-aiEnvironment