> ## Documentation Index
> Fetch the complete documentation index at: https://taskdaemon.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Raw protocol

# 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:

```json theme={null}
{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "task_type": "process",
  "task_data": {"key": "value"},
  "attempt": 0
}
```

| Field       | Type   | Description                        |
| ----------- | ------ | ---------------------------------- |
| `task_id`   | string | Unique task identifier (UUID)      |
| `task_type` | string | Handler type from config           |
| `task_data` | object | Arbitrary input data from client   |
| `attempt`   | number | Current attempt number (0-indexed) |

## Output Format

Write one JSON object per line to stdout.

### Success Response

```json theme={null}
{"status": "success", "result": {"key": "value"}}
```

### Error Response

```json theme={null}
{"status": "error", "error": "Error message", "retryable": false}
```

| Field       | Type    | Description                                   |
| ----------- | ------- | --------------------------------------------- |
| `status`    | string  | `"success"` or `"error"`                      |
| `result`    | any     | Result data (success only)                    |
| `error`     | string  | Error message (error only)                    |
| `retryable` | boolean | Whether to retry (error only, default: false) |

## Example Implementations

### Python (No SDK)

```python theme={null}
import json
import sys

for line in sys.stdin:
    task = json.loads(line)
    
    try:
        # Process task
        name = task["task_data"].get("name", "World")
        result = {"message": f"Hello, {name}!"}
        response = {"status": "success", "result": result}
    except Exception as e:
        response = {"status": "error", "error": str(e), "retryable": False}
    
    print(json.dumps(response), flush=True)
```

### Node.js (No SDK)

```javascript theme={null}
const readline = require('readline');

const rl = readline.createInterface({ input: process.stdin });

rl.on('line', (line) => {
  const task = JSON.parse(line);
  
  try {
    const name = task.task_data.name || 'World';
    const result = { message: `Hello, ${name}!` };
    console.log(JSON.stringify({ status: 'success', result }));
  } catch (e) {
    console.log(JSON.stringify({ status: 'error', error: String(e), retryable: false }));
  }
});
```

### Ruby

```ruby theme={null}
require 'json'

STDOUT.sync = true

STDIN.each_line do |line|
  task = JSON.parse(line)
  
  begin
    name = task['task_data']['name'] || 'World'
    result = { message: "Hello, #{name}!" }
    puts JSON.generate({ status: 'success', result: result })
  rescue => e
    puts JSON.generate({ status: 'error', error: e.message, retryable: false })
  end
end
```

### PHP

```php theme={null}
<?php
while ($line = fgets(STDIN)) {
    $task = json_decode($line, true);
    
    try {
        $name = $task['task_data']['name'] ?? 'World';
        $result = ['message' => "Hello, {$name}!"];
        $response = ['status' => 'success', 'result' => $result];
    } catch (Exception $e) {
        $response = ['status' => 'error', 'error' => $e->getMessage(), 'retryable' => false];
    }
    
    echo json_encode($response) . "\n";
    flush();
}
```

### Bash

```bash theme={null}
#!/bin/bash
while IFS= read -r line; do
    name=$(echo "$line" | jq -r '.task_data.name // "World"')
    echo "{\"status\": \"success\", \"result\": {\"message\": \"Hello, $name!\"}}"
done
```

### Perl

```perl theme={null}
use JSON;
use strict;

$| = 1;  # Autoflush

while (my $line = <STDIN>) {
    my $task = decode_json($line);
    my $name = $task->{task_data}{name} // 'World';
    
    print encode_json({
        status => 'success',
        result => { message => "Hello, $name!" }
    }) . "\n";
}
```

## Important Requirements

### 1. Flush Output

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

```python theme={null}
print(json.dumps(response), flush=True)  # Python
```

```javascript theme={null}
// Node.js console.log auto-flushes
console.log(JSON.stringify(response));
```

```ruby theme={null}
STDOUT.sync = true  # Ruby
```

### 2. One Response Per Task

Write exactly one JSON line per input line. Don't write partial responses or multiple lines.

### 3. Keep Running

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

```python theme={null}
# Wrong - exits after one task
task = json.loads(input())
print(json.dumps(result))

# Correct - keeps running
for line in sys.stdin:
    task = json.loads(line)
    print(json.dumps(result), flush=True)
```

### 4. Handle Errors Gracefully

Return error status instead of crashing:

```python theme={null}
try:
    result = process(task)
    response = {"status": "success", "result": result}
except Exception as e:
    response = {"status": "error", "error": str(e), "retryable": False}
```

### 5. Use Unbuffered I/O

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

```dockerfile theme={null}
# Python
ENV PYTHONUNBUFFERED=1
CMD ["python", "-u", "handler.py"]

# Node.js (auto-flushes)
CMD ["node", "handler.js"]

# Ruby
CMD ["ruby", "-e", "$stdout.sync=true; load 'handler.rb'"]
```

## Dockerfile Template

```dockerfile theme={null}
FROM your-base-image

COPY handler.ext /app/
WORKDIR /app

# Ensure unbuffered output (language-specific)
ENV PYTHONUNBUFFERED=1

CMD ["your-runtime", "handler.ext"]
```

## Testing Handlers Locally

Test your handler without TaskDaemon:

```bash theme={null}
echo '{"task_id":"test","task_type":"greet","task_data":{"name":"World"},"attempt":0}' | ./handler
```

Expected output:

```json theme={null}
{"status":"success","result":{"message":"Hello, World!"}}
```
