What Is the `internal/plugins/ai` Directory in Fabric? The AI Vendor Abstraction Layer Explained

The internal/plugins/ai directory is the core AI vendor abstraction layer that unifies how Fabric communicates with dozens of AI providers through a single Vendor interface.

This directory houses the plugin architecture that allows Fabric to treat OpenAI, Anthropic, Gemini, Azure, Ollama, and numerous other services as interchangeable backends. By encapsulating provider-specific HTTP clients, authentication, and request formatting behind a common contract, the internal/plugins/ai package enables Fabric’s CLI, REST API, and pattern engine to switch models with a single flag.

Core Purpose of the internal/plugins/ai Directory

The internal/plugins/ai package serves as Fabric’s AI-vendor layer, hiding the differences between disparate AI APIs behind a unified Go interface. Instead of scattering provider-specific logic throughout the codebase, Fabric centralizes it here, allowing the application to treat every AI service as a generic Vendor.

This design means adding support for a new provider requires only creating a new sub-directory that implements the Vendor interface; the rest of Fabric automatically discovers and uses it without modification.

Key Components and File Structure

The Vendor Interface (vendor.go)

At the heart of the directory is the Vendor interface defined in internal/plugins/ai/vendor.go. This contract mandates that every AI provider must implement methods for:

  • Listing available models
  • Streaming and non-streaming chat completions
  • Reporting whether the vendor requires raw mode

By strictly defining this interface, Fabric ensures that any code importing internal/plugins/ai can interact with AI services without knowing which specific provider is configured.

Model Management Utilities (models.go)

The internal/plugins/ai/models.go file provides VendorsModels, a utility struct that aggregates models across all registered vendors. It offers helper methods for:

  • Grouping models by vendor name
  • Filtering by specific vendor (case-insensitive)
  • Case-insensitive lookups for model names
  • Pretty-printing model lists for CLI output

These utilities power Fabric’s --listmodels flag and ensure users can select models using intuitive, case-insensitive names.

Vendor Registry (vendors.go)

The internal/plugins/ai/vendors.go file acts as a central registry, aggregating constructors for every concrete vendor implementation. It dynamically exposes available providers to the rest of the application, allowing Fabric’s initialization code to discover and instantiate vendors without hard-coding provider names.

Provider Implementations

Each supported AI service resides in its own sub-directory under internal/plugins/ai/, implementing the Vendor interface with provider-specific logic:

Each directory contains the HTTP client configuration, request/response marshaling, authentication headers, and any provider-specific features like image generation or text-to-speech.

Dry-Run Mode (dryrun/dryrun.go)

For testing and development, internal/plugins/ai/dryrun/dryrun.go implements a special Vendor that performs no actual API calls. Instead, it returns the would-be request payload, enabling users to validate patterns and configurations using the --dry-run CLI flag without consuming API credits.

Practical Usage Examples

Listing Available Vendors via CLI

To see all registered AI providers that Fabric can use:

fabric --listvendors

This command queries the registry in vendors.go and prints every vendor that implements the Vendor interface.

Programmatic Model Selection

When building tools on top of Fabric’s Go API, use VendorsModels to handle model discovery and selection:

import (
    "github.com/danielmiessler/fabric/internal/plugins/ai"
    "fmt"
)

func main() {
    // Initialize the model catalog
    models := ai.NewVendorsModels()
    
    // Add models from different vendors
    models.AddGroupItems("OpenAI", "gpt-4o", "gpt-4-turbo")
    models.AddGroupItems("Anthropic", "claude-3-opus-20240229", "claude-3-sonnet-20240229")
    
    // Filter to specific vendor (case-insensitive)
    openAIModels := models.FilterByVendor("openai")
    
    // Find model with case-insensitive matching
    modelName := openAIModels.FindModelNameCaseInsensitive("GPT-4O")
    fmt.Println(modelName) // Output: gpt-4o
}

The helper methods FilterByVendor and FindModelNameCaseInsensitive are defined in internal/plugins/ai/models.go.

Direct Vendor Integration

For advanced use cases requiring direct provider access, instantiate a specific vendor implementation:

import (
    "context"
    "github.com/danielmiessler/fabric/internal/plugins/ai/openai"
    "github.com/danielmiessler/fabric/internal/chat"
)

func chatWithOpenAI(ctx context.Context) (string, error) {
    // Create the OpenAI plugin
    // Constructor defined in internal/plugins/ai/openai/openai.go
    plugin := openai.NewPlugin()
    
    // Prepare messages
    messages := []*chat.ChatCompletionMessage{
        {Role: "user", Content: "Explain the fabric pattern system"},
    }
    
    // Send request using the Vendor interface method
    response, err := plugin.Send(ctx, messages, nil)
    return response, err
}

The Send method implements the Vendor interface contract defined in vendor.go.

Testing with Dry-Run Mode

Validate patterns without API costs using the dry-run implementation:

import (
    "context"
    "github.com/danielmiessler/fabric/internal/plugins/ai/dryrun"
    "github.com/danielmiessler/fabric/internal/chat"
    "fmt"
)

func previewPattern() {
    // Initialize dry-run plugin
    dr := dryrun.NewPlugin()
    
    // Create test message
    msg := &chat.ChatCompletionMessage{
        Role:    "user",
        Content: "Summarize this article",
    }
    
    // Execute without network call
    result, _ := dr.Send(context.Background(), []*chat.ChatCompletionMessage{msg}, nil)
    fmt.Println("Would send:", result)
}

This corresponds to the --dry-run CLI flag and is implemented in internal/plugins/ai/dryrun/dryrun.go.

Summary

  • The internal/plugins/ai directory is Fabric’s AI vendor abstraction layer, located at the heart of the plugin architecture.
  • It defines a strict Vendor interface in vendor.go that standardizes model listing, chat completion, and streaming across all providers.
  • models.go provides helper utilities for grouping, filtering, and case-insensitive model lookup, powering CLI commands like --listmodels.
  • Each AI service (OpenAI, Anthropic, Gemini, Azure, Ollama, etc.) lives in its own sub-directory, implementing the Vendor interface with provider-specific HTTP clients and authentication.
  • dryrun/dryrun.go enables cost-free testing by implementing a no-network vendor that returns request payloads for the --dry-run flag.
  • Because the package lives under internal/, it enforces encapsulation, ensuring vendors are only accessed through the defined interfaces, making the system modular and extensible.

Frequently Asked Questions

What is the purpose of the internal/plugins/ai directory in Fabric?

The internal/plugins/ai directory serves as Fabric’s core AI vendor abstraction layer. It defines the Vendor interface and houses concrete implementations for every supported AI provider, allowing the rest of the application to interact with OpenAI, Anthropic, Gemini, and other services through a single, standardized API without handling provider-specific details.

How does Fabric add support for a new AI provider?

To add a new AI provider, developers create a new sub-directory under internal/plugins/ai/ (for example, newprovider/) and implement the Vendor interface defined in vendor.go. This requires implementing methods for listing models, sending chat requests, and handling streaming responses. Once implemented, the provider is registered in vendors.go, making it automatically available to the CLI and API without modifying other parts of the codebase.

What is the difference between vendor.go and vendors.go in the internal/plugins/ai directory?

vendor.go defines the abstract Vendor interface that specifies the contract all AI providers must fulfill, including method signatures for chat completion and model listing. In contrast, vendors.go acts as a concrete registry that imports and aggregates all available vendor implementations (OpenAI, Anthropic, etc.), providing a central point for the application to discover and instantiate specific providers at runtime.

How can I test Fabric patterns without consuming API credits?

Fabric provides a dry-run mode through the dryrun package located at internal/plugins/ai/dryrun/dryrun.go. You can activate this via the --dry-run CLI flag, which instantiates a special Vendor implementation that returns the would-be request payload without making actual HTTP calls. This allows you to validate pattern syntax, message formatting, and vendor selection logic without incurring costs or network latency.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →