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

> Discover the purpose of the internal plugins ai directory in Fabric. Learn how this AI vendor abstraction layer unifies communication with multiple AI providers using a single Vendor interface.

- Repository: [Daniel Miessler 🛡️/fabric](https://github.com/danielmiessler/fabric)
- Tags: internals
- Published: 2026-02-28

---

**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`](https://github.com/danielmiessler/fabric/blob/main/vendor.go))

At the heart of the directory is the **`Vendor`** interface defined in [`internal/plugins/ai/vendor.go`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/models.go))

The [`internal/plugins/ai/models.go`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/vendors.go))

The [`internal/plugins/ai/vendors.go`](https://github.com/danielmiessler/fabric/blob/main/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:

- **`openai/`** – OpenAI GPT models ([`openai/openai.go`](https://github.com/danielmiessler/fabric/blob/main/openai/openai.go))
- **`anthropic/`** – Claude models ([`anthropic/anthropic.go`](https://github.com/danielmiessler/fabric/blob/main/anthropic/anthropic.go))
- **`azure/`** – Azure OpenAI Service ([`azure/azure.go`](https://github.com/danielmiessler/fabric/blob/main/azure/azure.go))
- **`vertexai/`** – Google Vertex AI ([`vertexai/vertexai.go`](https://github.com/danielmiessler/fabric/blob/main/vertexai/vertexai.go))
- **`ollama/`** – Local Ollama instances ([`ollama/ollama.go`](https://github.com/danielmiessler/fabric/blob/main/ollama/ollama.go))
- **`digitalocean/`** – DigitalOcean GenAI Platform ([`digitalocean/digitalocean.go`](https://github.com/danielmiessler/fabric/blob/main/digitalocean/digitalocean.go))
- **`perplexity/`** – Perplexity API ([`perplexity/perplexity.go`](https://github.com/danielmiessler/fabric/blob/main/perplexity/perplexity.go))
- **`lmstudio/`** – LM Studio local server ([`lmstudio/lmstudio.go`](https://github.com/danielmiessler/fabric/blob/main/lmstudio/lmstudio.go))

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`](https://github.com/danielmiessler/fabric/blob/main/dryrun/dryrun.go))

For testing and development, [`internal/plugins/ai/dryrun/dryrun.go`](https://github.com/danielmiessler/fabric/blob/main/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:

```bash
fabric --listvendors

```

This command queries the registry in [`vendors.go`](https://github.com/danielmiessler/fabric/blob/main/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:

```go
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`](https://github.com/danielmiessler/fabric/blob/main/internal/plugins/ai/models.go).

### Direct Vendor Integration

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

```go
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`](https://github.com/danielmiessler/fabric/blob/main/vendor.go).

### Testing with Dry-Run Mode

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

```go
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`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/vendor.go) that standardizes model listing, chat completion, and streaming across all providers.
- **[`models.go`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/vendor.go) and [`vendors.go`](https://github.com/danielmiessler/fabric/blob/main/vendors.go) in the `internal/plugins/ai` directory?

[`vendor.go`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/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`](https://github.com/danielmiessler/fabric/blob/main/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.