Genkit Azure Function with Azure OpenAI
February 23, 2026 · View on GitHub
An Azure Function powered by Genkit and the Azure OpenAI plugin for AI-powered generation, using the onCallGenkit helper for streamlined Azure Functions integration.
Prerequisites
- Node.js 20 or later
- Azure Account with:
- Azure CLI configured
- Azure OpenAI resource deployed
- Access to GPT-4o or other Azure OpenAI models
- Azure Functions Core Tools v4
- Azure credentials configured
Installation
- Clone and install dependencies:
npm install
- Install Genkit CLI globally:
npm install -g genkit-cli
- Install Azure Functions Core Tools (if not already installed):
npm install -g azure-functions-core-tools@4
Configuration
Azure OpenAI Setup
- Create an Azure OpenAI resource in the Azure Portal
- Deploy a GPT-4o model (or another supported model)
- Get your endpoint and API key from the "Keys and Endpoint" section
Environment Variables
Create a .env file in the root directory:
.env file (for running npm run genkit:ui):
AZURE_OPENAI_ENDPOINT=https://your-resource-name.openai.azure.com/
AZURE_OPENAI_API_KEY=your-api-key-here
OPENAI_API_VERSION=2024-10-21
For production deployment, set these as Application Settings in your Azure Function App.
Local Development
Run with Azure Functions Core Tools (Recommended)
The best way to test the Azure Function locally with a real HTTP endpoint:
npm run func:start
This starts a local server at http://localhost:7071 that mimics the Azure Functions runtime. Test it with:
# Story generator (with CORS & debug enabled)
curl -X POST http://localhost:7071/api/storyGeneratorFlow \
-H "Content-Type: application/json" \
-d '{
"data": {
"topic": "a robot learning to feel emotions",
"style": "sci-fi",
"length": "medium"
}
}'
# Joke generator
curl -X POST http://localhost:7071/api/jokeFlow \
-H "Content-Type: application/json" \
-d '{
"data": {
"subject": "programming"
}
}'
# Streaming joke (SSE)
curl -X POST http://localhost:7071/api/jokeStreamingFlow \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"data": {
"subject": "TypeScript"
}
}'
# Protected summary (requires API key)
curl -X POST http://localhost:7071/api/protectedSummaryFlow \
-H "Content-Type: application/json" \
-H "X-API-Key: demo-api-key" \
-d '{
"data": {
"text": "Your long text here...",
"maxLength": 50
}
}'
Run with Genkit Dev UI
For testing and debugging the Genkit flow with visual traces:
npm run genkit:ui
This starts the Genkit Developer UI at http://localhost:4000. You can:
- Test the
storyGeneratorFlowwith different inputs - View detailed traces of AI generation
- Debug and optimize your prompts
Usage Examples
Flows & Endpoints
This sample registers 4 Azure Functions via onCallGenkit:
| Flow | Endpoint | Auth | Features |
|---|---|---|---|
storyGeneratorFlow | POST /api/storyGeneratorFlow | anonymous | CORS, debug |
jokeFlow | POST /api/jokeFlow | anonymous | Simplest form |
jokeStreamingFlow | POST /api/jokeStreamingFlow | anonymous | SSE streaming, CORS |
protectedSummaryFlow | POST /api/protectedSummaryFlow | API key (X-API-Key) | Auth, CORS, custom error handler |
Request Format (wrapped in data)
All requests use the genkit/beta/client protocol — input goes in a data envelope:
{
"data": {
"topic": "a time traveler discovering an ancient civilization",
"style": "mystery",
"length": "short"
}
}
Story Generator Parameters
topic(required): The main theme or topic for the storystyle(optional): Writing style (e.g., "adventure", "mystery", "sci-fi", "romance")length(optional): Story length -"short"(200-300 words),"medium"(500-700 words), or"long"(1000-1500 words)
Response Format
{
"result": {
"title": "Echoes of Atlantis",
"genre": "Mystery",
"story": "The full story text...",
"wordCount": 287,
"themes": ["time travel", "ancient mysteries", "discovery"]
}
}
Using the Genkit Client
You can also use the genkit/beta/client SDK to call these endpoints:
import { runFlow, streamFlow } from 'genkit/beta/client';
// Non-streaming
const result = await runFlow({
url: 'http://localhost:7071/api/jokeFlow',
input: { subject: 'programming' },
});
// Streaming
const result = streamFlow({
url: 'http://localhost:7071/api/jokeStreamingFlow',
input: { subject: 'TypeScript' },
});
for await (const chunk of result.stream) {
process.stdout.write(chunk);
}
const finalOutput = await result.output;
// With API key auth
const result = await runFlow({
url: 'http://localhost:7071/api/protectedSummaryFlow',
input: { text: 'Your long text...', maxLength: 50 },
headers: { 'X-API-Key': 'demo-api-key' },
});
Deployment
Prerequisites for Deployment
- Install Azure CLI:
# macOS
brew install azure-cli
# Or download from https://docs.microsoft.com/cli/azure/install-azure-cli
- Login to Azure:
az login
- Create a Function App (if you haven't already):
# Create a resource group
az group create --name myResourceGroup --location eastus
# Create a storage account
az storage account create --name mystorageaccount --location eastus --resource-group myResourceGroup --sku Standard_LRS
# Create a function app
az functionapp create --resource-group myResourceGroup --consumption-plan-location eastus \
--runtime node --runtime-version 20 --functions-version 4 \
--name myFunctionAppName --storage-account mystorageaccount
Configure Environment Variables in Azure
az functionapp config appsettings set --name myFunctionAppName --resource-group myResourceGroup \
--settings \
AZURE_OPENAI_ENDPOINT="https://your-resource-name.openai.azure.com/" \
AZURE_OPENAI_API_KEY="your-api-key-here" \
OPENAI_API_VERSION="2024-10-21"
Deploy to Azure
Important: This project requires remote build to install Node.js dependencies on Azure.
- Update the
deployscript inpackage.jsonwith your function app name:
"deploy": "func azure functionapp publish <YOUR_FUNCTION_APP_NAME> --build remote"
- Build the project locally:
npm run build
- Deploy with remote build (this installs dependencies on Azure):
npm run deploy
The --build remote flag tells Azure to:
- Install all npm dependencies from
package.json - Run the
postinstallscript which builds the TypeScript - Set up the function app correctly
After deployment, you'll see output like:
Functions in myFunctionAppName:
storyGenerator - [httpTrigger]
Invoke url: https://myfunctionappname.azurewebsites.net/api/generate
Note: The first deployment with remote build may take 3-5 minutes as Azure installs all dependencies.
Test the Deployed Function
curl -X POST https://myfunctionappname.azurewebsites.net/api/storyGeneratorFlow \
-H "Content-Type: application/json" \
-d '{
"data": {
"topic": "a robot learning to feel emotions",
"style": "sci-fi",
"length": "medium"
}
}'
Project Structure
.
├── src/
│ └── index.ts # Main Azure Function handler with Genkit flow
├── dist/ # Compiled JavaScript (generated by TypeScript)
├── host.json # Azure Functions host configuration
├── local.settings.json # Local config
├── .env # Environment variables
├── .funcignore # Files to exclude from deployment
├── .deployment # Azure deployment configuration
├── tsconfig.json # TypeScript configuration
├── package.json # Dependencies and scripts
└── README.md # This file
Configuration
Switching Azure OpenAI Models
Edit src/index.ts to use different Azure OpenAI models:
import { azureOpenAI, gpt4o, gpt35Turbo, onCallGenkit } from 'genkitx-azure-openai';
const ai = genkit({
plugins: [azureOpenAI()],
model: gpt35Turbo, // Change model here
});
Adjusting Function Resources
Edit the Function App settings in Azure Portal or using Azure CLI to change memory and timeout:
az functionapp config appsettings set --name myFunctionAppName --resource-group myResourceGroup \
--settings FUNCTIONS_WORKER_PROCESS_COUNT=1
Available Scripts
npm run build- Compile TypeScript to JavaScriptnpm start- Run the Genkit flow standalonenpm run genkit:ui- Start Genkit Developer UInpm run func:start- Start local Azure Functions runtime (requireslocal.settings.json)npm run deploy- Deploy to Azure with remote buildnpm run deploy- Deploy to Azure (update with your function app name)
Troubleshooting
"Authentication Failed" Error
Ensure your Azure OpenAI credentials are correctly set:
- Check
AZURE_OPENAI_ENDPOINTis correct - Verify
AZURE_OPENAI_API_KEYis valid - Confirm
OPENAI_API_VERSIONmatches your deployment
TypeScript Errors
Run npm install to ensure all dependencies are installed, including type definitions.
Function Not Starting Locally
Make sure you have:
- Installed Azure Functions Core Tools v4
- Created
.envfile with required environment variables - Built the TypeScript code with
npm run build
Deployment Issues
"Skipping build" error in Azure logs:
- Make sure you're using
--build remoteflag in the deploy command - Check
.funcignoredoesn't exclude TypeScript files - Verify
.deploymentfile exists with build configuration
"Not enough space on disk" during deployment:
- Ensure
.funcignoreexcludesnode_modulesdirectory - The deployment package should be ~67KB, not 600MB+
- Azure will install dependencies via remote build
Function not showing in Azure:
- Wait 3-5 minutes after deployment for remote build to complete
- Check Azure Portal → Deployment Center for build logs
- Verify environment variables are set in Application Settings
Using Azure Managed Identity (Optional)
For production, you can use Azure Managed Identity instead of API keys:
- Enable Managed Identity on your Function App
- Grant access to Azure OpenAI
- Update
src/index.ts:
import { DefaultAzureCredential, getBearerTokenProvider } from '@azure/identity';
const credential = new DefaultAzureCredential();
const scope = 'https://cognitiveservices.azure.com/.default';
const azureADTokenProvider = getBearerTokenProvider(credential, scope);
const ai = genkit({
plugins: [
azureOpenAI({
azureADTokenProvider,
endpoint: process.env.AZURE_OPENAI_ENDPOINT!,
apiVersion: process.env.OPENAI_API_VERSION!,
}),
],
model: gpt4o,
});
Learn More
License
Apache-2.0