AgentStack
SKILL unreviewed MIT Self-run

Azure Functions

skill-managedcode-dotnet-skills-azure-functions · by managedcode

Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable Functions, bindings, or host configuration. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific g…

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-managedcode-dotnet-skills-azure-functions

Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Dangerous shell/eval execution.

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution Used

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Azure Functions? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Azure Functions for .NET

Trigger On

  • working on Azure Functions in .NET
  • migrating from the in-process model to the isolated worker model
  • adding Durable Functions, bindings, or host configuration

Documentation

References

  • [Patterns](references/patterns.md) - Isolated worker patterns, Durable Functions patterns, advanced binding patterns
  • [Anti-Patterns](references/anti-patterns.md) - Common Azure Functions mistakes and how to avoid them

Workflow

  1. Use isolated worker model for all new work:
  • In-process model reaches end of support on November 10, 2026
  • Runtime v1.x ends support on September 14, 2026
  • Target .NET 8+ for longest support window
  1. Detect current project shape:
  • Target framework and runtime version
  • Worker model (isolated vs in-process)
  • Binding packages and host configuration
  1. Use standard .NET patterns in isolated model:
  • Normal dependency injection
  • Middleware pipeline
  • IOptions for configuration
  • ILogger for logging
  1. For Durable Functions:
  • Validate orchestration determinism constraints
  • Handle replay behavior correctly
  • Use typed activity patterns
  1. Verify both local and deployment behavior.

Isolated Worker Model Setup

Basic Function with DI

// Program.cs
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddSingleton();
    })
    .Build();

host.Run();

HTTP Trigger Function

public class HttpFunctions(ILogger logger, IMyService myService)
{
    [Function("GetItems")]
    public async Task GetItems(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "items")] HttpRequest req)
    {
        logger.LogInformation("Processing GetItems request");
        var items = await myService.GetItemsAsync();
        return new OkObjectResult(items);
    }
}

Queue Trigger with Options

public class QueueFunctions(ILogger logger, IOptions options)
{
    [Function("ProcessMessage")]
    public async Task ProcessMessage(
        [QueueTrigger("myqueue", Connection = "AzureWebJobsStorage")] string message)
    {
        logger.LogInformation("Processing message: {Message}", message);
        // Process with retry policy from options
    }
}

Middleware Pattern

Custom Middleware

// Program.cs
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication(builder =>
    {
        builder.UseMiddleware();
        builder.UseMiddleware();
    })
    .Build();

// CorrelationIdMiddleware.cs
public class CorrelationIdMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var correlationId = context.Features.Get()?.Headers["X-Correlation-Id"]
            ?? Guid.NewGuid().ToString();

        context.Items["CorrelationId"] = correlationId;

        await next(context);
    }
}

Durable Functions Patterns

Function Chaining

[Function(nameof(ChainOrchestrator))]
public static async Task ChainOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var result1 = await context.CallActivityAsync(nameof(Step1), "input");
    var result2 = await context.CallActivityAsync(nameof(Step2), result1);
    var result3 = await context.CallActivityAsync(nameof(Step3), result2);
    return result3;
}

[Function(nameof(Step1))]
public static string Step1([ActivityTrigger] string input) => $"Step1({input})";

[Function(nameof(Step2))]
public static string Step2([ActivityTrigger] string input) => $"Step2({input})";

[Function(nameof(Step3))]
public static string Step3([ActivityTrigger] string input) => $"Step3({input})";

Fan-Out/Fan-In

[Function(nameof(FanOutFanInOrchestrator))]
public static async Task FanOutFanInOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var workItems = await context.CallActivityAsync(nameof(GetWorkItems), null);

    // Fan out - process all items in parallel
    var tasks = workItems.Select(item =>
        context.CallActivityAsync(nameof(ProcessWorkItem), item));

    // Fan in - wait for all to complete
    var results = await Task.WhenAll(tasks);

    return results;
}

[Function(nameof(ProcessWorkItem))]
public static int ProcessWorkItem([ActivityTrigger] string item)
{
    // Process item and return result
    return item.Length;
}

Human Interaction Pattern

[Function(nameof(ApprovalOrchestrator))]
public static async Task ApprovalOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var request = context.GetInput();

    // Send notification
    await context.CallActivityAsync(nameof(SendApprovalRequest), request);

    // Wait for external event with timeout
    using var cts = new CancellationTokenSource();
    var approvalTask = context.WaitForExternalEvent("ApprovalEvent");
    var timeoutTask = context.CreateTimer(context.CurrentUtcDateTime.AddDays(7), cts.Token);

    var winner = await Task.WhenAny(approvalTask, timeoutTask);

    if (winner == approvalTask)
    {
        cts.Cancel();
        return approvalTask.Result ? "Approved" : "Rejected";
    }

    return "Timed out";
}

Best Practices

  1. Use isolated worker model for new development - Full .NET ecosystem access, middleware support, and longer support lifecycle
  2. Inject dependencies via constructor - Use ILogger and service interfaces for testability
  3. Keep orchestrator code deterministic - No I/O, random, DateTime.Now, or Guid.NewGuid() in orchestrators
  4. Handle sensitive data in activities - Fetch secrets from Key Vault in activity functions, never in orchestrators
  5. Use unique task hub names - Prevent accidental sharing when multiple apps use the same storage
  6. Avoid large inputs/outputs - Serialize to blob storage for large payloads to prevent history bloat
  7. Configure concurrency limits - Set appropriate limits in host.json for resource-intensive functions
  8. Keep SDK and extensions updated - Latest versions include performance improvements and bug fixes

Anti-Patterns to Avoid

| Anti-Pattern | Why It's Bad | Better Approach | |--------------|--------------|-----------------| | Mixing in-process and isolated guidance | Incompatible APIs and patterns | Choose one model consistently | | Non-deterministic orchestrator code | Replay failures, stuck orchestrations | Use context.CurrentUtcDateTime, no I/O | | Large orchestrator inputs/outputs | History bloat, memory issues | Store large data in blob storage | | Shared task hub names | Message conflicts, stuck orchestrations | Use unique names per app | | Secrets in orchestrator history | Security risk, exposed in logs | Fetch secrets in activity functions | | Blocking calls in async functions | Thread pool exhaustion | Use await throughout | | Missing retry policies | Transient failures cause job loss | Configure retry in bindings or code | | Ignoring execution model migration | EOL November 2026 for in-process | Migrate to isolated worker model |

Deployment Considerations

Linux Consumption Plan Limitations

.NET 10+ apps cannot run on Linux Consumption plan.
Use Flex Consumption plan or App Service for .NET 10+.
.NET 9 is the last version supported on Linux Consumption.

host.json Configuration

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "MyUniqueTaskHub",
      "maxConcurrentActivityFunctions": 10,
      "maxConcurrentOrchestratorFunctions": 5
    }
  },
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  }
}

Deliver

  • correct Functions project setup for the isolated worker model
  • clear binding and host configuration
  • middleware for cross-cutting concerns
  • Durable Functions with proper orchestration patterns
  • migration-safe guidance when upgrading execution models

Validate

  • execution model guidance is consistent (isolated only for new work)
  • orchestrator code is deterministic
  • bindings and host settings match the target runtime
  • large payloads are externalized to blob storage
  • retry policies are configured for transient failures
  • local and deployment behavior are both verified

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.