openclaw - 💡(How to fix) Fix [Bug]: Custom provider API keys fail with 'No API key for provider' after pi-ai 0.63+ [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#61429Fetched 2026-04-08 02:58:46
View on GitHub
Comments
1
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
closed ×1commented ×1

Custom providers configured in models.json with an apiKey field fail with No API key for provider: <name> at stream time. The key is correctly loaded into authStorage and modelRegistry, but never reaches streamSimpleOpenAICompletions. This affects all provider names not in pi-ai's built-in getEnvApiKey mapping (e.g. any user-defined OpenAI-compatible proxy).

Worked in versions using @mariozechner/pi-ai <= 0.55.x. Broke starting from 0.63.x after upstream pi-mono commit d93cbf8c removed the global apiKeys Map fallback.

Error Message

Diagnostic logging added to auth resolution chain confirms key is present at every layer:

[models-config-normalize] normalizeProviders: key=my-proxy hasApiKey=true apiKeyType=string modelsCount=7 [model-auth] resolveApiKeyForProvider: provider=my-proxy cfgDefined=true customKey=source=models.json,len=51 [auth-controller] applyApiKeyInfo: provider=my-proxy hasApiKey=true mode=api-key source=models.json keyLen=51 [auth-controller] setRuntimeApiKey: provider=my-proxy keyLen=51 [diag-attempt] authStorage.getApiKey=len=51 hasAuth=true registry.getApiKeyAndHeaders={ok:true,hasApiKey:true,apiKeyLen:51}

Yet pi-ai's streamSimpleOpenAICompletions throws:

Error: No API key for provider: my-proxy

Root Cause

The issue affects any provider name not in pi-ai's getEnvApiKey mapping. Built-in providers (anthropic, openai, google, groq, etc.) are unaffected because they fall back to environment variables. Custom providers rely solely on options.apiKey being passed through, which broke when pi-mono removed the global apiKeys Map in d93cbf8c.

Fix Action

Fix / Workaround

Workaround: After createAgentSession returns, inject a getApiKey callback on the Agent instance:

const agent = (session as any).agent;
if (agent && !agent.getApiKey) {
  agent.getApiKey = (provider: string) => authStorage.getApiKey(provider);
}

Code Example

{
  "models": {
    "providers": {
      "my-proxy": {
        "baseUrl": "http://my-proxy/v1",
        "apiKey": "sk-my-key",
        "api": "openai-completions",
        "models": [{ "id": "my-model", "name": "my-model" }]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": { "primary": "my-proxy/my-model" }
    }
  }
}

---

# Diagnostic logging added to auth resolution chain confirms key is present at every layer:

[models-config-normalize] normalizeProviders: key=my-proxy hasApiKey=true apiKeyType=string modelsCount=7
[model-auth] resolveApiKeyForProvider: provider=my-proxy cfgDefined=true customKey=source=models.json,len=51
[auth-controller] applyApiKeyInfo: provider=my-proxy hasApiKey=true mode=api-key source=models.json keyLen=51
[auth-controller] setRuntimeApiKey: provider=my-proxy keyLen=51
[diag-attempt] authStorage.getApiKey=len=51 hasAuth=true registry.getApiKeyAndHeaders={ok:true,hasApiKey:true,apiKeyLen:51}

# Yet pi-ai's streamSimpleOpenAICompletions throws:
Error: No API key for provider: my-proxy

---

const agent = (session as any).agent;
if (agent && !agent.getApiKey) {
  agent.getApiKey = (provider: string) => authStorage.getApiKey(provider);
}

---

agent = new Agent({
  ...
  getApiKey: (provider) => authStorage.getApiKey(provider),
});
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Custom providers configured in models.json with an apiKey field fail with No API key for provider: <name> at stream time. The key is correctly loaded into authStorage and modelRegistry, but never reaches streamSimpleOpenAICompletions. This affects all provider names not in pi-ai's built-in getEnvApiKey mapping (e.g. any user-defined OpenAI-compatible proxy).

Worked in versions using @mariozechner/pi-ai <= 0.55.x. Broke starting from 0.63.x after upstream pi-mono commit d93cbf8c removed the global apiKeys Map fallback.

Steps to reproduce

  1. Configure a custom provider in openclaw.json:
{
  "models": {
    "providers": {
      "my-proxy": {
        "baseUrl": "http://my-proxy/v1",
        "apiKey": "sk-my-key",
        "api": "openai-completions",
        "models": [{ "id": "my-model", "name": "my-model" }]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": { "primary": "my-proxy/my-model" }
    }
  }
}
  1. Start the gateway, send any message
  2. Observe: Error: No API key for provider: my-proxy with input:0, output:0

Expected behavior

Custom provider API keys configured in models.providers.<name>.apiKey should be passed through to the pi-ai stream function, as they were in versions using pi-ai <= 0.55.x.

Actual behavior

Every request to the custom provider fails immediately with No API key for provider: my-proxy. Diagnostic logging confirms the key is present in authStorage.runtimeOverrides and modelRegistry.getApiKeyAndHeaders() returns {ok: true, apiKey: <valid>}, but streamSimpleOpenAICompletions receives options.apiKey = undefined.

OpenClaw version

2026.4.2

Operating system

Linux (Node 22/24)

Install method

pnpm dev / docker

Model

my-proxy/my-model (any custom provider name not in pi-ai's built-in env var list)

Provider / routing chain

openclaw gateway -> custom OpenAI-compatible endpoint

Additional provider/model setup details

The issue affects any provider name not in pi-ai's getEnvApiKey mapping. Built-in providers (anthropic, openai, google, groq, etc.) are unaffected because they fall back to environment variables. Custom providers rely solely on options.apiKey being passed through, which broke when pi-mono removed the global apiKeys Map in d93cbf8c.

Upstream issue filed: https://github.com/badlogic/pi-mono/issues/2847 (auto-closed during OSS weekend, reopen after April 13)

Logs, screenshots, and evidence

# Diagnostic logging added to auth resolution chain confirms key is present at every layer:

[models-config-normalize] normalizeProviders: key=my-proxy hasApiKey=true apiKeyType=string modelsCount=7
[model-auth] resolveApiKeyForProvider: provider=my-proxy cfgDefined=true customKey=source=models.json,len=51
[auth-controller] applyApiKeyInfo: provider=my-proxy hasApiKey=true mode=api-key source=models.json keyLen=51
[auth-controller] setRuntimeApiKey: provider=my-proxy keyLen=51
[diag-attempt] authStorage.getApiKey=len=51 hasAuth=true registry.getApiKeyAndHeaders={ok:true,hasApiKey:true,apiKeyLen:51}

# Yet pi-ai's streamSimpleOpenAICompletions throws:
Error: No API key for provider: my-proxy

Impact and severity

Affected: All users with custom provider configurations (OpenAI-compatible proxies, self-hosted models, corporate API gateways) Severity: High (completely blocks all LLM calls for affected providers) Frequency: 100% — every request fails Consequence: Custom provider setups are non-functional after upgrading to versions using pi-ai >= 0.63

Additional information

Root cause in upstream pi-mono: createAgentSession in packages/coding-agent/src/core/sdk.ts creates the Agent without passing a getApiKey callback. Before d93cbf8c, the global apiKeys Map in stream.ts served as fallback inside streamSimple. After removal, custom providers have no path to deliver their API key to the stream function.

Workaround: After createAgentSession returns, inject a getApiKey callback on the Agent instance:

const agent = (session as any).agent;
if (agent && !agent.getApiKey) {
  agent.getApiKey = (provider: string) => authStorage.getApiKey(provider);
}

Suggested upstream fix (one line in pi-mono sdk.ts):

agent = new Agent({
  ...
  getApiKey: (provider) => authStorage.getApiKey(provider),
});

extent analysis

TL;DR

To fix the issue, inject a getApiKey callback on the Agent instance after createAgentSession returns, allowing custom providers to deliver their API key to the stream function.

Guidance

  • Identify the createAgentSession function in your code and modify it to include the getApiKey callback as suggested in the workaround.
  • Verify that the authStorage.getApiKey function is correctly retrieving the API key for the custom provider.
  • Test the workaround by sending a message to the gateway and checking that the custom provider API key is being passed through to the streamSimpleOpenAICompletions function.
  • Consider upgrading to a future version of pi-ai that includes the suggested upstream fix, if available.

Example

const agent = (session as any).agent;
if (agent && !agent.getApiKey) {
  agent.getApiKey = (provider: string) => authStorage.getApiKey(provider);
}

Notes

The provided workaround should resolve the issue for custom providers, but it may not be a permanent solution. The suggested upstream fix in pi-mono would be a more robust solution, but it requires an update to the pi-ai library.

Recommendation

Apply the workaround by injecting the getApiKey callback on the Agent instance, as it provides a functional solution to the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Custom provider API keys configured in models.providers.<name>.apiKey should be passed through to the pi-ai stream function, as they were in versions using pi-ai <= 0.55.x.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING