Files
openagent/README.md
Thomas Marchand a3d3437b1d OpenCode workspace host + MCP sync + iOS fixes (#27)
* Add multi-user auth and per-user control sessions

* Add mission store abstraction and auth UX polish

* Fix unused warnings in tooling

* Fix Bugbot review issues

- Prevent username enumeration by using generic error message
- Add pagination support to InMemoryMissionStore::list_missions
- Improve config error when JWT_SECRET missing but DASHBOARD_PASSWORD set

* Trim stored username in comparison for consistency

* Fix mission cleanup to also remove orphaned tree data

* Refactor Open Agent as OpenCode workspace host

* Remove chromiumoxide and pin @types/react

* Pin idna_adapter for MSRV compatibility

* Add host-mcp bin target

* Use isolated Playwright MCP sessions

* Allow Playwright MCP as root

* Fix iOS dashboard warnings

* Add autoFocus to username field in multi-user login mode

Mirrors the iOS implementation behavior where username field is focused
when multi-user auth mode is active.

* Fix Bugbot review issues

- Add conditional ellipsis for tool descriptions (only when > 32 chars)
- Add serde(default) to JWT usr field for backward compatibility

* Fix empty user ID fallback in multi-user auth

Add effective_user_id helper that falls back to username when id is empty,
preventing session sharing and token verification issues.

* Fix parallel mission history preservation

Load existing mission history into runner before starting parallel
execution to prevent losing conversation context.

* Fix desktop stream controls layout overflow on iPad

- Add frame(maxWidth: .infinity) constraints to ensure controls stay
  within bounds on wide displays
- Add alignment: .leading to VStacks for consistent layout
- Add Spacer() to buttons row to prevent spreading
- Increase label width to 55 for consistent FPS/Quality alignment
- Add alignment: .trailing to value text frames

* Fix queued user messages not persisted to mission history

When a user message was queued (sent while another task was running),
it was not being added to the history or persisted to the database.
This caused queued messages to be lost from mission history.

Added the same persistence logic used for initial messages to the
queued message handling code path.
2026-01-04 13:04:05 -08:00

6.7 KiB

Open Agent

A minimal autonomous coding agent with full machine access, implemented in Rust.

Features

  • HTTP API for task submission and monitoring
  • Tool-based agent loop following the "tools in a loop" pattern
  • Full toolset: file operations, terminal, machine-wide search, web access, git
  • OpenRouter integration for LLM access (supports any model)
  • SSE streaming for real-time task progress
  • AI-maintainable Rust codebase with strong typing

Quick Start

Prerequisites

Installation

git clone <repo-url>
cd open_agent
cargo build --release

Running

# Set your API key
export OPENROUTER_API_KEY="sk-or-v1-..."

# Optional: configure model (default: anthropic/claude-sonnet-4.5)
export DEFAULT_MODEL="anthropic/claude-sonnet-4.5"

# Optional: default working directory for relative paths (absolute paths work everywhere)
# In production this is typically /root
export WORKING_DIR="."

# Start the server
cargo run --release

The server starts on http://127.0.0.1:3000 by default.

OpenCode Backend (Required)

Open Agent delegates execution to an OpenCode server. OpenCode must be running and reachable.

# Point to a running OpenCode server
export OPENCODE_BASE_URL="http://127.0.0.1:4096"

# Optional: choose OpenCode agent (build/plan/etc)
export OPENCODE_AGENT="build"

# Optional: auto-allow all permissions for OpenCode sessions (default: true)
export OPENCODE_PERMISSIVE="true"

API Reference

Submit a Task

curl -X POST http://localhost:3000/api/task \
  -H "Content-Type: application/json" \
  -d '{"task": "Create a Python script that prints Hello World"}'

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending"
}

Get Task Status

curl http://localhost:3000/api/task/{id}

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "task": "Create a Python script that prints Hello World",
  "model": "openai/gpt-4.1-mini",
  "iterations": 3,
  "result": "I've created hello.py with a simple Hello World script...",
  "log": [...]
}

Stream Task Progress (SSE)

curl http://localhost:3000/api/task/{id}/stream

Events:

  • log - Execution log entries (tool calls, results)
  • done - Task completion with final status

Health Check

curl http://localhost:3000/api/health

Available Tools

Tool Description
read_file Read file contents (any path on the machine) with optional line range
write_file Write/create files anywhere on the machine
delete_file Delete files anywhere on the machine
list_directory List directory contents anywhere on the machine
search_files Search for files by name pattern (machine-wide; scope with path)
run_command Execute shell commands (optionally in a specified cwd)
grep_search Search file contents with regex (machine-wide; scope with path)
web_search Search the web (DuckDuckGo)
fetch_url Fetch URL contents
git_status Get git status for any repo path
git_diff Show git diff for any repo path
git_commit Create git commits for any repo path
git_log Show git log for any repo path

Configuration

Variable Default Description
OPENROUTER_API_KEY (required) Your OpenRouter API key
DEFAULT_MODEL anthropic/claude-sonnet-4.5 Default LLM model
WORKING_DIR . (dev) / /root (prod) Default working directory for relative paths (agent still has full machine access)
HOST 127.0.0.1 Server bind address
PORT 3000 Server port
MAX_ITERATIONS 50 Max agent loop iterations
OPEN_AGENT_USERS (optional) JSON array of multi-user accounts (enables multi-user auth)
DASHBOARD_PASSWORD (optional) Single-tenant dashboard password (legacy auth)
JWT_SECRET (required for auth) HMAC secret for JWT signing

Multi-user Auth

Provide OPEN_AGENT_USERS to enable multi-user login:

export JWT_SECRET="your-secret"
export OPEN_AGENT_USERS='[{"id":"alice","username":"alice","password":"..."}]'

When multi-user auth is enabled, the memory system is disabled to avoid cross-user leakage.

Architecture

┌─────────────────┐     ┌─────────────────┐
│   HTTP Client   │────▶│   HTTP API      │
└─────────────────┘     │   (axum)        │
                        └────────┬────────┘
                                 │
                        ┌────────▼────────┐
                        │   Agent Loop    │◀──────┐
                        │                 │       │
                        └────────┬────────┘       │
                                 │                │
                   ┌─────────────┼─────────────┐  │
                   ▼             ▼             ▼  │
            ┌──────────┐  ┌──────────┐  ┌──────────┐
            │   LLM    │  │  Tools   │  │  Tools   │
            │(OpenRouter)│ │(file,git)│ │(term,web)│
            └──────────┘  └──────────┘  └──────────┘
                   │
                   └──────────────────────────────┘
                            (results fed back)

Development

# Run with debug logging
RUST_LOG=debug cargo run

# Run tests
cargo test

# Format code
cargo fmt

# Check for issues
cargo clippy

Dashboard (Bun)

The dashboard lives in dashboard/ and uses Bun as the package manager.

cd dashboard
bun install
PORT=3001 bun dev

Calibration (Trial-and-Error Tuning)

Open Agent supports empirical tuning of its difficulty (complexity) and cost estimation via a calibration harness.

Run calibrator

export OPENROUTER_API_KEY="sk-or-v1-..."
cargo run --release --bin calibrate -- --workspace ./.open_agent_calibration --model openai/gpt-4.1-mini --write-tuning

This writes a tuning file at ./.open_agent_calibration/.openagent/tuning.json. Move/copy it to your real workspace as ./.openagent/tuning.json to enable it.

License

MIT