Documentation Index
Fetch the complete documentation index at: https://taskdaemon.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
C# SDK
The C# SDK for writing TaskDaemon handlers.
Installation
dotnet add package TaskDaemon.Handler
Basic Usage
using TaskDaemon;
Handler.Run(task => {
var name = task.task_data.GetValueOrDefault("name", "World");
return new Success(new { message = $"Hello, {name}!" });
});
Task Record
public record Task(
string task_id,
string task_type,
Dictionary<string, object> task_data,
int attempt // Current attempt (starts at 0)
);
Result Types
// Abstract base
public abstract record Result;
// Success with result
public record Success(object result) : Result;
// Error with message and optional retryable flag
public record Error(string error, bool retryable = false) : Result;
Usage:
// Success
return new Success(new { processed = true });
// Non-retryable error (default)
return new Error("Invalid input");
// Retryable error
return new Error("Service unavailable", retryable: true);
Complete Example
using TaskDaemon;
using System.Text.RegularExpressions;
Handler.Run(task => {
var text = task.task_data.GetValueOrDefault("text", "")?.ToString() ?? "";
// Count words
var words = Regex.Matches(text, @"\S+").Count;
// Count characters (excluding spaces)
var chars = text.Count(c => !char.IsWhiteSpace(c));
// Count lines
var lines = text.Split('\n').Length;
return new Success(new {
words,
characters = chars,
lines
});
});
Error Handling
Exceptions are automatically caught and converted to non-retryable errors:
Handler.Run(task => {
// If this throws, it becomes Error(exception.Message)
var required = task.task_data["required"];
return new Success(new { value = required });
});
For explicit error handling:
Handler.Run(task => {
if (!task.task_data.ContainsKey("required"))
return new Error("Missing required field");
try {
var result = ExternalApiCall();
return new Success(result);
} catch (HttpRequestException e) {
return new Error($"API unavailable: {e.Message}", retryable: true);
}
});
Async Handlers
using TaskDaemon;
await Handler.RunAsync(async task => {
var url = task.task_data["url"]?.ToString();
using var client = new HttpClient();
var response = await client.GetStringAsync(url);
return new Success(new { data = response });
});
Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/runtime:8.0
WORKDIR /app
COPY --from=builder /app/out ./
CMD ["dotnet", "Handler.dll"]
For a self-contained single-file deployment:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -o out
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0
COPY --from=builder /app/out/Handler /handler
CMD ["/handler"]
Handler Configuration
[handlers.process]
image = "csharp-handler:latest"
instances = 4
timeout = 30
Requirements
- .NET 6.0+ (uses records and file-scoped namespaces)
- System.Text.Json for serialization (built-in)