Integrations
RPC Mode
Control Autohand programmatically via JSON protocol over stdin/stdout. Perfect for building custom UIs, IDE integrations, and automation tools.
Quick answer
What is the Autohand RPC Mode integration?
Autohand RPC Mode exposes a newline-delimited JSON protocol over stdin and stdout. A parent process can start the CLI, send prompts and control messages, and consume structured events without parsing the interactive terminal interface.
- Status
- Available
- Requires
- A local process that can manage Autohand stdin, stdout, lifecycle, and any model-provider credentials.
- Configure with
- Start Autohand in RPC mode, send one JSON message per line, and keep stdout reserved for protocol events as documented below.
- Best for
- Custom interfaces, scripts, test harnesses, and process-level automation.
Know before you start: The host application owns process supervision, message ordering, secret injection, error handling, and protocol-version compatibility.
Overview
RPC mode enables headless operation of the Autohand CLI via a JSON-RPC protocol. This allows external applications to:
- Send prompts and receive streaming responses
- Monitor tool execution in real-time
- Handle permission requests programmatically
- Control auto-mode, plan mode, and YOLO mode
- Manage skills and MCP servers
- Build custom UIs and IDE extensions
- Create automated pipelines with full agent control
Looking for session-managed connections? If you need persistent sessions, model switching, and editor-style integration, see ACP Mode instead.
Getting Started
Start RPC Mode
Launch Autohand in RPC mode:
# Basic RPC mode
autohand --mode rpc
# With options
autohand --mode rpc --model nvidia/nemotron-3-super-120b-a12b:free --ephemeral
# All options
autohand --mode rpc \
--model <model-id> \
--ephemeral \
--thinking <level> \
--config <path>
Protocol Basics
The protocol uses newline-delimited JSON (JSON Lines):
- Commands: JSON objects sent to stdin, one per line
- Responses: JSON objects with
type: "response" - Events: JSON objects streamed during agent operation
Correlation IDs: Include an optional id field in commands. The corresponding response will include the same id for matching.
Core Commands
prompt
Send an instruction to the agent:
{"type": "prompt", "message": "Create a hello.ts file", "id": "1"}
// With file context
{"type": "prompt", "message": "Review this file", "mentions": ["src/index.ts"]}
abort
Cancel the current operation:
{"type": "abort"}
reset
Clear conversation context:
{"type": "reset"}
get_state
Get current agent state:
{"type": "get_state"}
// Response
{
"type": "response",
"command": "get_state",
"success": true,
"data": {
"model": "nvidia/nemotron-3-super-120b-a12b:free",
"provider": "openrouter",
"workspace": "/path/to/project",
"isProcessing": false,
"contextPercent": 85,
"messageCount": 5
}
}
get_messages
Get conversation history:
{"type": "get_messages"}
get_history
Get the full session history including tool calls and results:
{"type": "get_history"}
// Response
{
"type": "response",
"command": "get_history",
"success": true,
"data": {
"messages": [...],
"toolCalls": [...],
"totalTokens": 12500
}
}
permission_response
Respond to a permission request:
{"type": "permission_response", "requestId": "perm-123", "approve": true}
Auto-Mode Commands
Control the autonomous execution mode programmatically. Auto-mode lets the agent work through tasks without requiring manual prompt-by-prompt interaction.
automode_start
Start auto-mode with an initial instruction:
{"type": "automode_start", "message": "Refactor the auth module", "id": "am-1"}
// Response
{
"type": "response",
"command": "automode_start",
"success": true,
"data": {"status": "running"}
}
automode_status
Check the current auto-mode status:
{"type": "automode_status"}
// Response
{
"type": "response",
"command": "automode_status",
"success": true,
"data": {
"active": true,
"paused": false,
"turnsCompleted": 3,
"turnsRemaining": 7
}
}
automode_pause
Pause a running auto-mode session:
{"type": "automode_pause"}
automode_resume
Resume a paused auto-mode session:
{"type": "automode_resume"}
automode_cancel
Cancel auto-mode entirely:
{"type": "automode_cancel"}
automode_get_log
Get the auto-mode execution log:
{"type": "automode_get_log"}
// Response
{
"type": "response",
"command": "automode_get_log",
"success": true,
"data": {
"entries": [
{"turn": 1, "action": "Read file src/auth.ts", "timestamp": "..."},
{"turn": 2, "action": "Edited src/auth.ts", "timestamp": "..."}
]
}
}
Skill Commands
Manage the agent's skill registry programmatically.
get_skills_registry
List all available skills:
{"type": "get_skills_registry"}
// Response
{
"type": "response",
"command": "get_skills_registry",
"success": true,
"data": {
"skills": [
{
"name": "commit",
"description": "Create a git commit",
"source": "builtin"
},
{
"name": "review-pr",
"description": "Review a pull request",
"source": "plugin:code-review"
}
]
}
}
install_skill
Install a skill from a registry or path:
{
"type": "install_skill",
"source": "npm:@autohand/skill-tdd",
"id": "sk-1"
}
// Response
{
"type": "response",
"command": "install_skill",
"success": true,
"data": {"name": "tdd", "installed": true}
}
MCP Commands
Manage Model Context Protocol servers and tools.
mcp_list_servers
List configured MCP servers:
{"type": "mcp_list_servers"}
// Response
{
"type": "response",
"command": "mcp_list_servers",
"success": true,
"data": {
"servers": [
{"name": "context7", "status": "connected", "tools": 2},
{"name": "brave-search", "status": "connected", "tools": 1}
]
}
}
mcp_list_tools
List all available MCP tools across servers:
{"type": "mcp_list_tools"}
// Response
{
"type": "response",
"command": "mcp_list_tools",
"success": true,
"data": {
"tools": [
{"name": "query-docs", "server": "context7"},
{"name": "brave_web_search", "server": "brave-search"}
]
}
}
mcp_get_server_configs
Get the full configuration for all MCP servers:
{"type": "mcp_get_server_configs"}
// Response
{
"type": "response",
"command": "mcp_get_server_configs",
"success": true,
"data": {
"configs": {
"context7": {
"command": "npx",
"args": ["-y", "@upstash/context7-mcp@latest"]
}
}
}
}
mcp_set_vscode_tools
Configure MCP tools for VS Code integration. This syncs tool availability between the CLI and VS Code extension:
{
"type": "mcp_set_vscode_tools",
"tools": ["query-docs", "brave_web_search"]
}
mcp_invoke_response
Send the result of an MCP tool invocation back to the agent. Used when the host application handles tool execution:
{
"type": "mcp_invoke_response",
"toolCallId": "call_abc123",
"result": {"content": "Search results..."}
}
Mode Commands
Control agent operation modes.
plan_mode_set
Toggle plan mode on or off. In plan mode, the agent designs an approach before making changes:
// Enable plan mode
{"type": "plan_mode_set", "enabled": true}
// Disable plan mode
{"type": "plan_mode_set", "enabled": false}
// Response
{
"type": "response",
"command": "plan_mode_set",
"success": true,
"data": {"planMode": true}
}
yolo_set
Toggle YOLO mode. When enabled, the agent auto-approves all tool executions without permission prompts:
// Enable YOLO mode
{"type": "yolo_set", "enabled": true}
// With specific patterns
{"type": "yolo_set", "enabled": true, "patterns": ["npm *", "git *"]}
// Response
{
"type": "response",
"command": "yolo_set",
"success": true,
"data": {"yolo": true}
}
Use YOLO mode with care: Auto-approving all operations can lead to unwanted changes. Consider using patterns to limit which commands are auto-approved.
File Change Commands
changes_decision
Accept or reject file changes proposed by the agent. When the agent writes or edits files, you can review and decide on each change:
// Accept changes
{
"type": "changes_decision",
"changeId": "chg-456",
"decision": "accept"
}
// Reject changes
{
"type": "changes_decision",
"changeId": "chg-456",
"decision": "reject"
}
// Response
{
"type": "response",
"command": "changes_decision",
"success": true,
"data": {"applied": true}
}
Events
Events are streamed to stdout during agent operation:
| Event | Description |
|---|---|
agent_start |
Agent ready to accept commands |
agent_end |
Agent shutting down |
turn_start |
Started processing a prompt |
turn_end |
Finished processing a prompt |
message_start |
LLM response started |
message_update |
Streaming content delta |
message_end |
LLM response completed |
tool_execution_start |
Tool execution started |
tool_execution_update |
Tool output chunk |
tool_execution_end |
Tool execution completed |
permission_request |
Awaiting approval for action |
automode_turn |
Auto-mode completed a turn |
automode_complete |
Auto-mode finished all turns |
file_change |
File was created, modified, or deleted |
error |
Error occurred |
Event Examples
// Turn lifecycle
{"type": "turn_start", "timestamp": "...", "data": {"instruction": "Create a file"}}
{"type": "turn_end", "timestamp": "...", "data": {"success": true}}
// Message streaming
{"type": "message_update", "timestamp": "...", "data": {"delta": "I'll create "}}
// Tool execution
{"type": "tool_execution_start", "timestamp": "...", "data": {
"toolName": "write_file",
"toolCallId": "call_abc",
"args": {"path": "hello.ts"}
}}
{"type": "tool_execution_end", "timestamp": "...", "data": {
"toolName": "write_file",
"toolCallId": "call_abc",
"success": true,
"duration": 150
}}
// Permission request
{"type": "permission_request", "timestamp": "...", "data": {
"requestId": "perm-123",
"tool": "run_command",
"message": "Execute: npm install?"
}}
// Auto-mode events
{"type": "automode_turn", "timestamp": "...", "data": {
"turn": 3,
"total": 10,
"action": "Edited src/auth.ts"
}}
{"type": "automode_complete", "timestamp": "...", "data": {
"turnsCompleted": 5,
"success": true
}}
// File change
{"type": "file_change", "timestamp": "...", "data": {
"path": "src/hello.ts",
"action": "created",
"changeId": "chg-456"
}}
Examples
Python Client
import subprocess
import json
proc = subprocess.Popen(
["autohand", "--mode", "rpc", "--ephemeral"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True
)
def send(cmd):
proc.stdin.write(json.dumps(cmd) + "\n")
proc.stdin.flush()
def read_events():
for line in proc.stdout:
yield json.loads(line)
# Wait for ready
for event in read_events():
if event.get("type") == "agent_start":
break
# Send prompt
send({"type": "prompt", "message": "Hello!", "id": "1"})
# Process events
for event in read_events():
if event.get("type") == "message_update":
print(event["data"]["delta"], end="", flush=True)
if event.get("type") == "permission_request":
# Handle permission
send({
"type": "permission_response",
"requestId": event["data"]["requestId"],
"approve": True
})
if event.get("type") == "turn_end":
print()
break
proc.terminate()
Node.js Client
const { spawn } = require("child_process");
const readline = require("readline");
const agent = spawn("autohand", ["--mode", "rpc", "--ephemeral"]);
const rl = readline.createInterface({ input: agent.stdout });
rl.on("line", (line) => {
const event = JSON.parse(line);
if (event.type === "message_update") {
process.stdout.write(event.data.delta);
}
if (event.type === "permission_request") {
agent.stdin.write(JSON.stringify({
type: "permission_response",
requestId: event.data.requestId,
approve: true
}) + "\n");
}
if (event.type === "turn_end") {
console.log("\n--- Done ---");
}
});
// Send prompt after ready
setTimeout(() => {
agent.stdin.write(JSON.stringify({
type: "prompt",
message: "List files in current directory"
}) + "\n");
}, 1000);
process.on("SIGINT", () => {
agent.stdin.write(JSON.stringify({ type: "abort" }) + "\n");
agent.kill();
});
Auto-Mode Example
import subprocess
import json
proc = subprocess.Popen(
["autohand", "--mode", "rpc"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True
)
def send(cmd):
proc.stdin.write(json.dumps(cmd) + "\n")
proc.stdin.flush()
def read_events():
for line in proc.stdout:
yield json.loads(line)
# Wait for ready
for event in read_events():
if event.get("type") == "agent_start":
break
# Enable YOLO mode for auto-approval
send({"type": "yolo_set", "enabled": True, "patterns": ["git *"]})
# Start auto-mode
send({
"type": "automode_start",
"message": "Add unit tests for the auth module"
})
# Monitor progress
for event in read_events():
if event.get("type") == "automode_turn":
d = event["data"]
print(f"Turn {d['turn']}/{d['total']}: {d['action']}")
if event.get("type") == "automode_complete":
print("Auto-mode finished!")
break
proc.terminate()
Use Cases
IDE Extensions
Build VS Code, JetBrains, or Zed extensions that embed Autohand:
- Spawn RPC process on extension activation
- Send file context with
mentions - Display streaming responses in editor panels
- Handle permission requests via UI dialogs
Custom Web UIs
Create browser-based interfaces:
- Backend spawns RPC process
- WebSocket bridges JSON events to browser
- React/Vue components render streaming output
- Users approve/deny via web interface
CI/CD Integration
Programmatic control in pipelines:
- Auto-approve safe operations with YOLO patterns
- Use auto-mode for multi-step tasks
- Collect structured output for reports
- Chain multiple prompts in sequence
Error Handling
Failed commands return responses with success: false:
{
"type": "response",
"command": "prompt",
"success": false,
"error": "Agent is already processing a request"
}
// Parse errors
{
"type": "response",
"command": "parse",
"success": false,
"error": "Invalid JSON: Unexpected token..."
}
Always handle errors: Check success field in responses and listen for error events to handle failures gracefully.
Future Commands
These commands are planned for future releases:
- Model:
set_model,cycle_model,get_available_models - Thinking:
set_thinking_level,cycle_thinking_level - Compaction:
compact,set_auto_compaction
Common questions
RPC Mode integration FAQ
How do I configure the Autohand RPC Mode integration?
Start Autohand in RPC mode, send one JSON message per line, and keep stdout reserved for protocol events as documented below.
What does the Autohand RPC Mode integration require?
A local process that can manage Autohand stdin, stdout, lifecycle, and any model-provider credentials.
What limitations should I know about?
The host application owns process supervision, message ordering, secret injection, error handling, and protocol-version compatibility.