Auth Profiles Not Distributed to Non-Default Agents During Onboard
The `openclaw onboard` command writes authentication credentials only to the default agent directory, leaving all other configured agents without valid auth tokens and causing silent fallback to free models.
π Symptoms
Direct Observation
When openclaw onboard completes, auth tokens are written to only one directory:
bash $ ls ~/.openclaw/agents/*/agent/auth-profiles.json /home/user/.openclaw/agents/main/agent/auth-profiles.json # exists with valid tokenRef /home/user/.openclaw/agents/chief/agent/auth-profiles.json # MISSING or stale /home/user/.openclaw/agents/developer/agent/auth-profiles.json # MISSING or stale /home/user/.openclaw/agents/qa/agent/auth-profiles.json # MISSING or stale /home/user/.openclaw/agents/secretary/agent/auth-profiles.json # MISSING or stale /home/user/.openclaw/agents/lawyer/agent/auth-profiles.json # MISSING or stale /home/user/.openclaw/agents/writer/agent/auth-profiles.json # MISSING (uses free model) /home/user/.openclaw/agents/experimenter/agent/auth-profiles.json # MISSING or stale
Behavioral Manifestation
Non-default agents silently fall back to free/fallback models without warning:
bash $ openclaw run –agent developer “explain quantum entanglement”
Actual: Routes to GLM 4.5 Air (free fallback), no error shown
Expected: Uses claude-sonnet-4-6 with Anthropic auth
$ cat ~/.openclaw/agents/developer/logs/gateway.log [2026-03-08T14:32:11Z] WARN: No valid auth-profiles.json found for agent ‘developer’, using free fallback model ‘openrouter/z-ai/glm-4.5-air:free’
Exit Code Behavior
Onboard completes successfully (exit code 0) even when other agents lack auth:
bash $ openclaw onboard β Authenticated with Anthropic (setup-token) β Token written to agents/main/agent/auth-profiles.json β Onboarding complete
$ echo $? 0
Agents attempting to use paid models receive no immediate error:
bash $ openclaw run –agent developer “test” 2>&1
Returns results from fallback model, silently
π§ Root Cause
Code Path Analysis
The onboard command iterates over agents.list in openclaw.json but only writes auth to the path derived from the default agent ID (main), not from each agent’s actual id:
javascript // Source: src/commands/onboard.ts (approximate logic) async function writeAuthProfiles(agents: Agent[], tokenRef: string) { for (const agent of agents) { // BUG: Always uses ‘main’ instead of agent.id const authPath = path.join( process.env.OPENCLAW_HOME || ‘~/.openclaw’, ‘agents’, ‘main’, // β Hardcoded default agent ID ‘agent’, ‘auth-profiles.json’ );
await fs.writeFile(authPath, JSON.stringify({ tokenRef }));
// Should be: agent.id instead of 'main'
} }
Failure Sequence
- User runs
openclaw onboardwith 7 agents configured - Auth handler validates token against Anthropic API
- Token reference is stored in memory
- Loop writes auth file 7 times to the same path:
~/.openclaw/agents/main/agent/auth-profiles.json - Final state: Only
mainagent has auth; all other agent directories retain stale tokens or have no auth file - Gateway starts with
mainagent properly authenticated - Other agents attempt model calls β gateway checks
agents/{id}/agent/auth-profiles.jsonβ not found β silently uses fallback
Architectural Inconsistency
The gateway’s auth resolution follows this priority chain:
- Check: agents/{current_agent}/agent/auth-profiles.json
- Fallback: Use free/fallback model (no auth required)
- Skip: Never checks agents/main/agent/auth-profiles.json as canonical fallback
This differs from how other agent-scoped configs (prompts, tools, context) are inherited from main when agent-specific versions are absent.
Environment Variable Impact
The OPENCLAW_HOME environment variable is respected for the base path, but the agent subdirectory bug remains:
bash $ OPENCLAW_HOME=/opt/openclaw openclaw onboard
Still writes only to /opt/openclaw/agents/main/agent/auth-profiles.json
π οΈ Step-by-Step Fix
Option A: Fix onboard Command (Recommended)
File: src/commands/onboard.ts
Before: typescript for (const agent of agents) { const authDir = path.join( openclawHome, ‘agents’, ‘main’, // BUG: hardcoded ‘agent’ ); await fs.mkdir(authDir, { recursive: true }); await fs.writeFile( path.join(authDir, ‘auth-profiles.json’), JSON.stringify({ tokenRef: validatedToken.tokenRef }, null, 2) ); }
After: typescript for (const agent of agents) { const authDir = path.join( openclawHome, ‘agents’, agent.id, // FIX: use actual agent ID ‘agent’ ); await fs.mkdir(authDir, { recursive: true }); await fs.writeFile( path.join(authDir, ‘auth-profiles.json’), JSON.stringify({ tokenRef: validatedToken.tokenRef }, null, 2) ); }
Rebuild and reinstall: bash cd openclaw npm run build npm link openclaw onboard –reauth # re-authenticate with new fix
Option B: Gateway Fallback Auth Resolution (Alternative)
Modify src/gateway/auth-resolver.ts to inherit from main agent:
Before: typescript async resolveAuth(agentId: string): Promise<AuthProfile | null> { const agentAuthPath = path.join(openclawHome, ‘agents’, agentId, ‘agent’, ‘auth-profiles.json’);
if (fs.existsSync(agentAuthPath)) { return this.loadAuthProfile(agentAuthPath); }
return null; // Falls through to free model }
After: typescript async resolveAuth(agentId: string): Promise<AuthProfile | null> { // Check agent-specific auth first const agentAuthPath = path.join(openclawHome, ‘agents’, agentId, ‘agent’, ‘auth-profiles.json’);
if (fs.existsSync(agentAuthPath)) { return this.loadAuthProfile(agentAuthPath); }
// Fallback: inherit from default agent (main) if agent-specific is missing
if (agentId !== ‘main’) {
const defaultAuthPath = path.join(openclawHome, ‘agents’, ‘main’, ‘agent’, ‘auth-profiles.json’);
if (fs.existsSync(defaultAuthPath)) {
console.warn([Auth] Agent '${agentId}' has no auth file; inheriting from 'main'. Run 'openclaw onboard' to provision explicitly.);
return this.loadAuthProfile(defaultAuthPath);
}
}
return null; }
Temporary Workaround (Immediate)
bash
Define agents from your config
AGENTS=“main chief developer qa secretary lawyer writer experimenter”
Create directories and copy auth
for agent in $AGENTS; do
mkdir -p ~/.openclaw/agents/$agent/agent
cp ~/.openclaw/agents/main/agent/auth-profiles.json
~/.openclaw/agents/$agent/agent/auth-profiles.json
done
Restart gateway to pick up new tokens
pkill -f “openclaw gateway” openclaw gateway start &
Single-command version: bash jq -r ‘.agents.list[].id’ openclaw.json | xargs -I{} sh -c ‘mkdir -p ~/.openclaw/agents/{}/agent && cp ~/.openclaw/agents/main/agent/auth-profiles.json ~/.openclaw/agents/{}/agent/’
π§ͺ Verification
1. Confirm All Auth Files Exist
bash $ ls -la ~/.openclaw/agents/*/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/chief/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/developer/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/main/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/experimenter/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/lawyer/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/qa/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/secretary/agent/auth-profiles.json -rw——- 1 user user 892 Mar 8 14:30 /home/user/.openclaw/agents/writer/agent/auth-profiles.json
All 8 files should exist with identical or equivalent tokenRef content.
2. Verify Token Content Consistency
bash $ jq -r ‘.tokenRef’ ~/.openclaw/agents/main/agent/auth-profiles.json sk-ant-…
$ for agent in chief developer qa secretary lawyer writer experimenter; do echo -n “$agent: " jq -r ‘.tokenRef’ ~/.openclaw/agents/$agent/agent/auth-profiles.json 2>/dev/null || echo “MISSING” done chief: sk-ant-… developer: sk-ant-… qa: sk-ant-… secretary: sk-ant-… lawyer: sk-ant-… writer: sk-ant-… experimenter: sk-ant-…
All agents should display the same tokenRef (or equivalent value).
3. Test Agent Authentication via Gateway
bash $ openclaw gateway logs –follow & $ openclaw run –agent developer “echo test” 2>&1 | head -20
Should see no fallback warnings in gateway logs:
[2026-03-08T14:35:01Z] INFO: Agent ‘developer’ authenticated via agents/developer/agent/auth-profiles.json
4. Verify No Silent Fallback Occurs
bash $ grep -r “using free fallback” ~/.openclaw/agents/*/logs/gateway.log || echo “No fallbacks detected”
$ openclaw run –agent developer “what model are you”
Should respond as Claude Sonnet, not as GLM 4.5 Air
5. Verify Fixed Build (if Option A applied)
bash $ grep “agent.id” node_modules/openclaw/dist/commands/onboard.js const authDir = path.join(openclawHome, ‘agents’, agent.id, ‘agent’);
$ openclaw onboard –dry-run β Would write auth to: agents/chief/agent/auth-profiles.json β Would write auth to: agents/developer/agent/auth-profiles.json …
6. Exit Code Validation
bash $ openclaw onboard && echo “Exit code: $?” β Authenticated with Anthropic β Token written to all 8 agent directories β Onboarding complete Exit code: 0
β οΈ Common Pitfalls
Pitfall 1: Agent ID Mismatch
If your openclaw.json uses custom agent IDs that don’t match directory names:
json { “agents”: { “list”: [ { “id”: “prod-server”, “model”: “anthropic/claude-opus-4-6” } ] } }
The onboard command may fail silently if prod-server contains hyphens (OS-specific path issues on Windows).
Mitigation: Verify directory creation succeeds: bash ls -la ~/.openclaw/agents/prod-server/agent/
Pitfall 2: Mixed Auth Methods
If some agents use setup-token and others use OAuth:
json
{
“agents”: {
“list”: [
{ “id”: “main”, “auth”: { “method”: “setup-token”, “provider”: “anthropic” } },
{ “id”: “developer”, “auth”: { “method”: “oauth”, “provider”: “openai” } }
]
}
}
Onboard may overwrite OAuth tokens with setup-token refs. Always audit auth files post-onboard.
Mitigation: Review auth config per agent after onboarding: bash jq ‘.auth.method’ ~/.openclaw/agents/*/agent/auth-profiles.json
Pitfall 3: Docker Environment
When running in Docker, ~/.openclaw inside the container is ephemeral:
bash docker run –rm openclaw onboard
Tokens written to container’s ~/.openclaw, lost on exit
docker run -v openclaw-data:/root/.openclaw openclaw onboard
Tokens persist via volume mount
Mitigation: Mount persistent volume for auth data: bash docker run -v $(pwd)/openclaw-data:/root/.openclaw openclaw onboard
Pitfall 4: Windows Path Separator
On Windows, ~/.openclaw expands to %USERPROFILE%\.openclaw, but the code may use forward slashes:
powershell
Bug manifests as:
Writing to: C:\Users\user.openclaw\agents\main\agent\auth-profiles.json
But gateway reads: C:/Users/user/.openclaw/agents/main/agent/auth-profiles.json
$ openclaw onboard
May succeed but gateway cannot find file
Mitigation: Run openclaw verify-config before onboard on Windows.
Pitfall 5: Stale Token Cooldowns
If agents had previous failed auth attempts, they may be in error cooldown:
bash $ openclaw run –agent developer “test” Error: Rate limited (cooldown: 47 minutes remaining)
Mitigation: Clear cooldown state: bash rm ~/.openclaw/agents/developer/agent/auth-profiles.json openclaw onboard
Pitfall 6: Untracked Auth Files
Git-ignored auth-profiles.json files won’t be backed up:
bash $ cat .gitignore … agents/*/agent/auth-profiles.json # excluded
Onboarding on new machine β no auth files exist
Main agent gets auth, others remain empty
Mitigation: Track auth file structure without content: bash
Commit directory skeleton:
mkdir -p agents/TEMPLATE/agent touch agents/TEMPLATE/agent/.gitkeep
π Related Errors
#28293 β Non-default agents get 401 with same token
Symptom: Agents configured with identical tokenRef receive HTTP 401 from provider.
Difference: This issue stems from token expiry or scope validation; this bug (auth file distribution) causes the token to be unavailable in the first place.
Resolution: Verify token validity with openclaw auth verify; if valid, apply the onboard fix.
#38336 β OAuth renewal doesn’t update provisioned copy
Symptom: After OAuth token refresh via browser, CLI commands still fail auth for non-main agents.
Relationship: Demonstrates the same architectural gapβauth updates flow to main agent only, leaving others in stale state.
Workaround: Manually sync after OAuth renewal:
bash
cp ~/.openclaw/agents/main/agent/auth-profiles.json
~/.openclaw/agents/*/agent/auth-profiles.json
EAUTH-001 β Auth profile not found
Symptom: EAUTH-001: No auth-profiles.json found for agent '{agent}'
Root: Agent directory doesn’t exist or was never provisioned by onboard.
EFAIL-202 β Silent fallback to free model
Symptom: Command succeeds but output quality is degraded (free model responses).
Root: Gateway detects missing auth and falls back without user notification.
EMODEL-404 β Model not available for agent
Symptom: Agent configured for anthropic/claude-opus-4-6 but receives “model not found” error.
Root: May indicate auth file exists but contains invalid/expired token; verify with openclaw auth status --agent {id}.