Buffaly Logo
Developer Extensibility

Add a model provider

This guide explains the external-provider registration flow for developers. Provider modules are dynamic, compiled C# assemblies loaded at runtime, ensuring enterprise stability and strict response contracts.

When to add a provider module

Add a model provider only when Buffaly must select and call an entirely different LLM reasoning backend. Provider modules are not a generic tool mechanism.

If you need to...Do this instead
Add a repeatable text/checklist workflowCreate a Prompt skill
Execute a native typed operationCreate a ProtoScript action
Connect deterministic SDK/protocol logicBuild a C# DLL tool
Model a configured system with identity/lifecycleBuild a Service
Add a new LLM backend to the runtimeBuild a Model Provider Module

Provider module anatomy & Contracts

The architecture keeps provider implementations outside the core Buffaly.Development tree. They must implement shared Buffaly.Agent.Web.Common contracts.

IProviderCatalogSource

Builds the catalog row. Returns the provider token, available models, default model, reasoning options, and enabled state to the UI and validation engine.

IProviderNativeCompletionExecutor

The execution surface. Handles the actual API calls to the LLM backend and maps the response into Buffaly's canonical format.

IProviderAuthHandler (Optional)

Implemented by OAuth-capable providers. Owns provider-specific login protocol details (like OIDC discovery and PKCE exchange), handing tokens back to the host for storage.

ProviderModules.json & Layout

Modules are loaded from the runtime install root, specifically <InstallRootPath>\lib\provider-modules\. You must copy your compiled provider assembly and its dependencies into a dedicated subfolder here.

Critical Deployment Note:

The Web App needs provider catalog-source assemblies. Worker processes need provider completion-executor assemblies. Keep the web and worker provider-modules folders perfectly aligned.

Example ProviderModules.json

{
  "Modules": [
    {
      "Enabled": true,
      "Provider": "anthropic",
      "DisplayName": "Anthropic",
      "AssemblyPath": "Buffaly.Provider.Anthropic/Buffaly.Provider.Anthropic.dll",
      "CatalogSourceTypeName": "Buffaly.Provider.Anthropic.AnthropicProviderCatalogSource",
      "CompletionExecutorTypeName": "Buffaly.Provider.Anthropic.AnthropicCompletionExecutor",
      "LoadOrder": 500
    }
  ]
}

Credentials & Feature Rows

Provider credentials and model settings live in the target instance's SQL sessions database (dbo.Features table), not in source code or the manifest.

Example structure of the Anthropic Feature row:

FeatureName = Anthropic Feature
Settings = {
  "ApiKey": "...",
  "ModelNames": ["claude-sonnet-4-5"],
  "SupportedReasoningLevels": ["low", "medium", "high"],
  "DefaultReasoningLevel": "medium",
  "BaseUrl": "https://api.anthropic.com",
  "Version": "2023-06-01",
  "MaxTokens": 4096
}

The Response Contract

External APIs return data in a hundred different ways. The Provider Executor must unwrap the external API response and return it as Buffaly canonical items JSON in ProviderNativeCompletionResult.Raw.

{
  "items": [
    {
      "type": "message",
      "role": "assistant",
      "phase": "final_answer",
      "content": [
        {
          "type": "output_text",
          "text": "provider smoke ok"
        }
      ],
      "metadata": {
        "format": "text",
        "result_type": "display message"
      }
    }
  ]
}

If a 3rd-party model returns a canonical payload as text inside a fenced JSON code block, the executor must unwrap it before returning it to Buffaly.

Registration Workflow

  1. Build the provider project implementing the Common contracts.
  2. Copy the module folder into <InstallRootPath>\lib\provider-modules.
  3. Add/update the manifest entry in ProviderModules.json.
  4. Inject the provider feature row (credentials) into the target instance SQL sessions database.
  5. Recycle only the target instance app pool (e.g., appcmd.exe recycle apppool /apppool.name:stagingPool). Do not kill shared dotnet processes.
  6. Verify the catalog endpoints and run a smoke test.

API Verification

Use JsonWs endpoints directly for API-only verification. Post to /api/buffaly.agent.host/provider-catalog-service/get-provider-catalog to ensure your provider appears.

  • Provider token matches.
  • IsEnabled=true (from the manifest).
  • IsConfigured=true (verifying your SQL Feature Row credentials successfully bound).
Providers and AuthenticationAdding skills, services, and toolsAdd a C# DLL toolTroubleshooting and validation