Skip to main content

Overview

PicoClaw has transitioned from the legacy providers configuration to a new model_list format. The new format is:
  • More flexible - Configure multiple models from the same provider
  • More powerful - Support for load balancing and custom endpoints
  • Vendor-agnostic - Uses vendor/model format instead of separate provider + model
  • Easier to understand - Model-centric configuration
The legacy providers format is deprecated but still supported for backward compatibility. New features will only be added to model_list.

Migration Overview

The migration process involves:
  1. Moving provider configuration from providers to model_list
  2. Updating agents.defaults.model from model name to vendor/model format
  3. Removing the old provider field
PicoClaw automatically migrates legacy configs at runtime, but you should update your config files manually for clarity.

Migration Examples

Example 1: OpenAI

Before (Legacy):
{
  "providers": {
    "openai": {
      "api_key": "sk-...",
      "api_base": "https://api.openai.com/v1"
    }
  },
  "agents": {
    "defaults": {
      "provider": "openai",
      "model": "gpt-4"
    }
  }
}
After (New):
{
  "model_list": [
    {
      "model_name": "gpt-4",
      "model": "openai/gpt-4",
      "api_key": "sk-..."
    }
  ],
  "agents": {
    "defaults": {
      "model": "gpt-4"
    }
  }
}

Example 2: Anthropic

Before:
{
  "providers": {
    "anthropic": {
      "api_key": "sk-ant-..."
    }
  },
  "agents": {
    "defaults": {
      "provider": "anthropic",
      "model": "claude-sonnet-4.6"
    }
  }
}
After:
{
  "model_list": [
    {
      "model_name": "claude-sonnet-4.6",
      "model": "anthropic/claude-sonnet-4.6",
      "api_key": "sk-ant-..."
    }
  ],
  "agents": {
    "defaults": {
      "model": "claude-sonnet-4.6"
    }
  }
}

Example 3: Zhipu

Before:
{
  "providers": {
    "zhipu": {
      "api_key": "your-key",
      "api_base": "https://open.bigmodel.cn/api/paas/v4"
    }
  },
  "agents": {
    "defaults": {
      "provider": "zhipu",
      "model": "glm-4.7"
    }
  }
}
After:
{
  "model_list": [
    {
      "model_name": "glm-4.7",
      "model": "zhipu/glm-4.7",
      "api_key": "your-key"
    }
  ],
  "agents": {
    "defaults": {
      "model": "glm-4.7"
    }
  }
}
The api_base for Zhipu is optional in the new format - it’s set automatically to the correct endpoint.

Example 4: Multiple Providers

Before:
{
  "providers": {
    "openai": {
      "api_key": "sk-openai-..."
    },
    "anthropic": {
      "api_key": "sk-ant-..."
    },
    "groq": {
      "api_key": "gsk-..."
    }
  },
  "agents": {
    "defaults": {
      "provider": "openai",
      "model": "gpt-4"
    }
  }
}
After:
{
  "model_list": [
    {
      "model_name": "gpt-4",
      "model": "openai/gpt-4",
      "api_key": "sk-openai-..."
    },
    {
      "model_name": "claude-sonnet-4.6",
      "model": "anthropic/claude-sonnet-4.6",
      "api_key": "sk-ant-..."
    },
    {
      "model_name": "llama-3-70b",
      "model": "groq/llama-3.3-70b-versatile",
      "api_key": "gsk-..."
    }
  ],
  "agents": {
    "defaults": {
      "model": "gpt-4",
      "fallbacks": ["claude-sonnet-4.6", "llama-3-70b"]
    }
  }
}

Example 5: Custom Endpoint

Before:
{
  "providers": {
    "openai": {
      "api_key": "sk-...",
      "api_base": "https://my-proxy.com/v1"
    }
  },
  "agents": {
    "defaults": {
      "provider": "openai",
      "model": "custom-gpt-4"
    }
  }
}
After:
{
  "model_list": [
    {
      "model_name": "custom-gpt-4",
      "model": "openai/custom-gpt-4",
      "api_key": "sk-...",
      "api_base": "https://my-proxy.com/v1"
    }
  ],
  "agents": {
    "defaults": {
      "model": "custom-gpt-4"
    }
  }
}

Field Mapping

Legacy FieldNew FieldNotes
providers.{vendor}.api_keymodel_list[].api_keySame
providers.{vendor}.api_basemodel_list[].api_baseOptional, auto-detected for known providers
agents.defaults.provider(removed)Now part of model field
agents.defaults.modelagents.defaults.modelNow references model_name from model_list

Vendor Name Mapping

When migrating, use these vendor prefixes:
ProviderVendor Prefix
OpenAIopenai/
Anthropicanthropic/
Zhipu AI (GLM)zhipu/
DeepSeekdeepseek/
Google Geminigemini/
Groqgroq/
Moonshotmoonshot/
Qwen (通义千问)qwen/
NVIDIAnvidia/
Ollamaollama/
OpenRouteropenrouter/
LiteLLMlitellm/
VLLMvllm/
Cerebrascerebras/
See the complete provider list for all supported vendors.

Automatic Migration

PicoClaw automatically migrates legacy configs at runtime:
[INFO] config: Auto-migrating legacy providers config to model_list
[INFO] config: Migrated provider: openai → model_list[0]
[INFO] config: Migrated provider: anthropic → model_list[1]
But you should manually update your config for clarity.

Migration Script

Here’s a Python script to help migrate your config:
import json
import sys

def migrate_config(old_config):
    new_config = old_config.copy()
    
    # Create model_list from providers
    if "providers" in old_config:
        model_list = []
        
        for vendor, config in old_config["providers"].items():
            # Get model name from agents.defaults
            model_name = old_config.get("agents", {}).get("defaults", {}).get("model", "")
            
            entry = {
                "model_name": model_name,
                "model": f"{vendor}/{model_name}",
                "api_key": config.get("api_key", "")
            }
            
            if "api_base" in config:
                entry["api_base"] = config["api_base"]
            
            model_list.append(entry)
        
        new_config["model_list"] = model_list
        del new_config["providers"]
    
    # Update agents.defaults
    if "agents" in new_config and "defaults" in new_config["agents"]:
        if "provider" in new_config["agents"]["defaults"]:
            del new_config["agents"]["defaults"]["provider"]
    
    return new_config

if __name__ == "__main__":
    with open("config.json", "r") as f:
        old_config = json.load(f)
    
    new_config = migrate_config(old_config)
    
    with open("config.new.json", "w") as f:
        json.dump(new_config, f, indent=2)
    
    print("Migrated config saved to config.new.json")
Usage:
python migrate.py
# Review config.new.json
# If looks good: mv config.new.json ~/.picoclaw/config.json

Testing Your Migration

After migrating, test your config:
# Check configuration
picoclaw status

# Test agent with new config
picoclaw agent -m "Hello, are you working?"

# Check provider status
picoclaw auth status

Breaking Changes

No breaking changes! The legacy format is still supported. However:
  • New features (load balancing, advanced routing) only work with model_list
  • Deprecation warnings may appear in logs
  • Future versions may remove legacy support entirely

Benefits of New Format

Load balancing

Configure multiple API keys for the same model

Flexible routing

Mix models from different providers

Clearer config

Model-centric instead of provider-centric

Custom endpoints

Easier to configure custom API bases

Troubleshooting

  • Ensure you deleted the provider field from agents.defaults
  • Check that model in agents.defaults matches a model_name in model_list
  • Restart PicoClaw after config changes
  • Verify api_key is correctly copied to model_list
  • Check api_base if you had a custom endpoint
  • Run picoclaw status to see provider health
  • These are safe to ignore if everything works
  • Migrate to model_list to remove warnings
  • Legacy support will be removed in a future version

Next Steps

Model Configuration

Complete guide to model_list configuration

Load Balancing

Use multiple endpoints for high availability

Providers

Understand the provider system

Troubleshooting

Common issues and solutions

Build docs developers (and LLMs) love