Skip to main content

Raw Protocol

Write handlers in any language without an SDK using the raw stdin/stdout protocol.

Protocol Overview

TaskDaemon communicates with handlers via:
  • Input: JSON task objects sent to stdin (one per line)
  • Output: JSON result objects written to stdout (one per line)
The handler process stays alive and processes multiple tasks.

Input Format

Each line on stdin is a JSON object:
The handler request uses attempt = stored attempts + 1, starting at attempt: 1. API attempts starts at zero and increments on retry scheduling or a Failed marking; successful completion does not increment it. An initial success therefore has request attempt: 1 and API attempts: 0, while an initial terminal failure stores attempts: 1. Recovery can repeat the same request attempt, so this number is not a unique execution counter. The daemon retries only valid status: "error" responses with retryable: true, subject to the task’s stored retry budget and backoff. Execution timeout or broken protocol/I/O is a terminal failure, and the unusable handler stream is stopped before reuse.

Output Format

Write one JSON object per line to stdout.

Success Response

Error Response

Example Implementations

Python (No SDK)

Node.js (No SDK)

Ruby

PHP

Bash

Perl

Important Requirements

1. Flush Output

Always flush stdout after writing to ensure TaskDaemon receives the response immediately:

2. One Response Per Task

Write exactly one JSON response line per input line. Send diagnostic logs to stderr, especially JSON-formatted logs that could be mistaken for responses.

3. Keep Running

The handler process stays alive and processes multiple tasks. Don’t exit after one task:

4. Handle Errors Gracefully

Return error status instead of crashing:

5. Use Unbuffered I/O

Configure your runtime for unbuffered or line-buffered I/O:

Dockerfile Template

Testing Handlers Locally

Test your handler without TaskDaemon:
Expected output: