Experimental Research fork — APIs and behaviour may change without notice. Read disclaimer →

The JSON channel provides a programmatic interface to picobot via newline-delimited JSON (NDJSON) on stdin/stdout. Use it to embed picobot in scripts, build integrations, or create custom frontends.

Activation

picobot agent --json

Protocol

All messages are single-line JSON objects separated by newlines. The channel reads from stdin and writes to stdout.

Input Messages (stdin)

Send a message:

{"type": "message", "content": "What tools do you have?"}

With a session ID:

{"type": "message", "content": "Continue our work", "session": "my-session"}

With attachments:

{"type": "message", "content": "Analyze this", "attachments": [{"name": "data.csv", "content": "a,b,c\n1,2,3"}]}

Ping (health check):

{"type": "ping"}

Shutdown:

{"type": "shutdown"}

Output Messages (stdout)

Ready (on startup):

{"type": "ready"}

Response (agent's reply):

{"type": "response", "content": "I have these tools: ...", "session": "json:my-session"}

Progress events (real-time streaming):

{"type": "progress", "event": "text_delta", "text": "I have"}
{"type": "progress", "event": "tool_call_start", "id": "1", "name": "list_dir", "arguments": {"path": "/"}}
{"type": "progress", "event": "tool_call_done", "id": "1", "name": "list_dir", "result": "..."}
{"type": "progress", "event": "reasoning_delta", "text": "thinking..."}

Error:

{"type": "error", "message": "Invalid JSON", "code": "parse_error"}

Pong (ping response):

{"type": "pong"}

Sessions

Sessions are scoped to json:<session_id>. If you don't provide a session ID, a new one is generated per message. Provide a session ID to maintain conversation context across messages:

{"type": "message", "content": "Hello", "session": "project-x"}
{"type": "message", "content": "What did I just say?", "session": "project-x"}

Attachments

Text attachments are prepended to the message content as blocks:

[Attachment: data.csv]
a,b,c
1,2,3
[/Attachment]

Analyze this

This lets you send file contents alongside a question without the agent needing to read files from disk.

Error Recovery

The channel recovers from errors without shutting down:

  • Invalid JSON → error response, continue reading
  • Unknown message type → error response, continue reading
  • Agent exception → error response, continue reading

Only {"type": "shutdown"} or EOF on stdin stops the channel.

Example: Python Integration

import subprocess
import json

proc = subprocess.Popen(
    ["picobot", "agent", "--json"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    text=True,
)

# Wait for ready
ready = json.loads(proc.stdout.readline())
assert ready["type"] == "ready"

# Send a message
msg = {"type": "message", "content": "List my cron jobs", "session": "script"}
proc.stdin.write(json.dumps(msg) + "\n")
proc.stdin.flush()

# Read response (skip progress events)
while True:
    line = proc.stdout.readline()
    data = json.loads(line)
    if data["type"] == "response":
        print(data["content"])
        break

# Shutdown
proc.stdin.write('{"type": "shutdown"}\n')
proc.stdin.flush()
proc.wait()

Use Cases

  • Build a custom CLI with different UX than the default REPL
  • Embed in CI/CD for automated tasks (code review, test generation)
  • Create a web frontend that proxies through the JSON channel
  • Script multi-step workflows with precise control over sessions
  • Build channel adapters (Telegram, Slack) — this is the foundation for Phase 9 integrations