Skip to content

Add support for named providers in .ctx files #132

@celeria-ai

Description

@celeria-ai

Feature Request: Named Providers in .ctx Files

Summary

Add support for a providers field in .ctx files that allows users to define multiple named provider configurations with their own model, api_url, and api_key settings. NPCs can then reference these providers by name, enabling easy switching between different OpenAI-compatible APIs and other providers.

Use Case

Users working with multiple LLM providers (e.g., Ollama Cloud, local Ollama, different OpenAI endpoints) need a clean way to:

  1. Define multiple provider configurations in one place
  2. Reference them by name in NPC definitions
  3. Override specific fields (like model) while inheriting others (like api_url)

Proposed Structure

# team.ctx
providers:
  - name: ollama_cloud
    provider_type: openai-like
    model: llama3.2
    api_url: https://ollama-cloud.example.com/v1
    api_key: ${OLLAMA_CLOUD_KEY}  # optional
    
  - name: local_ollama
    provider_type: openai-like
    model: mistral
    api_url: http://localhost:11434/v1
    
  - name: main_openai
    provider_type: openai
    model: gpt-4o
    api_key: ${OPENAI_API_KEY}

team:
  name: my_team
  members:
    - npc: researcher
      provider: ollama_cloud  # references provider by name
      # model and api_url inherited from provider definition
      
    - npc: coder
      provider: local_ollama
      model: codellama  # can override model
      
    - npc: reviewer
      provider: main_openai

Implementation Plan

npcsh/_state.py only (npcpy remains unchanged):

  1. Parse the providers field from .ctx files during team initialization in setup_shell()
  2. Build a providers dict mapping name → config
  3. When initializing NPCs, resolve provider references:
    • If NPC has provider: <name> matching a defined provider:
      • Inject model from provider if NPC doesn't have one
      • Inject api_url from provider if NPC doesn't have one
      • Inject api_key from provider if NPC doesn't have one
      • Use provider_type from provider as the actual provider
    • Allow NPCs to override specific fields

npcpy remains completely agnostic - it just receives fully-resolved NPC configs with model, provider, api_url, api_key as it does now.

Benefits

  1. Centralized configuration: All provider settings in one place
  2. Reusability: Multiple NPCs can use the same provider config
  3. Flexibility: Override individual fields while inheriting others
  4. Environment variable support: Continue to support ${VAR} syntax
  5. Clean NPC definitions: NPCs focus on their role, not infrastructure
  6. npcpy agnostic: Core library doesn't need npcsh-specific logic

Example NPC File

# researcher.npc
name: researcher
primary_directive: You are a research assistant...
provider: ollama_cloud  # inherits model and api_url from provider definition
# coder.npc  
name: coder
primary_directive: You are a coding assistant...
provider: local_ollama  # inherits api_url
model: codellama  # overrides provider's model

Testing

Test scenarios:

  1. Define providers in .ctx, reference by name in NPCs
  2. Override model/api_url in NPC while inheriting other fields
  3. Mix of provider-referenced and explicitly-configured NPCs
  4. Environment variable expansion in provider configs
  5. Error handling for undefined provider references

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions