> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dartantic.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Providers

> Create your own providers and use them like the built-in providers.

Your provider can expose a `ChatModel`, an `EmbeddingsModel` or both.

## Dependencies

You do not need to depend on the `dartantic_ai` package to create a custom
provider. The `dartantic_interface` package is all you need.

```yaml theme={null}
dependencies:
  dartantic_interface: ^VERSION
```

## Creating a Custom Provider

Here's a simple example of a custom provider that exposes a `ChatModel`:

```dart theme={null}
class EchoProvider extends Provider<
  ChatModelOptions,
  EmbeddingsModelOptions,
  MediaGenerationModelOptions
> {
  EchoProvider()
    : super(
        name: 'echo',
        displayName: 'Echo',
        defaultModelNames: {ModelKind.chat: 'echo'},
      );

  @override
  ChatModel<ChatModelOptions> createChatModel({
    String? name,
    List<Tool<Object>>? tools,
    double? temperature,
    ChatModelOptions? options,
  }) => EchoChatModel(
    name: name ?? defaultModelNames[ModelKind.chat]!,
    defaultOptions: options,
  );
  
  @override
  MediaGenerationModel<MediaGenerationModelOptions> createMediaModel({
    String? name,
    List<Tool>? tools,
    MediaGenerationModelOptions? options,
  }) => throw UnsupportedError('Media generation not supported');
  
  // ... other required methods
}
```

## Custom Model

Here's a minimal chat model example:

```dart theme={null}
class EchoChatModel extends ChatModel<ChatModelOptions> {
  EchoChatModel({required super.name, ChatModelOptions? defaultOptions})
    : super(defaultOptions: defaultOptions ?? const ChatModelOptions());

  @override
  Stream<ChatResult<ChatMessage>> sendStream(
    List<ChatMessage> messages, {
    ChatModelOptions? options,
    Schema? outputSchema,
  }) {
    // Echo back the last user message
    return Stream.fromIterable([
      ChatResult<ChatMessage>(
        output: ChatMessage.fromJson(
          messages.last.toJson()..['role'] = 'model',
        ),
      ),
    ]);
  }
}
```

With your custom provider, you can use it with an agent directly:

```dart theme={null}
final agent = Agent.forProvider(EchoProvider());
final result = await agent.send('Hello!');
print(result.output);
```

## Dynamic Provider Registration

If you'd like to participate in the named lookup of providers, you can add your
custom provider to the factory registry:

```dart theme={null}
// Add your custom provider factory to the registry
Agent.providerFactories['echo'] = EchoProvider.new;

// Use it like any built-in provider
final agent = Agent('echo');
final result = await agent.send('Hello!');
print(result.output);
```

Note: The registry maps provider names to factory functions (`Provider
Function()`), not instances. Each time a provider is requested, a fresh instance
is created.

## Examples

* [Custom
  Provider](https://github.com/csells/dartantic_ai/blob/main/packages/dartantic_ai/example/bin/custom_provider.dart)

## Next Steps

* [Providers](/providers) - Current built-in providers
* [Environment Setup](/environment-setup) - Configure API keys
