Azure Foundry plugin
Azure AI Foundry plugin for Genkit Go that provides text generation and chat capabilities using Azure OpenAI and other models available through Azure AI Foundry. The plugin is maintained in the azure-foundry-go-plugin repository.
Installation
Section titled “Installation”go get github.com/xavidop/genkit-azure-foundry-goFeatures
Section titled “Features”- Text Generation: Support for
GPTmodels - Embeddings: Support for
text-embeddingmodels - Image Generation: Support for creating images from text prompts
- Text-to-Speech: Convert text to natural-sounding speech with multiple voices
- Speech-to-Text: Transcribe audio to text with subtitle support
- Streaming: Full streaming support for real-time responses
- Tool Calling: Complete function calling capabilities
- Multimodal Support: Support for text + image inputs
- Multi-turn Conversations: Full support for chat history and context management
- Type Safety: Robust type conversion and schema validation
- Flexible Authentication: Support for API keys, Azure Default Credential, and custom token credentials
Initialize the Plugin
Section titled “Initialize the Plugin”package main
import ( "context" "log" "os"
"github.com/firebase/genkit/go/ai" "github.com/firebase/genkit/go/genkit" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
func main() { ctx := context.Background()
// Initialize Azure AI Foundry plugin azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: os.Getenv("AZURE_OPENAI_ENDPOINT"), APIKey: os.Getenv("AZURE_OPENAI_API_KEY"), }
// Initialize Genkit g := genkit.Init(ctx, genkit.WithPlugins(azurePlugin), genkit.WithDefaultModel("azureaifoundry/my-gpt5-deployment"), )
log.Println("Starting basic Azure AI Foundry example...")
// Define your GPT-5 deployment. The plugin registers nothing at Init and // has no dynamic resolver, so a name that was never defined does not // resolve at Generate time. gpt5Model := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{ Name: "my-gpt5-deployment", // Your deployment name in Azure Type: azureaifoundry.ModelTypeChat, SupportsMedia: true, }, nil)
// Example: Generate text (basic usage) response, err := genkit.Generate(ctx, g, ai.WithModel(gpt5Model), ai.WithPrompt("What are the key benefits of using Azure AI Foundry?"), ) if err != nil { log.Printf("Error: %v", err) } else { log.Printf("Response: %s", response.Text()) }}Configuration Options
Section titled “Configuration Options”The plugin supports various configuration options:
azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: "https://your-resource.openai.azure.com/", APIKey: "your-api-key", // Use API key // OR use Azure credential // Credential: azidentity.NewDefaultAzureCredential(), APIVersion: "2024-02-15-preview", // Optional}Available Configuration
Section titled “Available Configuration”| Option | Type | Default | Description |
|---|---|---|---|
Endpoint | string | required | Azure OpenAI endpoint URL |
APIKey | string | "" | API key for authentication |
Credential | azcore.TokenCredential | nil | Azure credential (alternative to API key) |
APIVersion | string | Latest | API version to use |
Azure Setup and Authentication
Section titled “Azure Setup and Authentication”Getting Your Endpoint and API Key
Section titled “Getting Your Endpoint and API Key”- Go to Azure Portal
- Navigate to your Azure OpenAI resource
- Go to “Keys and Endpoint” section
- Copy your endpoint URL and API key
Authentication Methods
Section titled “Authentication Methods”The plugin supports multiple authentication methods to suit different deployment scenarios:
1. API Key Authentication (Quick Start)
Section titled “1. API Key Authentication (Quick Start)”Best for: Development, testing, and simple scenarios
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"export AZURE_OPENAI_API_KEY="your-api-key"import ( "os" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: os.Getenv("AZURE_OPENAI_ENDPOINT"), APIKey: os.Getenv("AZURE_OPENAI_API_KEY"),}2. Azure Default Credential (Recommended for Production)
Section titled “2. Azure Default Credential (Recommended for Production)”Best for: Production deployments, Azure-hosted applications
DefaultAzureCredential automatically tries multiple authentication methods in the following order:
- Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)
- Managed Identity (when deployed to Azure)
- Azure CLI credentials (for local development)
- Azure PowerShell credentials
- Interactive browser authentication
# Required environment variablesexport AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"export AZURE_TENANT_ID="your-tenant-id"
# Optional: For service principal authenticationexport AZURE_CLIENT_ID="your-client-id"export AZURE_CLIENT_SECRET="your-client-secret"import ( "fmt" "os" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
func main() { endpoint := os.Getenv("AZURE_OPENAI_ENDPOINT") tenantID := os.Getenv("AZURE_TENANT_ID")
// Create DefaultAzureCredential credential, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{ TenantID: tenantID, }) if err != nil { fmt.Fprintf(os.Stderr, "ERROR: %s\n", err) return }
// Initialize plugin with credential azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: endpoint, Credential: credential, }
// Use the plugin with Genkit...}3. Managed Identity (Azure Deployments)
Section titled “3. Managed Identity (Azure Deployments)”Best for: Applications deployed to Azure (App Service, Container Apps, VMs, AKS)
When deployed to Azure, Managed Identity provides authentication without storing credentials:
import ( "os" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
func main() { endpoint := os.Getenv("AZURE_OPENAI_ENDPOINT")
// Use Managed Identity credential, err := azidentity.NewManagedIdentityCredential(nil) if err != nil { panic(err) }
azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: endpoint, Credential: credential, }}4. Client Secret Credential (Service Principal)
Section titled “4. Client Secret Credential (Service Principal)”Best for: CI/CD pipelines, automated deployments
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"export AZURE_TENANT_ID="your-tenant-id"export AZURE_CLIENT_ID="your-client-id"export AZURE_CLIENT_SECRET="your-client-secret"import ( "os" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
func main() { endpoint := os.Getenv("AZURE_OPENAI_ENDPOINT") tenantID := os.Getenv("AZURE_TENANT_ID") clientID := os.Getenv("AZURE_CLIENT_ID") clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
credential, err := azidentity.NewClientSecretCredential(tenantID, clientID, clientSecret, nil) if err != nil { panic(err) }
azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: endpoint, Credential: credential, }}5. Azure CLI Credential (Local Development)
Section titled “5. Azure CLI Credential (Local Development)”Best for: Local development with Azure CLI installed
# Login to Azure CLI firstaz login
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"import ( "os" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" azureaifoundry "github.com/xavidop/genkit-azure-foundry-go")
func main() { endpoint := os.Getenv("AZURE_OPENAI_ENDPOINT")
// Use Azure CLI credentials credential, err := azidentity.NewAzureCLICredential(nil) if err != nil { panic(err) }
azurePlugin := &azureaifoundry.AzureAIFoundry{ Endpoint: endpoint, Credential: credential, }}Model Deployments
Section titled “Model Deployments”Every model you generate with has to be defined first: the plugin registers nothing at Init and has no dynamic resolver. ModelDefinition describes one deployment.
| Field | Type | Description |
|---|---|---|
Name | string | Your deployment name in Azure, not the model name. If you deployed gpt-5 as my-gpt5-deployment, use "my-gpt5-deployment". |
Type | string | One of the ModelType constants below. Left empty, the type is inferred from Name. |
MaxTokens | int32 | Default maximum output tokens. A per-call value wins. |
SupportsMedia | bool | Whether the deployment takes images or audio as input. Required for a model you send media to. |
Type decides which Azure API the request goes to, so it has to match the deployment:
| Constant | Value | Use for |
|---|---|---|
azureaifoundry.ModelTypeChat | "chat" | Chat and text deployments |
azureaifoundry.ModelTypeText | "text" | Same path as chat |
azureaifoundry.ModelTypeImage | "image" | DALL-E, GPT Image |
azureaifoundry.ModelTypeTextToSpeech | "text-to-speech" | TTS deployments |
azureaifoundry.ModelTypeSpeechToText | "speech-to-text" | Whisper, transcription |
azureaifoundry.DefineCommonModels(azurePlugin, g) registers chat deployments named gpt-5, gpt-5-mini, gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4, and gpt-35-turbo, and DefineCommonEmbedders(azurePlugin, g) does the same for text-embedding-ada-002, text-embedding-3-small, and text-embedding-3-large. Both take the plugin first and g second, unlike the g-first order used elsewhere in Genkit Go. They only help if your deployment names happen to match those model names.
For more Genkit features like embeddings, structured output, and flows, refer to the Genkit documentation.
Non-chat configuration
Section titled “Non-chat configuration”Image, text-to-speech, and speech-to-text requests take an untyped map[string]any config. Unlike the typed configs on the first-party provider pages, these keys go to Azure verbatim and are not validated against a schema, so a misspelled key or an out-of-range value fails at Azure rather than locally. The keys are Azure OpenAI’s own wire names; the tables below list what the plugin forwards, and the linked REST references are authoritative on the accepted values.
Image Generation
Section titled “Image Generation”Generate images with DALL-E models using the standard genkit.Generate() method:
// Define DALL-E modeldallE3 := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{ Name: azureaifoundry.ModelDallE3, Type: azureaifoundry.ModelTypeImage,}, nil)
// Generate imageresponse, err := genkit.Generate(ctx, g, ai.WithModel(dallE3), ai.WithPrompt("A serene landscape with mountains at sunset"), ai.WithConfig(map[string]any{ "quality": "hd", "size": "1024x1024", "style": "vivid", }),)
if err != nil { log.Fatal(err)}
for _, part := range response.MediaParts() { log.Printf("%s: %s", part.ContentType, part.Text)}Generated images come back as media parts with content type image/png, one per image. part.Text holds either the Azure URL or a data:image/png;base64,... URL, depending on response_format.
Configuration keys, per the image generation REST reference:
| Option | Type | Description |
|---|---|---|
n | int | Number of images, 1 to 10. Default 1. |
size | string | 256x256, 512x512, 1024x1024, 1792x1024, 1024x1792. Default 1024x1024. |
quality | string | standard or hd. DALL-E 3 only. Default standard. |
style | string | vivid or natural. DALL-E 3 only. Default vivid. |
response_format | string | url or b64_json. Default url. |
Text-to-Speech
Section titled “Text-to-Speech”Convert text to speech using the standard genkit.Generate() method:
import ( "encoding/base64" "strings")
// Define TTS modelttsModel := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{ Name: azureaifoundry.ModelTTS1HD, Type: azureaifoundry.ModelTypeTextToSpeech,}, nil)
// Generate speechresponse, err := genkit.Generate(ctx, g, ai.WithModel(ttsModel), ai.WithPrompt("Hello! Welcome to Azure AI Foundry."), ai.WithConfig(map[string]any{ "voice": "nova", "response_format": "mp3", "speed": 1.5, }),)
if err != nil { log.Fatal(err)}
// The audio arrives as a media part holding a data URL._, encoded, _ := strings.Cut(response.Media(), ",")audioData, err := base64.StdEncoding.DecodeString(encoded)if err != nil { log.Fatal(err)}os.WriteFile("output.mp3", audioData, 0644)Configuration keys, per the audio generation REST reference:
| Option | Type | Description |
|---|---|---|
voice | string | alloy, echo, fable, onyx, nova, shimmer. Default alloy. |
response_format | string | mp3, opus, aac, flac, wav, pcm. Default mp3. The media part’s content type follows this. |
speed | float | 0.25 to 4.0. Default 1.0. |
Speech-to-Text
Section titled “Speech-to-Text”Transcribe audio to text using the standard genkit.Generate() method:
import "encoding/base64"
// Define Whisper model with media support (required for audio input)whisperModel := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{ Name: azureaifoundry.ModelWhisper1, Type: azureaifoundry.ModelTypeSpeechToText, SupportsMedia: true, // Required for media parts (audio)}, nil)
// Read and encode audio fileaudioData, _ := os.ReadFile("audio.mp3")base64Audio := base64.StdEncoding.EncodeToString(audioData)
// Transcribe audioresponse, err := genkit.Generate(ctx, g, ai.WithModel(whisperModel), ai.WithMessages(ai.NewUserMessage( ai.NewMediaPart("audio/mp3", "data:audio/mp3;base64,"+base64Audio), )), ai.WithConfig(map[string]any{ "language": "en", }),)
if err != nil { log.Fatal(err)}
log.Printf("Transcription: %s", response.Text())The transcript is the one modality that does come back as text, so response.Text() is right here.
Configuration keys, per the audio transcription REST reference:
| Option | Type | Description |
|---|---|---|
language | string | Input language code, for example en or es. Improves accuracy when you know it. |
prompt | string | Free text that guides the model’s style and spelling. |
response_format | string | json, text, srt, verbose_json, vtt. Default json. |
temperature | float | 0 to 1. |