Skip to main content

Handler Overview

TaskDaemon handlers are containerized programs that process tasks. They communicate via a simple JSON protocol over stdin/stdout, making it possible to write handlers in any programming language.

How Handlers Work

TaskDaemon                    Handler Container
    │                              │
    │──── JSON task ──────────────▶│ (stdin)
    │                              │
    │                         Process task
    │                              │
    │◀─── JSON result ────────────│ (stdout)
    │                              │
  1. TaskDaemon sends a JSON task to the handler’s stdin
  2. Handler processes the task
  3. Handler writes a JSON result to stdout
  4. TaskDaemon captures the result

Protocol

Input (stdin)

{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "task_type": "process",
  "task_data": {"key": "value"},
  "attempt": 1
}

Output (stdout)

Success:
{"status": "success", "result": {"processed": true}}
Error (retryable):
{"status": "error", "error": "Connection timeout", "retryable": true}
Error (permanent):
{"status": "error", "error": "Invalid input", "retryable": false}

Official SDKs

We provide SDKs that handle the protocol for you:

Handler Requirements

1

Read JSON from stdin

Handler must continuously read line-delimited JSON from stdin
2

Process the task

Parse the task data and perform the work
3

Write JSON to stdout

Output a single JSON line with status and result
4

Flush output

Ensure stdout is flushed after each response
Print statements are safe. TaskDaemon automatically skips non-JSON lines in handler output, so print() statements for debugging won’t break the protocol. However, for production use, logging to stderr is recommended.

Logging to stderr

For production handlers, log to stderr instead of stdout to keep logs separate from the JSON protocol:
import sys
print("Debug info", file=sys.stderr)

# Or use logging
import logging
logging.basicConfig(stream=sys.stderr)
logging.info("Processing task")

Minimal Example

Here’s the simplest possible handler in Python:
import json
import sys

for line in sys.stdin:
    task = json.loads(line)
    result = {"echo": task["task_data"]}
    print(json.dumps({"status": "success", "result": result}), flush=True)

Dockerfile

Handlers must be packaged as Docker images. Make sure to install the SDK from the package manager:
FROM python:3.11-slim
RUN pip install --no-cache-dir taskdaemon
COPY handler.py /app/
WORKDIR /app
CMD ["python", "-u", "handler.py"]
Always use unbuffered output (-u flag in Python, flush=True, etc.) to ensure responses are sent immediately.

Configuration

Register handlers in handlers.toml:
[handlers.myhandler]
image = "my-handler:latest"
instances = 4
timeout = 30
handler_selection = "round-robin"
See handlers.toml configuration for all options.