Skip to content

Providers

nagents supports multiple LLM providers with a unified interface, making it easy to switch between providers without changing your application logic.

Provider Types

Provider Type Description
OpenAI ProviderType.OPENAI_COMPATIBLE OpenAI API and compatible services
Anthropic ProviderType.ANTHROPIC Anthropic Claude API
Google ProviderType.GEMINI_NATIVE Google Gemini API
OpenRouter ProviderType.OPENROUTER OpenAI-compatible API with OpenRouter identification
LiteLLM ProviderType.LITELLM API-key gateway with an explicit API prefix

Sign in from ngn

Use /provider in the TUI or Settings → Global/Workspace → Provider connections in ngn serve to manage named connections shared across clients. Global ones are saved to $XDG_CONFIG_HOME/ngn/providers.json; workspace ones are saved to workspace-specific JSON under the same config root. Both use environment-variable references, not key values. OpenAI can select ngn ChatGPT login, local Codex discovery, or an API-key variable. Azure AI Foundry supports API-key variables and Microsoft Entra ID through the optional azure-identity package. Voice settings for a named connection use the same endpoint and credential reference. See named provider configuration.

Chat model selection is independent: use /model in the TUI, --model for a single CLI invocation, or the global/workspace chat-model selector in web Settings. Connections display their credential source and effective endpoint; their JSON entries do not contain a chat model. Voice preferences are stored separately from provider connections.

ngn login chatgpt stores the device credential used by a named OpenAI connection with "auth": "chatgpt". Login alone does not activate a provider; select a named connection in the registry or with --provider-id. API-key connections use the environment-variable name specified in providers.json. ngn login --status and ngn logout manage saved login credentials. Library users pass credentials explicitly as shown below.

Discover Model IDs

Local Codex configuration

from nagents import OpenAIProvider

provider = OpenAIProvider()

With no explicit credentials, OpenAIProvider discovers Codex configuration under CODEX_HOME or ~/.codex. It reads config.toml and file-based auth.json to select the model, API contract and authentication method. Saved ChatGPT login uses the existing Codex OAuth transport; API-key/custom-provider configuration uses the selected Responses or legacy Chat Completions API. An unrelated OPENAI_API_KEY does not replace a saved ChatGPT login.

Optional overrides are OpenAIProvider(home=..., profile=..., model=...).

An explicit API key bypasses local discovery, including saved ChatGPT login:

provider = OpenAIProvider(api_key="your-api-key", model="gpt-5.6-terra", api="responses")

Use api="chat_completions" to select that protocol. A custom base_url requires an explicit api_key. provider.uses_chatgpt_auth distinguishes subscription authentication from API-key authentication.

Selected NAME.config.toml profile files and legacy [profiles.NAME] tables are supported. Custom providers can specify base_url, wire_api, env_key, and requires_openai_auth. Project-local configuration is not used for authentication or endpoint discovery. No credentials are copied or written. OAuth tokens are reread before requests, picking up refreshes performed by Codex; Nagents does not rotate the external application's refresh tokens.

This discovery path currently requires file credentials. Keyring-only/ephemeral logins and provider command-auth/custom-header/query settings report an explicit configuration error instead of silently selecting another route. Supplying the existing credential callback continues to work for application-owned OAuth.

Explicit catalog discovery

await provider.get_model_list() -> list[str] is included in v0.15.0. See the Provider API example for a complete async example using your own OPENAI_API_KEY environment variable.

Discovery is explicit and fresh. It does not select a model, alter configuration, or generate a response. OpenAI-compatible, OpenRouter, LiteLLM, and Azure v1 connections query their configured API prefix plus /models, using their own API key. A custom service must implement the conventional data array with string id fields. Keep a manual model-ID input: unsupported discovery raises NotImplementedError, and missing credentials, upstream failures, or malformed catalogs raise ModelListError. An empty list means a valid empty catalog, not a fallback after a failure. Native Gemini, Anthropic, and versioned Azure discovery is not implemented by this method; their existing verification behavior is unchanged.

Catalog IDs are not capability or entitlement guarantees. The generation service can reject a listed model or accept an unlisted one. API-key catalogs and ChatGPT/Codex OAuth catalogs are separate connections, not interchangeable ways to use a subscription. Never pass a Codex OAuth token as Provider.api_key, or send it to an OpenAI-compatible endpoint. Use OpenAIProvider with ChatGPT authentication and the existing ngn login flow for subscription access. Its get_model_list() fetches picker-visible slug IDs from the fixed Codex catalog using a fresh credential snapshot. supported_in_api: false does not exclude an OAuth model. See the ChatGPT API example and pinned contract for authentication, visibility validation, and compatibility limits. This follows the official Codex client, not a stable public API guarantee; manual entry remains available without changing login or billing mode.


OpenAI Compatible

Works with OpenAI API and any compatible service (Azure, local models, etc.):

from nagents import Provider, ProviderType

provider = Provider(
    provider_type=ProviderType.OPENAI_COMPATIBLE,
    api_key="sk-...",
    model="gpt-4o-mini",
)

Available models:

  • gpt-4o - Most capable
  • gpt-4o-mini - Fast and affordable
  • gpt-4-turbo - Previous generation
  • gpt-3.5-turbo - Legacy, fastest
provider = Provider(
    provider_type=ProviderType.OPENAI_COMPATIBLE,
    api_key="your-azure-key",
    model="gpt-4",
    base_url="https://your-resource.openai.azure.com/openai/deployments/gpt-4",
)

Azure Configuration

Set base_url to your Azure OpenAI deployment endpoint.

# Ollama
provider = Provider(
    provider_type=ProviderType.OPENAI_COMPATIBLE,
    api_key="not-needed",  # (1)!
    model="llama2",
    base_url="http://localhost:11434/v1",
)

# vLLM
provider = Provider(
    provider_type=ProviderType.OPENAI_COMPATIBLE,
    api_key="not-needed",
    model="meta-llama/Llama-2-7b-chat-hf",
    base_url="http://localhost:8000/v1",
)
  1. Local servers typically don't require an API key, but the parameter is still required.

Anthropic Claude

Native Anthropic API support with all Claude models:

from nagents import Provider, ProviderType

provider = Provider(
    provider_type=ProviderType.ANTHROPIC,
    api_key="sk-ant-...",
    model="claude-3-5-sonnet-20241022",
)

Available models:

Model Description
claude-3-5-sonnet-20241022 Best balance of intelligence and speed
claude-3-opus-20240229 Most capable, best for complex tasks
claude-3-sonnet-20240229 Balanced performance
claude-3-haiku-20240307 Fastest, best for simple tasks

Model Selection

Start with claude-3-5-sonnet for most use cases. Use opus for complex reasoning and haiku for high-throughput, simple tasks.


Google Gemini

Native Gemini API support:

from nagents import Provider, ProviderType

provider = Provider(
    provider_type=ProviderType.GEMINI_NATIVE,
    api_key="...",
    model="gemini-2.0-flash",
)

Available models:

Model Description
gemini-2.0-flash Latest, fastest multimodal model
gemini-1.5-pro Most capable, large context window
gemini-1.5-flash Fast and efficient

Switching Providers

The unified interface makes it easy to switch providers dynamically:

multi_provider.py
import os
from pathlib import Path
from nagents import Agent, ErrorEvent, Provider, ProviderType, SessionManager, TextChunkEvent


def get_provider(provider_name: str) -> Provider:
    """Create a provider based on name."""
    match provider_name:
        case "openai":
            return Provider(
                provider_type=ProviderType.OPENAI_COMPATIBLE,
                api_key=os.environ["OPENAI_API_KEY"],
                model=os.environ["OPENAI_MODEL"],
            )
        case "anthropic":
            return Provider(
                provider_type=ProviderType.ANTHROPIC,
                api_key=os.environ["ANTHROPIC_API_KEY"],
                model=os.environ["ANTHROPIC_MODEL"],
            )
        case "gemini":
            return Provider(
                provider_type=ProviderType.GEMINI_NATIVE,
                api_key=os.environ["GOOGLE_API_KEY"],
                model=os.environ["GOOGLE_MODEL"],
            )
        case _:
            raise ValueError(f"Unknown provider: {provider_name}")


async def main():
    # Select provider from environment or config
    provider_name = os.getenv("LLM_PROVIDER", "openai")
    provider = get_provider(provider_name)

    session_manager = SessionManager(Path("sessions.db"))

    # The same text-only agent interface can use any of these providers.
    agent = Agent(
        provider=provider,
        session_manager=session_manager,
        streaming=True,
    )

    try:
        async for event in agent.run("Hello!"):
            if isinstance(event, TextChunkEvent):
                print(event.chunk, end="", flush=True)
            elif isinstance(event, ErrorEvent):
                print(f"\nError: {event.message}")
    finally:
        await agent.close()

Set the selected provider's API key and *_MODEL environment variables before calling main(). Choose a model available to your account.

Provider Agnostic

The text-generation interface is shared, but media, reasoning, batch, and generation-option support depend on the backend and HTTP contract. Your application can use this interface to:

  • Switch providers for cost optimization
  • Use different providers for different tasks
  • Fail over to backup providers
  • Test with local models, deploy with cloud providers

Provider Comparison

Feature Comparison
Feature OpenAI Anthropic Gemini
Streaming
Tool Calling
Vision
Max Context 128K 200K 2M
Custom Base URL

Best Practices

Recommendations

  1. Use environment variables for API keys
  2. Start with smaller models (gpt-4o-mini, claude-3-haiku, gemini-flash) for development
  3. Implement fallback logic for production systems
  4. Monitor token usage via the usage field in events