Skip to content

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.

Terminal window
go get github.com/xavidop/genkit-azure-foundry-go
  • Text Generation: Support for GPT models
  • Embeddings: Support for text-embedding models
  • 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
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())
}
}

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
}
OptionTypeDefaultDescription
EndpointstringrequiredAzure OpenAI endpoint URL
APIKeystring""API key for authentication
Credentialazcore.TokenCredentialnilAzure credential (alternative to API key)
APIVersionstringLatestAPI version to use
  1. Go to Azure Portal
  2. Navigate to your Azure OpenAI resource
  3. Go to “Keys and Endpoint” section
  4. Copy your endpoint URL and API key

The plugin supports multiple authentication methods to suit different deployment scenarios:

Best for: Development, testing, and simple scenarios

Terminal window
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"),
}
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:

  1. Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)
  2. Managed Identity (when deployed to Azure)
  3. Azure CLI credentials (for local development)
  4. Azure PowerShell credentials
  5. Interactive browser authentication
Terminal window
# Required environment variables
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_TENANT_ID="your-tenant-id"
# Optional: For service principal authentication
export 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...
}

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

Terminal window
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

Terminal window
# Login to Azure CLI first
az 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,
}
}

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.

FieldTypeDescription
NamestringYour deployment name in Azure, not the model name. If you deployed gpt-5 as my-gpt5-deployment, use "my-gpt5-deployment".
TypestringOne of the ModelType constants below. Left empty, the type is inferred from Name.
MaxTokensint32Default maximum output tokens. A per-call value wins.
SupportsMediaboolWhether 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:

ConstantValueUse 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.

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.

Generate images with DALL-E models using the standard genkit.Generate() method:

// Define DALL-E model
dallE3 := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{
Name: azureaifoundry.ModelDallE3,
Type: azureaifoundry.ModelTypeImage,
}, nil)
// Generate image
response, 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:

OptionTypeDescription
nintNumber of images, 1 to 10. Default 1.
sizestring256x256, 512x512, 1024x1024, 1792x1024, 1024x1792. Default 1024x1024.
qualitystringstandard or hd. DALL-E 3 only. Default standard.
stylestringvivid or natural. DALL-E 3 only. Default vivid.
response_formatstringurl or b64_json. Default url.

Convert text to speech using the standard genkit.Generate() method:

import (
"encoding/base64"
"strings"
)
// Define TTS model
ttsModel := azurePlugin.DefineModel(g, azureaifoundry.ModelDefinition{
Name: azureaifoundry.ModelTTS1HD,
Type: azureaifoundry.ModelTypeTextToSpeech,
}, nil)
// Generate speech
response, 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:

OptionTypeDescription
voicestringalloy, echo, fable, onyx, nova, shimmer. Default alloy.
response_formatstringmp3, opus, aac, flac, wav, pcm. Default mp3. The media part’s content type follows this.
speedfloat0.25 to 4.0. Default 1.0.

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 file
audioData, _ := os.ReadFile("audio.mp3")
base64Audio := base64.StdEncoding.EncodeToString(audioData)
// Transcribe audio
response, 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:

OptionTypeDescription
languagestringInput language code, for example en or es. Improves accuracy when you know it.
promptstringFree text that guides the model’s style and spelling.
response_formatstringjson, text, srt, verbose_json, vtt. Default json.
temperaturefloat0 to 1.