Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build serverless applications with Azure Functions. Create HTTP and event-driven functions with input/output bindings, configure triggers for queues, timers, and blob storage. Use Durable Functions for stateful orchestration workflows.
.claude/skills/terminalskills-azure-functions/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 92% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 104% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 193% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 268% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 10% | 0% |
Azure Functions is a serverless compute service that runs event-driven code without managing infrastructure. Its unique binding system connects to Azure services declaratively, and Durable Functions enable complex stateful workflows.
bash# Create a new function project func init my-functions --worker-runtime node --language javascript cd my-functions
bash# Create a new HTTP-triggered function func new --name HandleWebhook --template "HTTP trigger" --authlevel anonymous
bash# Create Azure resources az group create --name my-app-rg --location eastus az storage account create \ --name myappfuncstorage \ --resource-group my-app-rg \ --sku Standard_LRS az functionapp create \ --name my-app-functions \ --resource-group my-app-rg \ --storage-account myappfuncstorage \ --consumption-plan-location eastus \ --runtime node \ --runtime-version 20 \ --functions-version 4
javascript// src/functions/handleWebhook.js — HTTP triggered function const { app } = require('@azure/functions'); app.http('handleWebhook', { methods: ['POST'], authLevel: 'anonymous', route: 'webhooks/{source}', handler: async (request, context) => { const source = request.params.source; const body = await request.json(); context.log(`Webhook from ${source}:`, body); // Process webhook const result = await processWebhook(source, body); return { status: 200, jsonBody: { received: true, id: result.id } }; } });
javascript// src/functions/dailyCleanup.js — runs on a CRON schedule const { app } = require('@azure/functions'); app.timer('dailyCleanup', { schedule: '0 0 2 * * *', // 2:00 AM daily handler: async (myTimer, context) => { context.log('Running daily cleanup at', new Date().toISOString()); const deleted = await cleanupExpiredSessions(); context.log(`Deleted ${deleted} expired sessions`); } });
javascript// src/functions/processOrder.js — triggered by queue, writes to Cosmos DB const { app, output } = require('@azure/functions'); const cosmosOutput = output.cosmosDB({ databaseName: 'app-db', containerName: 'processed-orders', connection: 'CosmosDBConnection', createIfNotExists: true }); app.storageQueue('processOrder', { queueName: 'order-queue', connection: 'AzureWebJobsStorage', return: cosmosOutput, handler: async (queueItem, context) => { context.log('Processing order:', queueItem.orderId); const processedOrder = { id: queueItem.orderId, ...queueItem, status: 'processed', processedAt: new Date().toISOString() }; // Returned value goes to Cosmos DB via output binding return processedOrder; } });
javascript// src/functions/processImage.js — triggered when blob is uploaded const { app } = require('@azure/functions'); app.storageBlob('processImage', { path: 'uploads/{name}', connection: 'AzureWebJobsStorage', handler: async (blob, context) => { const fileName = context.triggerMetadata.name; context.log(`Processing blob: ${fileName}, size: ${blob.length} bytes`); // Resize image, extract metadata, etc. await generateThumbnail(blob, fileName); } });
javascript// src/functions/orderOrchestrator.js — orchestrate multi-step order processing const { app } = require('@azure/functions'); const df = require('durable-functions'); // Orchestrator function df.app.orchestration('orderOrchestrator', function* (context) { const order = context.df.getInput(); // Step 1: Validate inventory const inventory = yield context.df.callActivity('checkInventory', order.items); if (!inventory.available) { yield context.df.callActivity('notifyCustomer', { orderId: order.id, message: 'Items out of stock' }); return { status: 'cancelled', reason: 'out_of_stock' }; } // Step 2: Process payment const payment = yield context.df.callActivity('processPayment', { amount: order.total, customerId: order.customerId }); // Step 3: Ship order (with retry) const retryOptions = new df.RetryOptions(5000, 3); // 5s interval, 3 attempts const shipment = yield context.df.callActivityWithRetry( 'shipOrder', retryOptions, order ); // Step 4: Notify customer yield context.df.callActivity('notifyCustomer', { orderId: order.id, message: `Shipped! Tracking: ${shipment.trackingNumber}` }); return { status: 'completed', tracking: shipment.trackingNumber }; }); // Activity functions df.app.activity('checkInventory', { handler: async (items) => { /* ... */ } }); df.app.activity('processPayment', { handler: async (payment) => { /* ... */ } }); df.app.activity('shipOrder', { handler: async (order) => { /* ... */ } }); df.app.activity('notifyCustomer', { handler: async (notification) => { /* ... */ } }); // HTTP starter app.http('startOrder', { route: 'orders/start', methods: ['POST'], extraInputs: [df.input.durableClient()], handler: async (req, context) => { const client = df.getClient(context); const order = await req.json(); const instanceId = await client.startNew('orderOrchestrator', { input: order }); return client.createCheckStatusResponse(req, instanceId); } });
bash# Deploy to Azure func azure functionapp publish my-app-functions
bash# Set application settings az functionapp config appsettings set \ --name my-app-functions \ --resource-group my-app-rg \ --settings "CosmosDBConnection=AccountEndpoint=..."
bash# View function logs func azure functionapp logstream my-app-functions
FUNCTIONS_WORKER_PROCESS_COUNT for CPU-bound workloads| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 9,168 | 7,047 | -23% | 1 | 1 | 0% | 1,722 | 3,314 | +92% | 0 | 0 | — |
case-06 | pass→pass | 4,099 | 3,235 | -21% | 1 | 1 | 0% | 622 | 2,288 | +268% | 0 | 0 | — |
case-02 | pass→pass | 17,560 | 11,354 | -35% | 1 | 1 | 0% | 3,989 | 4,395 | +10% | 0 | 0 | — |
case-03 | pass→pass | 8,165 | 6,469 | -21% | 1 | 1 | 0% | 1,627 | 3,283 | +102% | 0 | 0 | — |
case-04 | pass→pass | 18,622 | 12,723 | -32% | 1 | 1 | 0% | 2,697 | 4,755 | +76% | 0 | 0 | — |
case-05 | pass→pass | 8,601 | 9,038 | +5% | 1 | 1 | 0% | 1,753 | 3,229 | +84% | 0 | 0 | — |
case-11 | pass→pass | 8,748 | 6,007 | -31% | 1 | 1 | 0% | 1,760 | 2,995 | +70% | 0 | 0 | — |
case-07 | pass→pass | 2,616 | 1,879 | -28% | 1 | 1 | 0% | 452 | 2,142 | +374% | 0 | 0 | — |
case-08 | pass→pass | 4,528 | 2,862 | -37% | 1 | 1 | 0% | 948 | 2,330 | +146% | 0 | 0 | — |
case-09 | pass→pass | 7,827 | 4,877 | -38% | 1 | 1 | 0% | 1,384 | 2,724 | +97% | 0 | 0 | — |
case-10 | pass→pass | 5,124 | 4,535 | -11% | 1 | 1 | 0% | 1,066 | 2,791 | +162% | 0 | 0 | — |
case-12 | fail→pass | 5,890 | 3,370 | -43% | 1 | 1 | 0% | 1,220 | 2,494 | +104% | 0 | 0 | — |
case-13 | pass→pass | 8,450 | 3,935 | -53% | 1 | 1 | 0% | 1,312 | 2,585 | +97% | 0 | 0 | — |
case-14 | pass→pass | 2,620 | 1,557 | -41% | 1 | 1 | 0% | 432 | 1,990 | +361% | 0 | 0 | — |
case-15 | fail→pass | 4,019 | 3,211 | -20% | 1 | 1 | 0% | 831 | 2,433 | +193% | 0 | 0 | — |
case-16 | pass→pass | 2,680 | 1,281 | -52% | 1 | 1 | 0% | 486 | 2,007 | +313% | 0 | 0 | — |
case-17 | pass→pass | 5,148 | 4,810 | -7% | 1 | 1 | 0% | 1,201 | 2,840 | +136% | 0 | 0 | — |
case-18 | fail→fail | 4,651 | 3,636 | -22% | 1 | 1 | 0% | 930 | 2,527 | +172% | 0 | 0 | — |
case-19 | pass→pass | 13,041 | 11,897 | -9% | 1 | 1 | 0% | 2,758 | 4,434 | +61% | 0 | 0 | — |
case-20 | pass→pass | 3,381 | 2,274 | -33% | 1 | 1 | 0% | 679 | 2,145 | +216% | 0 | 0 | — |
case-21 | pass→pass | 7,734 | 7,034 | -9% | 1 | 1 | 0% | 1,631 | 2,987 | +83% | 0 | 0 | — |
case-22 | pass→pass | 7,042 | 4,197 | -40% | 1 | 1 | 0% | 1,469 | 2,663 | +81% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.