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

  1. Clone and install dependencies:
npm install
  1. Install Genkit CLI globally:
npm install -g genkit-cli
  1. Install Azure Functions Core Tools (if not already installed):
npm install -g azure-functions-core-tools@4

Configuration

Azure OpenAI Setup

  1. Create an Azure OpenAI resource in the Azure Portal
  2. Deploy a GPT-4o model (or another supported model)
  3. 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

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 storyGeneratorFlow with 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:

FlowEndpointAuthFeatures
storyGeneratorFlowPOST /api/storyGeneratorFlowanonymousCORS, debug
jokeFlowPOST /api/jokeFlowanonymousSimplest form
jokeStreamingFlowPOST /api/jokeStreamingFlowanonymousSSE streaming, CORS
protectedSummaryFlowPOST /api/protectedSummaryFlowAPI 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 story
  • style (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

  1. Install Azure CLI:
# macOS
brew install azure-cli

# Or download from https://docs.microsoft.com/cli/azure/install-azure-cli
  1. Login to Azure:
az login
  1. 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.

  1. Update the deploy script in package.json with your function app name:
"deploy": "func azure functionapp publish <YOUR_FUNCTION_APP_NAME> --build remote"
  1. Build the project locally:
npm run build
  1. 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 postinstall script 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 JavaScript
  • npm start - Run the Genkit flow standalone
  • npm run genkit:ui - Start Genkit Developer UI
  • npm run func:start - Start local Azure Functions runtime (requires local.settings.json)
  • npm run deploy - Deploy to Azure with remote build
  • npm 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_ENDPOINT is correct
  • Verify AZURE_OPENAI_API_KEY is valid
  • Confirm OPENAI_API_VERSION matches 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 .env file 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 remote flag in the deploy command
  • Check .funcignore doesn't exclude TypeScript files
  • Verify .deployment file exists with build configuration

"Not enough space on disk" during deployment:

  • Ensure .funcignore excludes node_modules directory
  • 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:

  1. Enable Managed Identity on your Function App
  2. Grant access to Azure OpenAI
  3. 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