Automation Guide
This is the end-to-end runbook for AI agents and automation systems operating Otto programmatically. Before starting, review For Agents for constraints and decision flow.
Prerequisites
- Node.js 18+ and npm
- Google Chrome installed
- Network access between relay, browser node, and controller
Step 1: Install and set up
npm install -g @telepat/otto
otto setup --relay-url http://localhost:8787 --non-interactive
Parse the JSON output for:
daemonStatus:startedoralready_runningextensionPath: path to the unpacked extensionextensionVersion: installed version
Step 2: Extension handoff
otto setup provides the unpacked extension path. Present the following instructions to the human:
- Open
chrome://extensionsin Chrome. - Enable Developer mode (toggle in top right).
- Click Load unpacked and select the extension path from setup output.
- Open the extension popup.
- Set the relay URL to
http://localhost:8787(or your relay URL).
For remote relay deployments, the relay endpoint must be reachable from both the browser node and the controller. Use https:// / wss:// for remote traffic.
Step 3: Pairing
# Generate an authcode for the node to use
otto authcode
# After the user enters the code in the extension popup, approve it:
otto pair <code>
If the user cannot locate the pairing code field in the extension popup, guide them to Options → Pairing in the extension.
Step 4: Register controller and authenticate
otto client register --name "agent-worker" --description "Autonomous Otto controller" --json
otto client login --client-id <clientId>
Secret handling:
- Store the returned client secret in an environment variable or keychain.
- Never print it to shared logs.
- Hand it off out-of-band for external controllers.
Step 5: ACL approval
If commands return acl_missing_node_grant, the user must grant access:
- Open the extension popup.
- Navigate to Controller Access.
- Approve the controller client.
After approval, retry the failing command.
Step 6: Verify the full stack
otto commands list --json
A successful response confirms relay, node, controller, and ACL are all operational.
Step 7: Execute commands
# Open a managed tab
otto cmd --action primitive.tab.open --payload '{"url":"https://www.reddit.com"}'
# Run a site command using the returned tabSessionId
otto cmd --action command.run \
--tab-session <tabSessionId> \
--payload '{"site":"reddit.com","command":"getFeed"}'
# Run with otto test for stream-capable commands
otto test reddit.com getChatMessages --stream-follow-ms 30000 --json
Handling manual_login_required
When a command returns manual_login_required:
- Tell the human: the site requires login before this command can run.
- Ask them to log in to the site in the open browser tab.
- Once confirmed, retry the command using the same
--tab-session.
Do not attempt to automate credential entry. This behavior is intentional and non-negotiable.
Correlating failures
Every command response includes a requestId. Use it to pull correlated logs:
otto logs list --request-id <requestId> --source all --latest 100 --json
For extension-specific issues:
otto logs list --source node --latest 50 --json
For live debugging:
otto logs follow --source all --json
Multi-machine deployments
When relay, browser node, and controller are on different machines:
- The relay endpoint must be reachable from both the node and controller network paths.
- Configure
OTTO_EXTENSION_ORIGINto match the extension origin in production. - Use
wss://andhttps://for remote deployments. - Firewall rules must allow WebSocket upgrades on the relay port.
Security boundaries
- Never automate credential submission — always use explicit
manual_login_requiredhandoff. - Never expose
OTTO_TOKEN_SECRET, client secrets, or node tokens in logs or output. - Verify ACL grants are node-owned; do not attempt to inject ACL state directly.
- Keep payloads bounded — do not loop unboundedly or capture unlimited stream data.
Related pages
- For Agents — constraints, decision flow, and failure handling reference.
- MCP Server — MCP server documentation and tool list.
- Agent Setup — register Otto with agent frameworks.
- Controller Implementation Guide — WebSocket controller integration.
- Use Cases — runnable examples for common automation patterns.
- Troubleshooting Advanced — stream and routing diagnostics.
MCP server usage
For agents using Otto via MCP instead of CLI commands:
Start MCP server
otto mcp
Register with agent framework
otto agent install claude # or cursor, vscode, etc.
MCP workflow
- Call
otto_statusto verify relay is running. - Call
otto_commands_listto discover available commands. - Call
otto_cmdwithaction: "primitive.tab.open"to open a tab. - Call
otto_cmdwithaction: "command.run"to execute site commands. - Handle
manual_login_requiredby asking user to log in. - Handle
acl_missing_node_grantby asking user to approve access.
Example MCP tool calls
Check status:
{ "name": "otto_status", "arguments": {} }
List commands:
{ "name": "otto_commands_list", "arguments": { "nodeId": "node_123" } }
Open a tab:
{ "name": "otto_cmd", "arguments": { "action": "primitive.tab.open", "payload": "{\"url\":\"https://www.reddit.com\"}" } }
Run a site command:
{ "name": "otto_cmd", "arguments": { "action": "command.run", "tabSession": "tab_abc", "payload": "{\"site\":\"reddit.com\",\"command\":\"getFeed\"}" } }