From f07778481eb5c50cefaed72978bc3a956093c56c Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 9 Dec 2025 07:07:07 +0000 Subject: [PATCH 01/11] docs: weekly architecture docs refresh - Update agent-server.mdx to reflect current server responsibilities and endpoints (source: openhands-agent-server/*) - Fix security.mdx source link; add ConfirmationPolicy reference; add Last updated and Source commit footer Co-authored-by: openhands --- sdk/arch/agent-server.mdx | 631 ++++++++------------------------------ sdk/arch/security.mdx | 9 +- 2 files changed, 135 insertions(+), 505 deletions(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index 8ad7663c..17874772 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -1,534 +1,159 @@ --- title: Agent Server Package -description: HTTP API server for remote agent execution with workspace isolation, container orchestration, and multi-user support. +description: HTTP API server for remote agent execution with conversation/event endpoints and WebSocket streaming. --- -The Agent Server package (`openhands.agent_server`) provides an HTTP API server for remote agent execution. It enables building multi-user systems, SaaS products, and distributed agent platforms. +The Agent Server package (`openhands.agent_server`) exposes a FastAPI-based HTTP/WebSocket interface that runs OpenHands conversations remotely. It is stateless with respect to agent logic and does not orchestrate containers by itself. Containerization is handled by workspace implementations (e.g., DockerWorkspace) that launch this server inside a sandbox when needed. -**Source**: [`openhands/agent_server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands/agent_server) +Source: [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) -## Purpose +## Core Responsibilities -The Agent Server enables: -- **Remote execution**: Clients interact with agents via HTTP API -- **Multi-user isolation**: Each user gets isolated workspace -- **Container orchestration**: Manages Docker containers for workspaces -- **Centralized management**: Monitor and control all agents -- **Scalability**: Horizontal scaling with multiple servers +The server provides: -## Architecture Overview +1. **Conversation lifecycle API** - Create, run, pause, delete conversations (source: openhands/agent_server/conversation_router.py) +2. **Event access** - Search, count, get, batch-get conversation events; WebSocket event streaming (source: openhands/agent_server/event_router.py, openhands/agent_server/sockets.py) +3. **Execution utilities** - Start and monitor bash commands; file upload/download; simple Git ops (source: openhands/agent_server/bash_router.py, file_router.py, git_router.py) +4. **Tool registry listing** - Introspect available tools on the server (source: openhands/agent_server/tool_router.py) +5. **Server details** - Health, alive, and server info endpoints (source: openhands/agent_server/server_details_router.py) -```mermaid -graph TB - Client[Web/Mobile Client] -->|HTTPS| API[FastAPI Server] - - API --> Auth[Authentication] - API --> Router[API Router] - - Router --> WS[Workspace Manager] - Router --> Conv[Conversation Handler] - - WS --> Docker[Docker Manager] - Docker --> C1[Container 1
User A] - Docker --> C2[Container 2
User B] - Docker --> C3[Container 3
User C] - - Conv --> Agent[Software Agent SDK] - Agent --> C1 - Agent --> C2 - Agent --> C3 - - style Client fill:#e1f5fe - style API fill:#fff3e0 - style WS fill:#e8f5e8 - style Docker fill:#f3e5f5 - style Agent fill:#fce4ec -``` - -### Key Components - -**1. FastAPI Server** -- HTTP REST API endpoints -- Authentication and authorization -- Request validation -- WebSocket support for streaming - -**2. Workspace Manager** -- Creates and manages Docker containers -- Isolates workspaces per user -- Handles container lifecycle -- Manages resource limits - -**3. Conversation Handler** -- Routes requests to appropriate workspace -- Manages conversation state -- Handles concurrent requests -- Supports streaming responses - -**4. Docker Manager** -- Interfaces with Docker daemon -- Builds and pulls images -- Creates and destroys containers -- Monitors container health - -## Design Decisions - -### Why HTTP API? - -Alternative approaches considered: -- **gRPC**: More efficient but harder for web clients -- **WebSockets only**: Good for streaming but not RESTful -- **HTTP + WebSockets**: Best of both worlds - -**Decision**: HTTP REST for operations, WebSockets for streaming -- ✅ Works from any client (web, mobile, CLI) -- ✅ Easy to debug (curl, Postman) -- ✅ Standard authentication (API keys, OAuth) -- ✅ Streaming where needed - -### Why Container Per User? - -Alternative approaches: -- **Shared container**: Multiple users in one container -- **Container per session**: New container each conversation -- **Container per user**: One container per user (chosen) - -**Decision**: Container per user -- ✅ Strong isolation between users -- ✅ Persistent workspace across sessions -- ✅ Better resource management -- ⚠️ More containers, but worth it for isolation - -### Why FastAPI? - -Alternative frameworks: -- **Flask**: Simpler but less type-safe -- **Django**: Too heavyweight -- **FastAPI**: Modern, fast, type-safe (chosen) - -**Decision**: FastAPI -- ✅ Automatic API documentation (OpenAPI) -- ✅ Type validation with Pydantic -- ✅ Async support for performance -- ✅ WebSocket support built-in - -## API Design - -### Key Endpoints - -**Workspace Management** -``` -POST /workspaces Create new workspace -GET /workspaces/{id} Get workspace info -DELETE /workspaces/{id} Delete workspace -POST /workspaces/{id}/execute Execute command -``` - -**Conversation Management** -``` -POST /conversations Create conversation -GET /conversations/{id} Get conversation -POST /conversations/{id}/messages Send message -GET /conversations/{id}/stream Stream responses (WebSocket) -``` - -**Health & Monitoring** -``` -GET /health Server health check -GET /metrics Prometheus metrics -``` - -### Authentication - -**API Key Authentication** -```bash -curl -H "Authorization: Bearer YOUR_API_KEY" \ - https://agent-server.example.com/conversations -``` - -**Per-user workspace isolation** -- API key → user ID mapping -- Each user gets separate workspace -- Users can't access each other's workspaces - -### Streaming Responses - -**WebSocket for real-time updates** -```python -async with websocket_connect(url) as ws: - # Send message - await ws.send_json({"message": "Hello"}) - - # Receive events - async for event in ws: - if event["type"] == "message": - print(event["content"]) -``` - -**Why streaming?** -- Real-time feedback to users -- Show agent thinking process -- Better UX for long-running tasks - -## Deployment Models - -### 1. Local Development - -Run server locally for testing: -```bash -# Start server -openhands-agent-server --port 8000 - -# Or with Docker -docker run -p 8000:8000 \ - -v /var/run/docker.sock:/var/run/docker.sock \ - ghcr.io/all-hands-ai/agent-server:latest -``` - -**Use case**: Development and testing - -### 2. Single-Server Deployment - -Deploy on one server (VPS, EC2, etc.): -```bash -# Install -pip install openhands-agent-server - -# Run with systemd/supervisor -openhands-agent-server \ - --host 0.0.0.0 \ - --port 8000 \ - --workers 4 -``` - -**Use case**: Small deployments, prototypes, MVPs - -### 3. Multi-Server Deployment - -Scale horizontally with load balancer: -``` - Load Balancer - | - +-------------+-------------+ - | | | - Server 1 Server 2 Server 3 - (Agents) (Agents) (Agents) - | | | - +-------------+-------------+ - | - Shared State Store - (Database, Redis, etc.) -``` - -**Use case**: Production SaaS, high traffic, need redundancy - -### 4. Kubernetes Deployment - -Container orchestration with Kubernetes: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: agent-server -spec: - replicas: 3 - template: - spec: - containers: - - name: agent-server - image: ghcr.io/all-hands-ai/agent-server:latest - ports: - - containerPort: 8000 -``` - -**Use case**: Enterprise deployments, auto-scaling, high availability - -## Resource Management - -### Container Limits - -Set per-workspace resource limits: -```python -# In server configuration -WORKSPACE_CONFIG = { - "resource_limits": { - "memory": "2g", # 2GB RAM - "cpus": "2", # 2 CPU cores - "disk": "10g" # 10GB disk - }, - "timeout": 300, # 5 min timeout -} -``` - -**Why limit resources?** -- Prevent one user from consuming all resources -- Fair usage across users -- Protect server from runaway processes -- Cost control - -### Cleanup & Garbage Collection - -**Container lifecycle**: -- Containers created on first use -- Kept alive between requests (warm) -- Cleaned up after inactivity timeout -- Force cleanup on server shutdown - -**Storage management**: -- Old workspaces deleted automatically -- Disk usage monitored -- Alerts when approaching limits - -## Security Considerations - -### Multi-Tenant Isolation - -**Container isolation**: -- Each user gets separate container -- Containers can't communicate -- Network isolation (optional) -- File system isolation - -**API isolation**: -- API keys mapped to users -- Users can only access their workspaces -- Server validates all permissions - -### Input Validation - -**Server validates**: -- API request schemas -- Command injection attempts -- Path traversal attempts -- File size limits - -**Defense in depth**: -- API validation -- Container validation -- Docker security features -- OS-level security - -### Network Security - -**Best practices**: -- HTTPS only (TLS certificates) -- Firewall rules (only port 443/8000) -- Rate limiting -- DDoS protection - -**Container networking**: -```python -# Disable network for workspace -WORKSPACE_CONFIG = { - "network_mode": "none" # No network access -} - -# Or allow specific hosts -WORKSPACE_CONFIG = { - "allowed_hosts": ["api.example.com"] -} -``` - -## Monitoring & Observability - -### Health Checks - -```bash -# Simple health check -curl https://agent-server.example.com/health - -# Response -{ - "status": "healthy", - "docker": "connected", - "workspaces": 15, - "uptime": 86400 -} -``` - -### Metrics - -**Prometheus metrics**: -- Request count and latency -- Active workspaces -- Container resource usage -- Error rates - -**Logging**: -- Structured JSON logs -- Per-request tracing -- Workspace events -- Error tracking - -### Alerting - -**Alert on**: -- Server down -- High error rate -- Resource exhaustion -- Container failures - -## Client SDK - -Python SDK for interacting with Agent Server: - -```python -from openhands.client import AgentServerClient - -client = AgentServerClient( - url="https://agent-server.example.com", - api_key="your-api-key" -) +## Architecture -# Create conversation -conversation = client.create_conversation() - -# Send message -response = client.send_message( - conversation_id=conversation.id, - message="Hello, agent!" -) - -# Stream responses -for event in client.stream_conversation(conversation.id): - if event.type == "message": - print(event.content) -``` - -**Client handles**: -- Authentication -- Request/response serialization -- Error handling -- Streaming -- Retries - -## Cost Considerations +```mermaid +%%{init: {"theme": "default", "flowchart": {"nodeSpacing": 28, "rankSpacing": 40}} }%% +flowchart TB + Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] -### Server Costs + subgraph Routers[Routers (/api/*)] + Conv[conversations] + Events[conversations/{id}/events] + Bash[bash] + File[file] + Git[git] + Tools[tools] + end -**Compute**: CPU and memory for containers -- Each active workspace = 1 container -- Typically 1-2 GB RAM per workspace -- 0.5-1 CPU core per workspace + WS[/sockets/*\n(WebSocket)/] -**Storage**: Workspace files and conversation state -- ~1-10 GB per workspace (depends on usage) -- Conversation history in database + API --> Routers + API --> WS -**Network**: API requests and responses -- Minimal (mostly text) -- Streaming adds bandwidth + subgraph Services[Services] + ConvSvc[ConversationService] + EventSvc[EventService] + end -### Cost Optimization + Routers --> ConvSvc + Routers --> EventSvc + WS --> EventSvc -**1. Idle timeout**: Shutdown containers after inactivity -```python -WORKSPACE_CONFIG = { - "idle_timeout": 3600 # 1 hour -} -``` + classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px + classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px + classDef tertiary fill:#fff4df,stroke:#b7791f,stroke-width:2px -**2. Resource limits**: Don't over-provision -```python -WORKSPACE_CONFIG = { - "resource_limits": { - "memory": "1g", # Smaller limit - "cpus": "0.5" # Fractional CPU - } -} + class API primary + class Routers,WS secondary + class Services tertiary ``` -**3. Shared resources**: Use single server for multiple low-traffic apps - -**4. Auto-scaling**: Scale servers based on demand - -## When to Use Agent Server - -### Use Agent Server When: - -✅ **Multi-user system**: Web app with many users -✅ **Remote clients**: Mobile app, web frontend -✅ **Centralized management**: Need to monitor all agents -✅ **Workspace isolation**: Users shouldn't interfere -✅ **SaaS product**: Building agent-as-a-service -✅ **Scaling**: Need to handle concurrent users - -**Examples**: -- Chatbot platforms -- Code assistant web apps -- Agent marketplaces -- Enterprise agent deployments +- App construction and route wiring happen in [`api.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/api.py): the app mounts a single `/api` router that includes conversation, event, tool, bash, git, file, vscode, and desktop routers. +- Event and VSCode/Desktop services are initialized in the lifespan context (source: openhands/agent_server/api.py). -### Use Standalone SDK When: +## Authentication -✅ **Single-user**: Personal tool or script -✅ **Local execution**: Running on your machine -✅ **Full control**: Need programmatic access -✅ **Simpler deployment**: No server management -✅ **Lower latency**: No network overhead +- HTTP requests: header `X-Session-API-Key` if session keys are configured (source: openhands/agent_server/dependencies.py, `create_session_api_key_dependency`) +- WebSocket: query parameter `session_api_key` (source: openhands/agent_server/dependencies.py, sockets.py) +- Configuration source: environment-driven `Config` (source: openhands/agent_server/config.py) -**Examples**: -- CLI tools -- Automation scripts -- Local development -- Desktop applications - -### Hybrid Approach - -Use SDK locally but RemoteAPIWorkspace for execution: -- Agent logic in your Python code -- Execution happens on remote server -- Best of both worlds - -## Building Custom Agent Server - -The server is extensible for custom needs: +```mermaid +flowchart LR + Client -->|X-Session-API-Key| HTTP[HTTP /api/*] + Client -->|session_api_key| WS[/sockets/*] +``` + +## Endpoints (selected) + +All REST endpoints are mounted under `/api` unless noted. + +- Conversations (source: openhands/agent_server/conversation_router.py) + - `GET /api/conversations/search` – list + - `GET /api/conversations/count` – count + - `GET /api/conversations/{conversation_id}` – get + - `GET /api/conversations?ids=...` – batch get + - `POST /api/conversations` – start (accepts `StartConversationRequest` built with SDK `Agent` and `LocalWorkspace`) + - `POST /api/conversations/{conversation_id}/run` – run loop + - `POST /api/conversations/{conversation_id}/pause` – pause + - `DELETE /api/conversations/{conversation_id}` – delete + - `PATCH /api/conversations/{conversation_id}` – update metadata (title) + - `POST /api/conversations/{id}/generate_title` – title via LLM + - `POST /api/conversations/{id}/secrets` – update secrets + - `POST /api/conversations/{id}/confirmation_policy` – set policy + - `POST /api/conversations/{id}/security_analyzer` – set analyzer + - `POST /api/conversations/{id}/ask_agent` – question-only (no state change) + +- Events (source: openhands/agent_server/event_router.py) + - `GET /api/conversations/{conversation_id}/events/search` + - `GET /api/conversations/{conversation_id}/events/count` + - `GET /api/conversations/{conversation_id}/events/{event_id}` + - `GET /api/conversations/{conversation_id}/events?event_ids=...` + - `POST /api/conversations/{conversation_id}/events` – send `Message` + +- Bash (source: openhands/agent_server/bash_router.py) + - `POST /api/bash/start_bash_command` + - `POST /api/bash/execute_bash_command` + - `GET /api/bash/bash_events/search|{event_id}|` (list/get) + - `DELETE /api/bash/bash_events` – clear + +- Files (source: openhands/agent_server/file_router.py) + - `POST /api/file/upload/{path}` – upload to absolute path + - `GET /api/file/download/{path}` – download absolute path + - `GET /api/file/download-trajectory/{conversation_id}` – zip state + +- Git (source: openhands/agent_server/git_router.py) + - `GET /api/git/changes/{path}` + - `GET /api/git/diff/{path}` + +- Tools (source: openhands/agent_server/tool_router.py) + - `GET /api/tools/` – list registered tools + +- Server details (source: openhands/agent_server/server_details_router.py) + - `GET /alive`, `GET /health`, `GET /server_info` + +- WebSockets (source: openhands/agent_server/sockets.py) + - `WS /sockets/events/{conversation_id}?session_api_key=...&resend_all=bool` + - `WS /sockets/bash-events?session_api_key=...&resend_all=bool` + +## Design Notes + +- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP (source: openhands-workspace/openhands/workspace/docker/workspace.py). +- Request/response models are Pydantic classes in `models.py` (source: openhands/agent_server/models.py). +- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads (sources: dependencies.py, file_router.py). + +## Component Relationships -**Custom authentication**: -```python -from openhands.agent_server import AgentServer +```mermaid +flowchart LR + Server[Agent Server] + SDK[SDK RemoteWorkspace] + Docker[DockerWorkspace] -class CustomAgentServer(AgentServer): - async def authenticate(self, request): - # Custom auth logic - return await oauth_verify(request) -``` + Docker -.->|launches server in container| Server + SDK -->|HTTP/WS| Server -**Custom workspace configuration**: -```python -server = AgentServer( - workspace_factory=lambda user: DockerWorkspace( - image=f"custom-image-{user.tier}", - resource_limits=user.resource_limits - ) -) -``` + classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px + classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px -**Custom middleware**: -```python -@server.middleware -async def logging_middleware(request, call_next): - # Custom logging - response = await call_next(request) - return response + class Server primary + class SDK,Docker secondary ``` -## Next Steps - -### For Usage Examples +- SDK’s `RemoteWorkspace` and higher-level `RemoteConversation` use these endpoints (source: openhands/sdk/workspace/remote/*, openhands/sdk/conversation/impl/remote_conversation.py). -- [Local Agent Server](/sdk/guides/agent-server/local-server) - Run locally -- [Docker Sandboxed Server](/sdk/guides/agent-server/docker-sandbox) - Docker setup -- [API Sandboxed Server](/sdk/guides/agent-server/api-sandbox) - Remote API -- [Remote Agent Server Overview](/sdk/guides/agent-server/overview) - All options +## See Also -### For Related Architecture +- [Workspace Architecture](/sdk/arch/workspace) – HTTP delegation model +- [SDK Architecture](/sdk/arch/overview) – Packages and modes -- [Workspace Architecture](/sdk/arch/workspace) - RemoteAPIWorkspace details -- [SDK Architecture](/sdk/arch/sdk) - Core framework -- [Architecture Overview](/sdk/arch/overview) - System design - -### For Implementation Details - -- [`openhands/agent_server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands/agent_server) - Server source -- [`examples/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples) - Working examples +--- +Last updated: 2025-12-09 06:57 UTC +Source commit (software-agent-sdk): `93d405c9` diff --git a/sdk/arch/security.mdx b/sdk/arch/security.mdx index c8118fe6..ae3c5100 100644 --- a/sdk/arch/security.mdx +++ b/sdk/arch/security.mdx @@ -5,7 +5,7 @@ description: High-level architecture of action security analysis and validation The **Security** system evaluates agent actions for potential risks before execution. It provides pluggable security analyzers that assess action risk levels and enforce confirmation policies based on security characteristics. -**Source:** [`openhands-sdk/penhands/sdk/security/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-sdk/openhands/sdk/security) +**Source:** [`openhands-sdk/openhands/sdk/security/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-sdk/openhands/sdk/security) ## Core Responsibilities @@ -58,7 +58,7 @@ flowchart TB Check --> Mode Mode --> Decision - + classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px classDef tertiary fill:#fff4df,stroke:#b7791f,stroke-width:2px @@ -102,6 +102,11 @@ flowchart TB Analyze --> Medium Analyze --> High Analyze --> Unknown + +--- +Last updated: 2025-12-09 06:57 UTC +Source commit (software-agent-sdk): `93d405c9` + style Low fill:#d1fae5,stroke:#10b981,stroke-width:2px style Medium fill:#fef3c7,stroke:#f59e0b,stroke-width:2px From 3cc7816411a9131e19115ef01dd02808124518f3 Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 9 Dec 2025 07:12:28 +0000 Subject: [PATCH 02/11] docs: add inline GitHub source links per guidelines (agent-server.mdx)\n\nCo-authored-by: openhands --- sdk/arch/agent-server.mdx | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index 17874772..2f09c691 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -11,11 +11,11 @@ Source: [`openhands-agent-server/`](https://github.com/OpenHands/software-agent- The server provides: -1. **Conversation lifecycle API** - Create, run, pause, delete conversations (source: openhands/agent_server/conversation_router.py) -2. **Event access** - Search, count, get, batch-get conversation events; WebSocket event streaming (source: openhands/agent_server/event_router.py, openhands/agent_server/sockets.py) -3. **Execution utilities** - Start and monitor bash commands; file upload/download; simple Git ops (source: openhands/agent_server/bash_router.py, file_router.py, git_router.py) -4. **Tool registry listing** - Introspect available tools on the server (source: openhands/agent_server/tool_router.py) -5. **Server details** - Health, alive, and server info endpoints (source: openhands/agent_server/server_details_router.py) +1. **Conversation lifecycle API** - Create, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) +2. **Event access** - Search, count, get, batch-get conversation events; WebSocket event streaming ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) +3. **Execution utilities** - Start and monitor bash commands; file upload/download; simple Git ops ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) +4. **Tool registry listing** - Introspect available tools on the server ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) +5. **Server details** - Health, alive, and server info endpoints ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) ## Architecture @@ -57,13 +57,13 @@ flowchart TB ``` - App construction and route wiring happen in [`api.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/api.py): the app mounts a single `/api` router that includes conversation, event, tool, bash, git, file, vscode, and desktop routers. -- Event and VSCode/Desktop services are initialized in the lifespan context (source: openhands/agent_server/api.py). +- Event and VSCode/Desktop services are initialized in the lifespan context ([api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py)). ## Authentication -- HTTP requests: header `X-Session-API-Key` if session keys are configured (source: openhands/agent_server/dependencies.py, `create_session_api_key_dependency`) -- WebSocket: query parameter `session_api_key` (source: openhands/agent_server/dependencies.py, sockets.py) -- Configuration source: environment-driven `Config` (source: openhands/agent_server/config.py) +- HTTP requests: header `X-Session-API-Key` if session keys are configured ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py)) +- WebSocket: query parameter `session_api_key` ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) +- Configuration source: environment-driven `Config` ([config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py)) ```mermaid flowchart LR @@ -75,7 +75,7 @@ flowchart LR All REST endpoints are mounted under `/api` unless noted. -- Conversations (source: openhands/agent_server/conversation_router.py) +- Conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) - `GET /api/conversations/search` – list - `GET /api/conversations/count` – count - `GET /api/conversations/{conversation_id}` – get @@ -91,43 +91,43 @@ All REST endpoints are mounted under `/api` unless noted. - `POST /api/conversations/{id}/security_analyzer` – set analyzer - `POST /api/conversations/{id}/ask_agent` – question-only (no state change) -- Events (source: openhands/agent_server/event_router.py) +- Events ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py)) - `GET /api/conversations/{conversation_id}/events/search` - `GET /api/conversations/{conversation_id}/events/count` - `GET /api/conversations/{conversation_id}/events/{event_id}` - `GET /api/conversations/{conversation_id}/events?event_ids=...` - `POST /api/conversations/{conversation_id}/events` – send `Message` -- Bash (source: openhands/agent_server/bash_router.py) +- Bash ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py)) - `POST /api/bash/start_bash_command` - `POST /api/bash/execute_bash_command` - `GET /api/bash/bash_events/search|{event_id}|` (list/get) - `DELETE /api/bash/bash_events` – clear -- Files (source: openhands/agent_server/file_router.py) +- Files ([file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)) - `POST /api/file/upload/{path}` – upload to absolute path - `GET /api/file/download/{path}` – download absolute path - `GET /api/file/download-trajectory/{conversation_id}` – zip state -- Git (source: openhands/agent_server/git_router.py) +- Git ([git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) - `GET /api/git/changes/{path}` - `GET /api/git/diff/{path}` -- Tools (source: openhands/agent_server/tool_router.py) +- Tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) - `GET /api/tools/` – list registered tools -- Server details (source: openhands/agent_server/server_details_router.py) +- Server details ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) - `GET /alive`, `GET /health`, `GET /server_info` -- WebSockets (source: openhands/agent_server/sockets.py) +- WebSockets ([sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) - `WS /sockets/events/{conversation_id}?session_api_key=...&resend_all=bool` - `WS /sockets/bash-events?session_api_key=...&resend_all=bool` ## Design Notes -- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP (source: openhands-workspace/openhands/workspace/docker/workspace.py). -- Request/response models are Pydantic classes in `models.py` (source: openhands/agent_server/models.py). -- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads (sources: dependencies.py, file_router.py). +- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP ([docker/workspace.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-workspace/openhands/workspace/docker/workspace.py)). +- Request/response models are Pydantic classes in `models.py` ([models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py)). +- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)). ## Component Relationships From 89ebfa0710f17e1626b9fbdb1c7e75d9f72dfb5e Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 9 Dec 2025 07:17:56 +0000 Subject: [PATCH 03/11] docs: move Last updated footer to end of file (security.mdx)\n\nCo-authored-by: openhands --- sdk/arch/security.mdx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/arch/security.mdx b/sdk/arch/security.mdx index ae3c5100..50493b9c 100644 --- a/sdk/arch/security.mdx +++ b/sdk/arch/security.mdx @@ -103,11 +103,7 @@ flowchart TB Analyze --> High Analyze --> Unknown ---- -Last updated: 2025-12-09 06:57 UTC -Source commit (software-agent-sdk): `93d405c9` - style Low fill:#d1fae5,stroke:#10b981,stroke-width:2px style Medium fill:#fef3c7,stroke:#f59e0b,stroke-width:2px style High fill:#ffe8e8,stroke:#dc2626,stroke-width:2px @@ -313,3 +309,8 @@ flowchart LR - **[Agent Architecture](/sdk/arch/agent)** - How agents use security analyzers - **[Tool System](/sdk/arch/tool-system)** - Tool annotations and metadata; includes MCP tool hints - **[Security Guide](/sdk/guides/security)** - Configuring security policies + +--- +Last updated: 2025-12-09 06:57 UTC +Source commit (software-agent-sdk): `93d405c9` + From 334d2bfcb4dd9f9c3963fc00c57f73e53010eb39 Mon Sep 17 00:00:00 2001 From: enyst Date: Thu, 11 Dec 2025 17:51:01 +0000 Subject: [PATCH 04/11] docs(agent-server): add Client SDK section with REST + WebSocket examples, inline source links\n\nCo-authored-by: openhands --- sdk/arch/agent-server.mdx | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index 2f09c691..c0f78000 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -155,5 +155,93 @@ flowchart LR - [SDK Architecture](/sdk/arch/overview) – Packages and modes --- + +## Client SDK + +Python examples for interacting with Agent Server: + +```python +# Minimal REST client using httpx (no SDK wrapper required) +# Endpoints from conversation/event routers: +# - POST /api/conversations/{conversation_id}/events (send message) +# - GET /api/conversations/{conversation_id}/events/search (read events) +# (source: event_router.py) +# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py + +import httpx + +BASE_URL = "https://agent-server.example.com" +API_KEY = "your-api-key" +CONVERSATION_ID = "your-conversation-uuid" + +headers = {"X-Session-API-Key": API_KEY} + +# Send a user message and start the agent loop +send = { + "role": "user", + "content": [{"type": "text", "text": "Hello, agent!"}], + "run": True, +} +r = httpx.post( + f"{BASE_URL}/api/conversations/{CONVERSATION_ID}/events", + json=send, + headers=headers, +) +r.raise_for_status() + +# Poll recent events (use WebSockets for streaming if preferred) +resp = httpx.get( + f"{BASE_URL}/api/conversations/{CONVERSATION_ID}/events/search", + headers=headers, + params={"limit": 50}, +) +resp.raise_for_status() +for ev in resp.json().get("items", []): + print(ev.get("kind"), ev.get("source")) +``` + + +To create a new conversation via REST, post a StartConversationRequest to `/api/conversations`. +See the JSON example in +[conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py) +(START_CONVERSATION_EXAMPLES). + + +### WebSocket streaming example (events) + +```python +# Stream conversation events over WebSocket +# Endpoint: /sockets/events/{conversation_id}?session_api_key=... +# (source: sockets.py) +# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py + +import asyncio +import json +import websockets + +BASE_WS = "wss://agent-server.example.com" +API_KEY = "your-api-key" +CONVERSATION_ID = "your-conversation-uuid" + +async def stream_events(): + ws_url = ( + f"{BASE_WS}/sockets/events/{CONVERSATION_ID}" + f"?session_api_key={API_KEY}&resend_all=false" + ) + async with websockets.connect(ws_url) as ws: + while True: + raw = await ws.recv() + event = json.loads(raw) + print(event.get("kind"), event.get("source")) + +asyncio.run(stream_events()) +``` + + +WebSockets require passing the session key as a query parameter +(`session_api_key`). See +[sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py). + + Last updated: 2025-12-09 06:57 UTC Source commit (software-agent-sdk): `93d405c9` From 26d140285a70fdbbfb682f2f0088db850f711b6d Mon Sep 17 00:00:00 2001 From: enyst Date: Thu, 11 Dec 2025 17:51:58 +0000 Subject: [PATCH 05/11] docs(agent-server): add bash-events WebSocket streaming example with inline source links\n\nCo-authored-by: openhands --- sdk/arch/agent-server.mdx | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index c0f78000..f26ea8d3 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -243,5 +243,37 @@ WebSockets require passing the session key as a query parameter [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py). -Last updated: 2025-12-09 06:57 UTC + +### WebSocket streaming example (bash-events) + +```python +# Stream bash events over WebSocket +# Endpoint: /sockets/bash-events?session_api_key=... +# (source: sockets.py) +# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py + +import asyncio +import json +import websockets + +BASE_WS = "wss://agent-server.example.com" +API_KEY = "your-api-key" + +async def stream_bash_events(): + ws_url = f"{BASE_WS}/sockets/bash-events?session_api_key={API_KEY}&resend_all=false" + async with websockets.connect(ws_url) as ws: + while True: + raw = await ws.recv() + event = json.loads(raw) + print(event.get("kind"), event.get("timestamp")) + +asyncio.run(stream_bash_events()) +``` + + +Bash WebSocket events include BashCommand and BashOutput items. For filtering or paging +via REST, see the bash event routes in +[bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py). + + Source commit (software-agent-sdk): `93d405c9` From f0328fa55538e55da628acab053909d7669e9e77 Mon Sep 17 00:00:00 2001 From: enyst Date: Thu, 11 Dec 2025 17:53:20 +0000 Subject: [PATCH 06/11] docs(nav): add SDK architecture link for agent-server to left nav Place agent-server at the end of the SDK Components section for consistent ordering. Co-authored-by: openhands --- docs.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs.json b/docs.json index ddeff833..7648a712 100644 --- a/docs.json +++ b/docs.json @@ -280,7 +280,8 @@ "sdk/arch/llm", "sdk/arch/skill", "sdk/arch/condenser", - "sdk/arch/security" + "sdk/arch/security", + "sdk/arch/agent-server" ] } ] From 4c8fa8b6f007f7835f79067a9b85b7918c9f4eb3 Mon Sep 17 00:00:00 2001 From: enyst Date: Thu, 11 Dec 2025 23:12:11 +0000 Subject: [PATCH 07/11] docs(agent-server): resolve conflicts, fix Mermaid blocks, rename to 'Agent Server', and simplify selected endpoints Also keeps concise Client SDK REST + WebSocket examples with inline GitHub source links. Co-authored-by: openhands --- sdk/arch/agent-server.mdx | 142 +++++++++++++++----------------------- 1 file changed, 55 insertions(+), 87 deletions(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index f26ea8d3..65e76ea6 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -1,9 +1,9 @@ --- -title: Agent Server Package +title: Agent Server description: HTTP API server for remote agent execution with conversation/event endpoints and WebSocket streaming. --- -The Agent Server package (`openhands.agent_server`) exposes a FastAPI-based HTTP/WebSocket interface that runs OpenHands conversations remotely. It is stateless with respect to agent logic and does not orchestrate containers by itself. Containerization is handled by workspace implementations (e.g., DockerWorkspace) that launch this server inside a sandbox when needed. +The Agent Server (`openhands.agent_server`) provides an HTTP/WebSocket interface for running OpenHands conversations remotely. It is stateless with respect to agent logic; containerization is handled by workspace implementations (e.g., DockerWorkspace) that launch this server inside a sandbox when needed. Source: [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) @@ -11,11 +11,11 @@ Source: [`openhands-agent-server/`](https://github.com/OpenHands/software-agent- The server provides: -1. **Conversation lifecycle API** - Create, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) -2. **Event access** - Search, count, get, batch-get conversation events; WebSocket event streaming ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) -3. **Execution utilities** - Start and monitor bash commands; file upload/download; simple Git ops ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) -4. **Tool registry listing** - Introspect available tools on the server ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) -5. **Server details** - Health, alive, and server info endpoints ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) +1. **Conversation lifecycle API** – Start, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) +2. **Event access** – Search/get conversation events; WebSocket streaming ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) +3. **Execution utilities** – Bash commands, file upload/download, simple Git ops ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) +4. **Tool registry** – List registered tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) +5. **Server details** – Health, uptime/idle info ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) ## Architecture @@ -24,7 +24,7 @@ The server provides: flowchart TB Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] - subgraph Routers[Routers (/api/*)] + subgraph Routers["Routers (/api/*)"] Conv[conversations] Events[conversations/{id}/events] Bash[bash] @@ -33,7 +33,7 @@ flowchart TB Tools[tools] end - WS[/sockets/*\n(WebSocket)/] + WS[/sockets/* (WebSocket)/] API --> Routers API --> WS @@ -56,105 +56,47 @@ flowchart TB class Services tertiary ``` -- App construction and route wiring happen in [`api.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/api.py): the app mounts a single `/api` router that includes conversation, event, tool, bash, git, file, vscode, and desktop routers. +- App construction and route wiring happen in [api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py): a single `/api` router includes conversation, event, tool, bash, git, file, vscode, and desktop routers. - Event and VSCode/Desktop services are initialized in the lifespan context ([api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py)). -## Authentication - -- HTTP requests: header `X-Session-API-Key` if session keys are configured ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py)) -- WebSocket: query parameter `session_api_key` ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) -- Configuration source: environment-driven `Config` ([config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py)) - -```mermaid -flowchart LR - Client -->|X-Session-API-Key| HTTP[HTTP /api/*] - Client -->|session_api_key| WS[/sockets/*] -``` - ## Endpoints (selected) -All REST endpoints are mounted under `/api` unless noted. +Representative API surface under `/api`: - Conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) - - `GET /api/conversations/search` – list - - `GET /api/conversations/count` – count - - `GET /api/conversations/{conversation_id}` – get - - `GET /api/conversations?ids=...` – batch get - - `POST /api/conversations` – start (accepts `StartConversationRequest` built with SDK `Agent` and `LocalWorkspace`) - - `POST /api/conversations/{conversation_id}/run` – run loop - - `POST /api/conversations/{conversation_id}/pause` – pause - - `DELETE /api/conversations/{conversation_id}` – delete - - `PATCH /api/conversations/{conversation_id}` – update metadata (title) - - `POST /api/conversations/{id}/generate_title` – title via LLM - - `POST /api/conversations/{id}/secrets` – update secrets - - `POST /api/conversations/{id}/confirmation_policy` – set policy - - `POST /api/conversations/{id}/security_analyzer` – set analyzer - - `POST /api/conversations/{id}/ask_agent` – question-only (no state change) + - `POST /api/conversations` – start conversation (StartConversationRequest) + - `POST /api/conversations/{conversation_id}/run` – run agent loop + - `POST /api/conversations/{conversation_id}/events` – send Message (optionally `run: true`) - Events ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py)) - - `GET /api/conversations/{conversation_id}/events/search` - - `GET /api/conversations/{conversation_id}/events/count` - - `GET /api/conversations/{conversation_id}/events/{event_id}` - - `GET /api/conversations/{conversation_id}/events?event_ids=...` - - `POST /api/conversations/{conversation_id}/events` – send `Message` + - `GET /api/conversations/{conversation_id}/events/search` – list events + - `GET /api/conversations/{conversation_id}/events/{event_id}` – get event - Bash ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py)) - - `POST /api/bash/start_bash_command` - - `POST /api/bash/execute_bash_command` - - `GET /api/bash/bash_events/search|{event_id}|` (list/get) - - `DELETE /api/bash/bash_events` – clear + - `POST /api/bash/start_bash_command` – start background command + - `GET /api/bash/bash_events/search` – list bash events - Files ([file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)) - - `POST /api/file/upload/{path}` – upload to absolute path - - `GET /api/file/download/{path}` – download absolute path - - `GET /api/file/download-trajectory/{conversation_id}` – zip state - -- Git ([git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) - - `GET /api/git/changes/{path}` - - `GET /api/git/diff/{path}` + - `POST /api/file/upload/{path}` – upload file (absolute path) + - `GET /api/file/download/{path}` – download file (absolute path) - Tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) - `GET /api/tools/` – list registered tools - Server details ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) - - `GET /alive`, `GET /health`, `GET /server_info` - -- WebSockets ([sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) - - `WS /sockets/events/{conversation_id}?session_api_key=...&resend_all=bool` - - `WS /sockets/bash-events?session_api_key=...&resend_all=bool` - -## Design Notes + - `GET /server_info` – uptime and idle_time -- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP ([docker/workspace.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-workspace/openhands/workspace/docker/workspace.py)). -- Request/response models are Pydantic classes in `models.py` ([models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py)). -- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)). - -## Component Relationships +## Authentication ```mermaid flowchart LR - Server[Agent Server] - SDK[SDK RemoteWorkspace] - Docker[DockerWorkspace] - - Docker -.->|launches server in container| Server - SDK -->|HTTP/WS| Server - - classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px - classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px - - class Server primary - class SDK,Docker secondary + Client -->|X-Session-API-Key| HTTP[HTTP /api/*] + Client -->|session_api_key| WS[/sockets/*] ``` -- SDK’s `RemoteWorkspace` and higher-level `RemoteConversation` use these endpoints (source: openhands/sdk/workspace/remote/*, openhands/sdk/conversation/impl/remote_conversation.py). - -## See Also - -- [Workspace Architecture](/sdk/arch/workspace) – HTTP delegation model -- [SDK Architecture](/sdk/arch/overview) – Packages and modes - ---- +- HTTP requests: header `X-Session-API-Key` if configured ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py)) +- WebSocket: query parameter `session_api_key` ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) +- Configuration: environment-driven `Config` ([config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py)) ## Client SDK @@ -243,7 +185,6 @@ WebSockets require passing the session key as a query parameter [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py). - ### WebSocket streaming example (bash-events) ```python @@ -272,8 +213,35 @@ asyncio.run(stream_bash_events()) Bash WebSocket events include BashCommand and BashOutput items. For filtering or paging -via REST, see the bash event routes in +via REST, see [bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py). +## Design Notes + +- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP ([docker/workspace.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-workspace/openhands/workspace/docker/workspace.py)). +- Request/response models are Pydantic classes in `models.py` ([models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py)). +- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)). + +## Component Relationships + +```mermaid +%%{init: {"theme": "default", "flowchart": {"nodeSpacing": 30}} }%% +flowchart LR + Server[Agent Server] + SDK[SDK RemoteWorkspace] + Docker[DockerWorkspace] + + Docker -.->|launches server in container| Server + SDK -->|HTTP/WS| Server + + classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px + classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px + + class Server primary + class SDK,Docker secondary +``` + +--- +Last updated: 2025-12-09 06:57 UTC Source commit (software-agent-sdk): `93d405c9` From abf463f838885d79fff628fa1c98180a37181dc6 Mon Sep 17 00:00:00 2001 From: enyst Date: Mon, 22 Dec 2025 11:53:34 +0000 Subject: [PATCH 08/11] sdk/arch(agent-server): fix Mermaid syntax for Mintlify (escape wildcards, avoid /* and braces in labels) - Replace '/api/*' and '/sockets/*' with safe labels in diagrams - Replace '{id}' with '' in node label Co-authored-by: openhands --- sdk/arch/agent-server.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index 65e76ea6..06e9a0ba 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -24,16 +24,16 @@ The server provides: flowchart TB Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] - subgraph Routers["Routers (/api/*)"] + subgraph Routers["Routers (/api)"] Conv[conversations] - Events[conversations/{id}/events] + Events[conversations//events] Bash[bash] File[file] Git[git] Tools[tools] end - WS[/sockets/* (WebSocket)/] + WS["/sockets (WebSocket)"] API --> Routers API --> WS @@ -90,8 +90,8 @@ Representative API surface under `/api`: ```mermaid flowchart LR - Client -->|X-Session-API-Key| HTTP[HTTP /api/*] - Client -->|session_api_key| WS[/sockets/*] + Client -->|X-Session-API-Key| HTTP["HTTP /api"] + Client -->|session_api_key| WS["/sockets"] ``` - HTTP requests: header `X-Session-API-Key` if configured ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py)) From 4cf89e8fbb794c13bb240dd7bcf24b1f90473f99 Mon Sep 17 00:00:00 2001 From: enyst Date: Mon, 22 Dec 2025 16:45:34 +0000 Subject: [PATCH 09/11] docs(nav): move Agent Server architecture page under Remote Agent Server group\n\n- Remove sdk/arch/agent-server from SDK Components\n- Add sdk/arch/agent-server under Guides > Remote Agent Server (after overview)\n\nCo-authored-by: openhands --- docs.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs.json b/docs.json index 7d19b5c1..c76261d0 100644 --- a/docs.json +++ b/docs.json @@ -243,6 +243,8 @@ "group": "Remote Agent Server", "pages": [ "sdk/guides/agent-server/overview", + "sdk/arch/agent-server", + "sdk/guides/agent-server/local-server", "sdk/guides/agent-server/docker-sandbox", "sdk/guides/agent-server/api-sandbox", @@ -282,8 +284,7 @@ "sdk/arch/llm", "sdk/arch/skill", "sdk/arch/condenser", - "sdk/arch/security", - "sdk/arch/agent-server" + "sdk/arch/security" ] } ] From f57c53e2bfaf20a9e9e388bee83abce68367ca8d Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 23 Dec 2025 17:53:59 +0000 Subject: [PATCH 10/11] docs: consolidate agent-server architecture and guides pages - Refactored sdk/arch/agent-server.mdx to focus on technical architecture: - Removed duplicate content and client SDK examples - Added clear API endpoints table - Added authentication table - Added links to workspace implementations (Docker, API, Cloud) - Added See Also section linking to guides - Refactored sdk/guides/agent-server/overview.mdx to focus on practical usage: - Renamed title to 'Remote Agent Server' for clarity - Removed duplicate architecture diagrams - Added workspace types comparison table - Added OpenHands Cloud workspace example - Simplified 'How It Works' section - Added links to architecture page for technical details - Updated Next Steps sections in all agent-server guide pages for consistency Co-authored-by: openhands --- sdk/arch/agent-server.mdx | 242 +++++++------------- sdk/guides/agent-server/api-sandbox.mdx | 8 +- sdk/guides/agent-server/cloud-workspace.mdx | 7 +- sdk/guides/agent-server/docker-sandbox.mdx | 9 +- sdk/guides/agent-server/local-server.mdx | 9 +- sdk/guides/agent-server/overview.mdx | 184 +++++++-------- 6 files changed, 190 insertions(+), 269 deletions(-) diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx index 06e9a0ba..567a0aab 100644 --- a/sdk/arch/agent-server.mdx +++ b/sdk/arch/agent-server.mdx @@ -3,19 +3,21 @@ title: Agent Server description: HTTP API server for remote agent execution with conversation/event endpoints and WebSocket streaming. --- -The Agent Server (`openhands.agent_server`) provides an HTTP/WebSocket interface for running OpenHands conversations remotely. It is stateless with respect to agent logic; containerization is handled by workspace implementations (e.g., DockerWorkspace) that launch this server inside a sandbox when needed. +The **Agent Server** (`openhands.agent_server`) is a FastAPI-based HTTP/WebSocket server that enables remote agent execution. It provides the API layer that workspace implementations connect to for running conversations in isolated environments. -Source: [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) +**Source:** [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) -## Core Responsibilities + +For practical usage guides on deploying and connecting to agent servers, see the [Remote Agent Server Overview](/sdk/guides/agent-server/overview). + -The server provides: +## Core Responsibilities -1. **Conversation lifecycle API** – Start, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) -2. **Event access** – Search/get conversation events; WebSocket streaming ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) -3. **Execution utilities** – Bash commands, file upload/download, simple Git ops ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) +1. **Conversation lifecycle** – Start, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) +2. **Event streaming** – Search/get events via REST; real-time streaming via WebSocket ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) +3. **Execution utilities** – Bash commands, file upload/download, Git operations ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) 4. **Tool registry** – List registered tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) -5. **Server details** – Health, uptime/idle info ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) +5. **Health monitoring** – Server uptime and idle time ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) ## Architecture @@ -24,16 +26,16 @@ The server provides: flowchart TB Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] - subgraph Routers["Routers (/api)"] + subgraph Routers["Routers under /api"] Conv[conversations] - Events[conversations//events] + Events[events] Bash[bash] File[file] Git[git] Tools[tools] end - WS["/sockets (WebSocket)"] + WS["WebSocket under /sockets"] API --> Routers API --> WS @@ -56,172 +58,66 @@ flowchart TB class Services tertiary ``` -- App construction and route wiring happen in [api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py): a single `/api` router includes conversation, event, tool, bash, git, file, vscode, and desktop routers. -- Event and VSCode/Desktop services are initialized in the lifespan context ([api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py)). +### Key Components -## Endpoints (selected) +| Component | Purpose | Source | +|-----------|---------|--------| +| **FastAPI App** | Main application with lifespan management | [api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py) | +| **ConversationService** | Manages conversation state and execution | [conversation_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_service.py) | +| **EventService** | Handles event storage and streaming | [event_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_service.py) | +| **Request/Response Models** | Pydantic models for API payloads | [models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py) | -Representative API surface under `/api`: +## API Endpoints -- Conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) - - `POST /api/conversations` – start conversation (StartConversationRequest) - - `POST /api/conversations/{conversation_id}/run` – run agent loop - - `POST /api/conversations/{conversation_id}/events` – send Message (optionally `run: true`) +### REST Endpoints (`/api`) -- Events ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py)) - - `GET /api/conversations/{conversation_id}/events/search` – list events - - `GET /api/conversations/{conversation_id}/events/{event_id}` – get event +| Router | Endpoint | Description | +|--------|----------|-------------| +| **Conversations** | `POST /api/conversations` | Start new conversation | +| | `POST /api/conversations/{id}/run` | Run agent loop | +| | `POST /api/conversations/{id}/events` | Send message (optionally with `run: true`) | +| **Events** | `GET /api/conversations/{id}/events/search` | List events | +| | `GET /api/conversations/{id}/events/{event_id}` | Get specific event | +| **Bash** | `POST /api/bash/start_bash_command` | Start background command | +| | `GET /api/bash/bash_events/search` | List bash events | +| **Files** | `POST /api/file/upload/{path}` | Upload file | +| | `GET /api/file/download/{path}` | Download file | +| **Tools** | `GET /api/tools/` | List registered tools | +| **Server** | `GET /server_info` | Get uptime and idle time | -- Bash ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py)) - - `POST /api/bash/start_bash_command` – start background command - - `GET /api/bash/bash_events/search` – list bash events +### WebSocket Endpoints (`/sockets`) -- Files ([file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)) - - `POST /api/file/upload/{path}` – upload file (absolute path) - - `GET /api/file/download/{path}` – download file (absolute path) - -- Tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) - - `GET /api/tools/` – list registered tools - -- Server details ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) - - `GET /server_info` – uptime and idle_time +| Endpoint | Description | +|----------|-------------| +| `/sockets/events/{conversation_id}` | Stream conversation events | +| `/sockets/bash-events` | Stream bash command events | ## Authentication ```mermaid flowchart LR - Client -->|X-Session-API-Key| HTTP["HTTP /api"] - Client -->|session_api_key| WS["/sockets"] -``` - -- HTTP requests: header `X-Session-API-Key` if configured ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py)) -- WebSocket: query parameter `session_api_key` ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) -- Configuration: environment-driven `Config` ([config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py)) - -## Client SDK - -Python examples for interacting with Agent Server: - -```python -# Minimal REST client using httpx (no SDK wrapper required) -# Endpoints from conversation/event routers: -# - POST /api/conversations/{conversation_id}/events (send message) -# - GET /api/conversations/{conversation_id}/events/search (read events) -# (source: event_router.py) -# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py - -import httpx - -BASE_URL = "https://agent-server.example.com" -API_KEY = "your-api-key" -CONVERSATION_ID = "your-conversation-uuid" - -headers = {"X-Session-API-Key": API_KEY} - -# Send a user message and start the agent loop -send = { - "role": "user", - "content": [{"type": "text", "text": "Hello, agent!"}], - "run": True, -} -r = httpx.post( - f"{BASE_URL}/api/conversations/{CONVERSATION_ID}/events", - json=send, - headers=headers, -) -r.raise_for_status() - -# Poll recent events (use WebSockets for streaming if preferred) -resp = httpx.get( - f"{BASE_URL}/api/conversations/{CONVERSATION_ID}/events/search", - headers=headers, - params={"limit": 50}, -) -resp.raise_for_status() -for ev in resp.json().get("items", []): - print(ev.get("kind"), ev.get("source")) + Client -->|X-Session-API-Key header| HTTP["HTTP /api"] + Client -->|session_api_key query param| WS["/sockets"] ``` - -To create a new conversation via REST, post a StartConversationRequest to `/api/conversations`. -See the JSON example in -[conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py) -(START_CONVERSATION_EXAMPLES). - +| Method | Authentication | Source | +|--------|---------------|--------| +| **HTTP** | `X-Session-API-Key` header | [dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py) | +| **WebSocket** | `session_api_key` query parameter | [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py) | +| **Config** | Environment-driven settings | [config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py) | -### WebSocket streaming example (events) - -```python -# Stream conversation events over WebSocket -# Endpoint: /sockets/events/{conversation_id}?session_api_key=... -# (source: sockets.py) -# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py - -import asyncio -import json -import websockets - -BASE_WS = "wss://agent-server.example.com" -API_KEY = "your-api-key" -CONVERSATION_ID = "your-conversation-uuid" - -async def stream_events(): - ws_url = ( - f"{BASE_WS}/sockets/events/{CONVERSATION_ID}" - f"?session_api_key={API_KEY}&resend_all=false" - ) - async with websockets.connect(ws_url) as ws: - while True: - raw = await ws.recv() - event = json.loads(raw) - print(event.get("kind"), event.get("source")) - -asyncio.run(stream_events()) -``` - - -WebSockets require passing the session key as a query parameter -(`session_api_key`). See -[sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py). - - -### WebSocket streaming example (bash-events) - -```python -# Stream bash events over WebSocket -# Endpoint: /sockets/bash-events?session_api_key=... -# (source: sockets.py) -# https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py +## Design Notes -import asyncio -import json -import websockets +**Stateless Server:** The agent server itself does not manage containers or infrastructure. It runs inside whatever environment is provided—containerization and lifecycle are handled by workspace implementations. -BASE_WS = "wss://agent-server.example.com" -API_KEY = "your-api-key" +**Workspace Integration:** Workspace implementations spawn or connect to the agent server: +- [**DockerWorkspace**](/sdk/guides/agent-server/docker-sandbox) launches the server inside a Docker container +- [**APIRemoteWorkspace**](/sdk/guides/agent-server/api-sandbox) connects to a server provisioned by a runtime API +- [**OpenHandsCloudWorkspace**](/sdk/guides/agent-server/cloud-workspace) connects to OpenHands Cloud-managed sandboxes -async def stream_bash_events(): - ws_url = f"{BASE_WS}/sockets/bash-events?session_api_key={API_KEY}&resend_all=false" - async with websockets.connect(ws_url) as ws: - while True: - raw = await ws.recv() - event = json.loads(raw) - print(event.get("kind"), event.get("timestamp")) +For workspace architecture details, see [Workspace Architecture](/sdk/arch/workspace). -asyncio.run(stream_bash_events()) -``` - - -Bash WebSocket events include BashCommand and BashOutput items. For filtering or paging -via REST, see -[bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py). - - -## Design Notes - -- The server itself does not manage Docker containers. Containerization and lifecycle are handled by workspace implementations such as `DockerWorkspace` in the `openhands-workspace` package, which run this server inside the container and connect via HTTP ([docker/workspace.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-workspace/openhands/workspace/docker/workspace.py)). -- Request/response models are Pydantic classes in `models.py` ([models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py)). -- Security: schema-level API key checks, path validation for file ops (absolute path enforcement), and typed payloads ([dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py)). +**Security:** API key validation at the schema level, absolute path enforcement for file operations, and typed Pydantic payloads. ## Component Relationships @@ -229,19 +125,37 @@ via REST, see %%{init: {"theme": "default", "flowchart": {"nodeSpacing": 30}} }%% flowchart LR Server[Agent Server] - SDK[SDK RemoteWorkspace] + Remote[RemoteWorkspace] Docker[DockerWorkspace] + API[APIRemoteWorkspace] + Cloud[OpenHandsCloudWorkspace] - Docker -.->|launches server in container| Server - SDK -->|HTTP/WS| Server + Docker -.->|spawns container with| Server + API -.->|connects via runtime API to| Server + Cloud -.->|connects via cloud API to| Server + Remote -->|HTTP/WS| Server classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px class Server primary - class SDK,Docker secondary + class Remote,Docker,API,Cloud secondary ``` +**Relationship Characteristics:** +- **DockerWorkspace → Agent Server**: Spawns container with server, connects via HTTP/WS +- **APIRemoteWorkspace → Agent Server**: Runtime API provisions server, SDK connects via HTTP/WS +- **OpenHandsCloudWorkspace → Agent Server**: Cloud provisions sandbox, SDK connects via HTTP/WS +- **RemoteWorkspace → Agent Server**: Base class for all remote workspace HTTP/WS communication + +## See Also + +- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** – Practical usage guide +- **[Workspace Architecture](/sdk/arch/workspace)** – Workspace abstraction and implementations +- **[Docker Sandbox Guide](/sdk/guides/agent-server/docker-sandbox)** – Running with DockerWorkspace +- **[API Sandbox Guide](/sdk/guides/agent-server/api-sandbox)** – Using APIRemoteWorkspace +- **[Cloud Workspace Guide](/sdk/guides/agent-server/cloud-workspace)** – Using OpenHandsCloudWorkspace + --- -Last updated: 2025-12-09 06:57 UTC +Last updated: 2025-12-23 UTC Source commit (software-agent-sdk): `93d405c9` diff --git a/sdk/guides/agent-server/api-sandbox.mdx b/sdk/guides/agent-server/api-sandbox.mdx index 4e9d8931..ba789dea 100644 --- a/sdk/guides/agent-server/api-sandbox.mdx +++ b/sdk/guides/agent-server/api-sandbox.mdx @@ -194,7 +194,7 @@ All agent execution happens on the remote runtime infrastructure. ## Next Steps -- **[Docker Sandboxed Server](/sdk/guides/agent-server/docker-sandbox)** -- **[Local Agent Server](/sdk/guides/agent-server/local-server)** -- **[Agent Server Overview](/sdk/guides/agent-server/overview)** - Architecture and implementation details -- **[Agent Server Package Architecture](/sdk/arch/agent-server)** - Remote execution architecture +- **[Docker Sandbox](/sdk/guides/agent-server/docker-sandbox)** - Run with DockerWorkspace +- **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Development without containers +- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options +- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/cloud-workspace.mdx b/sdk/guides/agent-server/cloud-workspace.mdx index eaf51bb4..d911ff91 100644 --- a/sdk/guides/agent-server/cloud-workspace.mdx +++ b/sdk/guides/agent-server/cloud-workspace.mdx @@ -205,7 +205,8 @@ This verifies connectivity to the cloud sandbox and ensures the environment is r ## Next Steps -- **[API-based Sandbox](/sdk/guides/agent-server/api-sandbox)** - Connect to Runtime API service -- **[Docker Sandboxed Server](/sdk/guides/agent-server/docker-sandbox)** - Run locally with Docker +- **[API Sandbox](/sdk/guides/agent-server/api-sandbox)** - Runtime API integration +- **[Docker Sandbox](/sdk/guides/agent-server/docker-sandbox)** - Isolated Docker containers - **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Development without containers -- **[Agent Server Overview](/sdk/guides/agent-server/overview)** - Architecture and implementation details +- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options +- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/docker-sandbox.mdx b/sdk/guides/agent-server/docker-sandbox.mdx index e1b2ca6d..ff4cb91f 100644 --- a/sdk/guides/agent-server/docker-sandbox.mdx +++ b/sdk/guides/agent-server/docker-sandbox.mdx @@ -607,7 +607,8 @@ http://localhost:8012/vnc.html?autoconnect=1&resize=remote ## Next Steps -- **[Local Agent Server](/sdk/guides/agent-server/local-server)** -- **[Agent Server Overview](/sdk/guides/agent-server/overview)** - Architecture and implementation details -- **[API Sandboxed Server](/sdk/guides/agent-server/api-sandbox)** - Connect to hosted API service -- **[Agent Server Package Architecture](/sdk/arch/agent-server)** - Remote execution architecture +- **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Development without containers +- **[API Sandbox](/sdk/guides/agent-server/api-sandbox)** - Runtime API integration +- **[Cloud Workspace](/sdk/guides/agent-server/cloud-workspace)** - OpenHands Cloud managed sandboxes +- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options +- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/local-server.mdx b/sdk/guides/agent-server/local-server.mdx index 89f8f823..765c8a66 100644 --- a/sdk/guides/agent-server/local-server.mdx +++ b/sdk/guides/agent-server/local-server.mdx @@ -363,7 +363,8 @@ This allows you to inspect the conversation history, analyze agent behavior, and ## Next Steps -- **[Docker Sandboxed Server](/sdk/guides/agent-server/docker-sandbox)** - Run server in Docker for isolation -- **[API Sandboxed Server](/sdk/guides/agent-server/api-sandbox)** - Connect to hosted API service -- **[Agent Server Overview](/sdk/guides/agent-server/overview)** - Architecture and implementation details -- **[Agent Server Package Architecture](/sdk/arch/agent-server)** - Remote execution architecture +- **[Docker Sandbox](/sdk/guides/agent-server/docker-sandbox)** - Isolated Docker containers +- **[API Sandbox](/sdk/guides/agent-server/api-sandbox)** - Runtime API integration +- **[Cloud Workspace](/sdk/guides/agent-server/cloud-workspace)** - OpenHands Cloud managed sandboxes +- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options +- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/overview.mdx b/sdk/guides/agent-server/overview.mdx index 14970832..d73b6247 100644 --- a/sdk/guides/agent-server/overview.mdx +++ b/sdk/guides/agent-server/overview.mdx @@ -1,12 +1,17 @@ --- -title: Overview +title: Remote Agent Server description: Run agents on remote servers with isolated workspaces for production deployments. --- -Remote Agent Servers package the Software Agent SDK into containers you can deploy anywhere (Kubernetes, VMs, on‑prem, any cloud) with strong isolation. The remote path uses the exact same SDK API as local—switching is just changing the workspace argument; your Conversation code stays the same. +Remote Agent Servers package the Software Agent SDK into containers you can deploy anywhere—Kubernetes, VMs, on-prem, or any cloud—with strong isolation. The remote path uses the exact same SDK API as local; switching is just changing the workspace argument. + +For technical architecture details (endpoints, authentication, component design), see [Agent Server Architecture](/sdk/arch/agent-server). + -For example, switching from a local workspace to a Docker‑based remote agent server: +## Switching from Local to Remote + +Your conversation code stays the same—just swap the workspace: ```python lines # Local → Docker @@ -18,9 +23,7 @@ with DockerWorkspace( # [!code ++] conversation = Conversation(agent=agent, workspace=workspace) # [!code ++] ``` -Use `DockerWorkspace` with the pre-built agent server image for the fastest startup. When you need to build from a custom base image, switch to [`DockerDevWorkspace`](/sdk/guides/agent-server/docker-sandbox). - -Or switching to an API‑based remote workspace (via [OpenHands Runtime API](https://runtime.all-hands.dev/)): +Or connect to a hosted runtime API: ```python lines # Local → Remote API @@ -34,125 +37,126 @@ with APIRemoteWorkspace( # [!code ++] conversation = Conversation(agent=agent, workspace=workspace) # [!code ++] ``` +Or use OpenHands Cloud for fully managed sandboxes: -## What is a Remote Agent Server? +```python lines +# Local → OpenHands Cloud +conversation = Conversation(agent=agent, workspace=os.getcwd()) # [!code --] +from openhands.workspace import OpenHandsCloudWorkspace # [!code ++] +with OpenHandsCloudWorkspace( # [!code ++] + cloud_api_url="https://app.all-hands.dev", # [!code ++] + cloud_api_key="YOUR_CLOUD_API_KEY", # [!code ++] +) as workspace: # [!code ++] + conversation = Conversation(agent=agent, workspace=workspace) # [!code ++] +``` -A Remote Agent Server is an HTTP/WebSocket server that: -- **Package the Software Agent SDK into containers** and deploy on your own infrastructure (Kubernetes, VMs, on-prem, or cloud) -- **Runs agents** on dedicated infrastructure -- **Manages workspaces** (Docker containers or remote sandboxes) -- **Streams events** to clients via WebSocket -- **Handles command and file operations** (execute command, upload, download), check [base class](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/workspace/base.py) for more details -- **Provides isolation** between different agent executions +## Workspace Types -Think of it as the "backend" for your agent, while your Python code acts as the "frontend" client. +| Workspace | What It Does | Best For | +|-----------|-------------|----------| +| [**DockerWorkspace**](/sdk/guides/agent-server/docker-sandbox) | Spawns a Docker container with agent server | Local development with isolation, self-hosted deployments | +| [**APIRemoteWorkspace**](/sdk/guides/agent-server/api-sandbox) | Connects to a runtime API that provisions sandboxes | Custom runtime environments, CI/CD pipelines | +| [**OpenHandsCloudWorkspace**](/sdk/guides/agent-server/cloud-workspace) | Connects to OpenHands Cloud for managed sandboxes | Production use, no infrastructure management | +| [**Local Server**](/sdk/guides/agent-server/local-server) | Runs agent server in-process | Testing, development without Docker | -{/* -Same interfaces as local: -[BaseConversation](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/conversation/base.py), -[ConversationStateProtocol](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/conversation/base.py), -[EventsListBase](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/conversation/events_list_base.py). Server-backed impl: -[RemoteConversation](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/conversation/impl/remote_conversation.py). - */} +## How It Works +When you use a remote workspace, the SDK automatically: -## Architecture Overview +1. **Starts or connects to an agent server** inside the workspace environment +2. **Creates a RemoteConversation** that communicates via HTTP/WebSocket +3. **Streams events in real-time** through WebSocket callbacks +4. **Handles cleanup** when the context manager exits -Remote Agent Servers follow a simple three-part architecture: +```python +with DockerWorkspace(server_image="ghcr.io/openhands/agent-server:latest-python") as workspace: + # Workspace spawns container with agent server + + conversation = Conversation(agent=agent, workspace=workspace, callbacks=[on_event]) + # SDK creates RemoteConversation, connects via WebSocket + + conversation.send_message("Create a hello.py file") + conversation.run() + # Agent executes inside container, events stream to callbacks + +# Container automatically cleaned up +``` -```mermaid -graph TD - Client[Client Code] -->|HTTP / WebSocket| Server[Agent Server] - Server --> Workspace[Workspace] +### File and Command Operations - subgraph Workspace Types - Workspace --> Local[Local Folder] - Workspace --> Docker[Docker Container] - Workspace --> API[Remote Sandbox via API] - end +Workspaces provide file and command operations that work identically whether local or remote: - Local --> Files[File System] - Docker --> Container[Isolated Runtime] - API --> Cloud[Cloud Infrastructure] +```python +# Execute commands in the workspace +result = workspace.execute_command("ls -la") +print(result.stdout) - style Client fill:#e1f5fe - style Server fill:#fff3e0 - style Workspace fill:#e8f5e8 +# Upload/download files +workspace.file_upload("local/file.txt", "/workspace/file.txt") +workspace.file_download("/workspace/output.txt", "local/output.txt") ``` -1. **Client (Python SDK)** — Your application creates and controls conversations using the SDK. -2. **Agent Server** — A lightweight HTTP/WebSocket service that runs the agent and manages workspace execution. -3. **Workspace** — An isolated environment (local, Docker, or remote VM) where the agent code runs. - -The same SDK API works across all three workspace types—you just switch which workspace the conversation connects to. - -## How Remote Conversations Work +These operations are proxied through the agent server API, keeping your code environment-agnostic. -Each step in the diagram maps directly to how the SDK and server interact: +## Deployment Options -### 1. Workspace Connection → *(Client → Server)* +### Self-Hosted (Docker) -When you create a conversation with a remote workspace (e.g., `DockerWorkspace` or `APIRemoteWorkspace`), the SDK automatically starts or connects to an agent server inside that workspace: +Use `DockerWorkspace` to run agent servers in containers on your own infrastructure: ```python -with DockerWorkspace(server_image="ghcr.io/openhands/agent-server:latest") as workspace: +from openhands.workspace import DockerWorkspace + +with DockerWorkspace( + server_image="ghcr.io/openhands/agent-server:latest-python", + host_port=8010, +) as workspace: conversation = Conversation(agent=agent, workspace=workspace) ``` -This turns the local `Conversation` into a **[RemoteConversation](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/conversation/impl/remote_conversation.py)** that speaks to the agent server over HTTP/WebSocket. - - -### 2. Server Initialization → *(Server → Workspace)* - -Once the workspace starts: -- It launches the agent server process. -- Waits for it to be ready. -- Shares the server URL with the SDK client. +See [Docker Sandbox Guide](/sdk/guides/agent-server/docker-sandbox) for details. -You don’t need to manage this manually—the workspace context handles startup and teardown automatically. +### Runtime API -### 3. Event Streaming → *(Bidirectional WebSocket)* - -The client and agent server maintain a live WebSocket connection for streaming events: +Use `APIRemoteWorkspace` to connect to a runtime API service that provisions sandboxes: ```python -def on_event(event): - print(f"Received: {type(event).__name__}") +from openhands.workspace import APIRemoteWorkspace -conversation = Conversation(agent=agent, workspace=workspace, callbacks=[on_event]) +with APIRemoteWorkspace( + runtime_api_url="https://runtime.eval.all-hands.dev", + runtime_api_key=os.getenv("RUNTIME_API_KEY"), + server_image="ghcr.io/openhands/agent-server:latest-python", +) as workspace: + conversation = Conversation(agent=agent, workspace=workspace) ``` -This allows you to see real-time updates from the running agent as it executes tasks inside the workspace. +See [API Sandbox Guide](/sdk/guides/agent-server/api-sandbox) for details. -### 4. Workspace Supports File and Command Operations → *(Server ↔ Workspace)* +### OpenHands Cloud -Workspace supports file and command operations via the agent server API ([base class](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/workspace/base.py)), ensuring isolation and consistent behavior: +Use `OpenHandsCloudWorkspace` for fully managed sandbox environments: ```python -workspace.file_upload(local_path, remote_path) -workspace.file_download(remote_path, local_path) -result = workspace.execute_command("ls -la") -print(result.stdout) -``` - -These commands are proxied through the agent server, whether it’s a Docker container or a remote VM, keeping your client code environment-agnostic. - -### Summary +from openhands.workspace import OpenHandsCloudWorkspace -The architecture makes remote execution seamless: -- Your **client code** stays the same. -- The **agent server** manages execution and streaming. -- The **workspace** provides secure, isolated runtime environments. +with OpenHandsCloudWorkspace( + cloud_api_url="https://app.all-hands.dev", + cloud_api_key=os.getenv("OPENHANDS_CLOUD_API_KEY"), +) as workspace: + conversation = Conversation(agent=agent, workspace=workspace) +``` -Switching from local to remote is just a matter of swapping the workspace class—no code rewrites needed. +See [Cloud Workspace Guide](/sdk/guides/agent-server/cloud-workspace) for details. ## Next Steps -Explore different deployment options: - -- **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Run agent server in the same process -- **[Docker Sandboxed Server](/sdk/guides/agent-server/docker-sandbox)** - Run agent server in isolated Docker containers -- **[API Sandboxed Server](/sdk/guides/agent-server/api-sandbox)** - Connect to hosted agent server via API +**Deployment Guides:** +- [Local Agent Server](/sdk/guides/agent-server/local-server) - Run server in-process for development +- [Docker Sandbox](/sdk/guides/agent-server/docker-sandbox) - Isolated Docker containers +- [API Sandbox](/sdk/guides/agent-server/api-sandbox) - Runtime API integration +- [Cloud Workspace](/sdk/guides/agent-server/cloud-workspace) - OpenHands Cloud managed sandboxes -For architectural details: -- **[Agent Server Package Architecture](/sdk/arch/agent-server)** - Remote execution architecture and deployment +**Architecture:** +- [Agent Server Architecture](/sdk/arch/agent-server) - Technical details, endpoints, authentication +- [Workspace Architecture](/sdk/arch/workspace) - Workspace abstraction and implementations From 419a6582676390fb7a658833d844a42636d9baee Mon Sep 17 00:00:00 2001 From: enyst Date: Wed, 31 Dec 2025 05:46:17 +0000 Subject: [PATCH 11/11] docs: consolidate agent-server content into overview - Move unique content from sdk/arch/agent-server.mdx to sdk/arch/overview.mdx - Remove sdk/arch/agent-server.mdx (content now in overview) - Update all references to point to the new location - Update docs.json navigation to remove agent-server page Co-authored-by: openhands --- docs.json | 2 - sdk/arch/agent-server.mdx | 161 -------------------- sdk/arch/overview.mdx | 89 ++++++++++- sdk/arch/sdk.mdx | 2 +- sdk/arch/workspace.mdx | 2 +- sdk/guides/agent-server/api-sandbox.mdx | 2 +- sdk/guides/agent-server/cloud-workspace.mdx | 2 +- sdk/guides/agent-server/docker-sandbox.mdx | 2 +- sdk/guides/agent-server/local-server.mdx | 2 +- sdk/guides/agent-server/overview.mdx | 4 +- 10 files changed, 91 insertions(+), 177 deletions(-) delete mode 100644 sdk/arch/agent-server.mdx diff --git a/docs.json b/docs.json index 61cbffd1..14591ece 100644 --- a/docs.json +++ b/docs.json @@ -245,8 +245,6 @@ "group": "Remote Agent Server", "pages": [ "sdk/guides/agent-server/overview", - "sdk/arch/agent-server", - "sdk/guides/agent-server/local-server", "sdk/guides/agent-server/docker-sandbox", "sdk/guides/agent-server/api-sandbox", diff --git a/sdk/arch/agent-server.mdx b/sdk/arch/agent-server.mdx deleted file mode 100644 index 567a0aab..00000000 --- a/sdk/arch/agent-server.mdx +++ /dev/null @@ -1,161 +0,0 @@ ---- -title: Agent Server -description: HTTP API server for remote agent execution with conversation/event endpoints and WebSocket streaming. ---- - -The **Agent Server** (`openhands.agent_server`) is a FastAPI-based HTTP/WebSocket server that enables remote agent execution. It provides the API layer that workspace implementations connect to for running conversations in isolated environments. - -**Source:** [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) - - -For practical usage guides on deploying and connecting to agent servers, see the [Remote Agent Server Overview](/sdk/guides/agent-server/overview). - - -## Core Responsibilities - -1. **Conversation lifecycle** – Start, run, pause, delete conversations ([conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_router.py)) -2. **Event streaming** – Search/get events via REST; real-time streaming via WebSocket ([event_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_router.py), [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py)) -3. **Execution utilities** – Bash commands, file upload/download, Git operations ([bash_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/bash_router.py), [file_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/file_router.py), [git_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/git_router.py)) -4. **Tool registry** – List registered tools ([tool_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/tool_router.py)) -5. **Health monitoring** – Server uptime and idle time ([server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/server_details_router.py)) - -## Architecture - -```mermaid -%%{init: {"theme": "default", "flowchart": {"nodeSpacing": 28, "rankSpacing": 40}} }%% -flowchart TB - Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] - - subgraph Routers["Routers under /api"] - Conv[conversations] - Events[events] - Bash[bash] - File[file] - Git[git] - Tools[tools] - end - - WS["WebSocket under /sockets"] - - API --> Routers - API --> WS - - subgraph Services[Services] - ConvSvc[ConversationService] - EventSvc[EventService] - end - - Routers --> ConvSvc - Routers --> EventSvc - WS --> EventSvc - - classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px - classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px - classDef tertiary fill:#fff4df,stroke:#b7791f,stroke-width:2px - - class API primary - class Routers,WS secondary - class Services tertiary -``` - -### Key Components - -| Component | Purpose | Source | -|-----------|---------|--------| -| **FastAPI App** | Main application with lifespan management | [api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py) | -| **ConversationService** | Manages conversation state and execution | [conversation_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_service.py) | -| **EventService** | Handles event storage and streaming | [event_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_service.py) | -| **Request/Response Models** | Pydantic models for API payloads | [models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py) | - -## API Endpoints - -### REST Endpoints (`/api`) - -| Router | Endpoint | Description | -|--------|----------|-------------| -| **Conversations** | `POST /api/conversations` | Start new conversation | -| | `POST /api/conversations/{id}/run` | Run agent loop | -| | `POST /api/conversations/{id}/events` | Send message (optionally with `run: true`) | -| **Events** | `GET /api/conversations/{id}/events/search` | List events | -| | `GET /api/conversations/{id}/events/{event_id}` | Get specific event | -| **Bash** | `POST /api/bash/start_bash_command` | Start background command | -| | `GET /api/bash/bash_events/search` | List bash events | -| **Files** | `POST /api/file/upload/{path}` | Upload file | -| | `GET /api/file/download/{path}` | Download file | -| **Tools** | `GET /api/tools/` | List registered tools | -| **Server** | `GET /server_info` | Get uptime and idle time | - -### WebSocket Endpoints (`/sockets`) - -| Endpoint | Description | -|----------|-------------| -| `/sockets/events/{conversation_id}` | Stream conversation events | -| `/sockets/bash-events` | Stream bash command events | - -## Authentication - -```mermaid -flowchart LR - Client -->|X-Session-API-Key header| HTTP["HTTP /api"] - Client -->|session_api_key query param| WS["/sockets"] -``` - -| Method | Authentication | Source | -|--------|---------------|--------| -| **HTTP** | `X-Session-API-Key` header | [dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py) | -| **WebSocket** | `session_api_key` query parameter | [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py) | -| **Config** | Environment-driven settings | [config.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/config.py) | - -## Design Notes - -**Stateless Server:** The agent server itself does not manage containers or infrastructure. It runs inside whatever environment is provided—containerization and lifecycle are handled by workspace implementations. - -**Workspace Integration:** Workspace implementations spawn or connect to the agent server: -- [**DockerWorkspace**](/sdk/guides/agent-server/docker-sandbox) launches the server inside a Docker container -- [**APIRemoteWorkspace**](/sdk/guides/agent-server/api-sandbox) connects to a server provisioned by a runtime API -- [**OpenHandsCloudWorkspace**](/sdk/guides/agent-server/cloud-workspace) connects to OpenHands Cloud-managed sandboxes - -For workspace architecture details, see [Workspace Architecture](/sdk/arch/workspace). - -**Security:** API key validation at the schema level, absolute path enforcement for file operations, and typed Pydantic payloads. - -## Component Relationships - -```mermaid -%%{init: {"theme": "default", "flowchart": {"nodeSpacing": 30}} }%% -flowchart LR - Server[Agent Server] - Remote[RemoteWorkspace] - Docker[DockerWorkspace] - API[APIRemoteWorkspace] - Cloud[OpenHandsCloudWorkspace] - - Docker -.->|spawns container with| Server - API -.->|connects via runtime API to| Server - Cloud -.->|connects via cloud API to| Server - Remote -->|HTTP/WS| Server - - classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px - classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px - - class Server primary - class Remote,Docker,API,Cloud secondary -``` - -**Relationship Characteristics:** -- **DockerWorkspace → Agent Server**: Spawns container with server, connects via HTTP/WS -- **APIRemoteWorkspace → Agent Server**: Runtime API provisions server, SDK connects via HTTP/WS -- **OpenHandsCloudWorkspace → Agent Server**: Cloud provisions sandbox, SDK connects via HTTP/WS -- **RemoteWorkspace → Agent Server**: Base class for all remote workspace HTTP/WS communication - -## See Also - -- **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** – Practical usage guide -- **[Workspace Architecture](/sdk/arch/workspace)** – Workspace abstraction and implementations -- **[Docker Sandbox Guide](/sdk/guides/agent-server/docker-sandbox)** – Running with DockerWorkspace -- **[API Sandbox Guide](/sdk/guides/agent-server/api-sandbox)** – Using APIRemoteWorkspace -- **[Cloud Workspace Guide](/sdk/guides/agent-server/cloud-workspace)** – Using OpenHandsCloudWorkspace - ---- -Last updated: 2025-12-23 UTC -Source commit (software-agent-sdk): `93d405c9` diff --git a/sdk/arch/overview.mdx b/sdk/arch/overview.mdx index a1dfdf64..09a5fba1 100644 --- a/sdk/arch/overview.mdx +++ b/sdk/arch/overview.mdx @@ -194,17 +194,94 @@ For full list of implemented workspaces, see the [source code](https://github.co **Purpose:** FastAPI-based HTTP/WebSocket server for remote agent execution. -**Features:** -- REST API & WebSocket endpoints for conversations, bash, files, events, desktop, and VSCode -- Service management with isolated per-user sessions -- API key authentication and health checking +**Source:** [`openhands-agent-server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server) -**Deployment:** Runs inside containers (via `DockerWorkspace`) or as standalone process (connected via `RemoteWorkspace`). +**Deployment:** Runs inside containers (via `DockerWorkspace`) or as standalone process (connected via `RemoteWorkspace`). The agent server itself does not manage containers—containerization and lifecycle are handled by [workspace implementations](/sdk/arch/workspace). **Use Cases:** Multi-user web apps, SaaS products, distributed systems. +#### Architecture + +```mermaid +%%{init: {"theme": "default", "flowchart": {"nodeSpacing": 28, "rankSpacing": 40}} }%% +flowchart TB + Client[Client / SDK] -->|HTTP/WS| API[FastAPI App] + + subgraph Routers["Routers under /api"] + Conv[conversations] + Events[events] + Bash[bash] + File[file] + Git[git] + Tools[tools] + end + + WS["WebSocket under /sockets"] + + API --> Routers + API --> WS + + subgraph Services[Services] + ConvSvc[ConversationService] + EventSvc[EventService] + end + + Routers --> ConvSvc + Routers --> EventSvc + WS --> EventSvc + + classDef primary fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px + classDef secondary fill:#e8f3ff,stroke:#2b6cb0,stroke-width:2px + classDef tertiary fill:#fff4df,stroke:#b7791f,stroke-width:2px + + class API primary + class Routers,WS secondary + class Services tertiary +``` + +#### Key Components + +| Component | Purpose | Source | +|-----------|---------|--------| +| **FastAPI App** | Main application with lifespan management | [api.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/api.py) | +| **ConversationService** | Manages conversation state and execution | [conversation_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/conversation_service.py) | +| **EventService** | Handles event storage and streaming | [event_service.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/event_service.py) | +| **Request/Response Models** | Pydantic models for API payloads | [models.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/models.py) | + +#### API Endpoints + +**REST Endpoints (`/api`):** + +| Router | Endpoint | Description | +|--------|----------|-------------| +| **Conversations** | `POST /api/conversations` | Start new conversation | +| | `POST /api/conversations/{id}/run` | Run agent loop | +| | `POST /api/conversations/{id}/events` | Send message (optionally with `run: true`) | +| **Events** | `GET /api/conversations/{id}/events/search` | List events | +| | `GET /api/conversations/{id}/events/{event_id}` | Get specific event | +| **Bash** | `POST /api/bash/start_bash_command` | Start background command | +| | `GET /api/bash/bash_events/search` | List bash events | +| **Files** | `POST /api/file/upload/{path}` | Upload file | +| | `GET /api/file/download/{path}` | Download file | +| **Tools** | `GET /api/tools/` | List registered tools | +| **Server** | `GET /server_info` | Get uptime and idle time | + +**WebSocket Endpoints (`/sockets`):** + +| Endpoint | Description | +|----------|-------------| +| `/sockets/events/{conversation_id}` | Stream conversation events | +| `/sockets/bash-events` | Stream bash command events | + +#### Authentication + +| Method | Authentication | Source | +|--------|---------------|--------| +| **HTTP** | `X-Session-API-Key` header | [dependencies.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/dependencies.py) | +| **WebSocket** | `session_api_key` query parameter | [sockets.py](https://github.com/OpenHands/software-agent-sdk/blob/HEAD/openhands-agent-server/openhands/agent_server/sockets.py) | + -For implementation details, see the [source code](https://github.com/OpenHands/software-agent-sdk/tree/main/openhands-agent-server). +For practical usage guides on deploying and connecting to agent servers, see the [Remote Agent Server Guide](/sdk/guides/agent-server/overview). ## How Components Work Together diff --git a/sdk/arch/sdk.mdx b/sdk/arch/sdk.mdx index a237f36a..58e66b30 100644 --- a/sdk/arch/sdk.mdx +++ b/sdk/arch/sdk.mdx @@ -455,7 +455,7 @@ Everything uses Pydantic models: - [Tool System](/sdk/arch/tool-system) - Built-in tool implementations - [Workspace Architecture](/sdk/arch/workspace) - Execution environments -- [Agent Server Architecture](/sdk/arch/agent-server) - Remote execution +- [Agent Server Architecture](/sdk/arch/overview#agent-server-package-openhandsagent_server) - Remote execution ### For Implementation Details diff --git a/sdk/arch/workspace.mdx b/sdk/arch/workspace.mdx index dbff538b..5b820294 100644 --- a/sdk/arch/workspace.mdx +++ b/sdk/arch/workspace.mdx @@ -203,5 +203,5 @@ flowchart LR ## See Also - **[Conversation Architecture](/sdk/arch/conversation)** - How workspace type determines conversation implementation -- **[Agent Server](/sdk/arch/agent-server)** - Remote execution API +- **[Agent Server](/sdk/arch/overview#agent-server-package-openhandsagent_server)** - Remote execution API - **[Tool System](/sdk/arch/tool-system)** - Tools that use workspace for execution diff --git a/sdk/guides/agent-server/api-sandbox.mdx b/sdk/guides/agent-server/api-sandbox.mdx index ba789dea..a378572a 100644 --- a/sdk/guides/agent-server/api-sandbox.mdx +++ b/sdk/guides/agent-server/api-sandbox.mdx @@ -197,4 +197,4 @@ All agent execution happens on the remote runtime infrastructure. - **[Docker Sandbox](/sdk/guides/agent-server/docker-sandbox)** - Run with DockerWorkspace - **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Development without containers - **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options -- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication +- **[Agent Server Architecture](/sdk/arch/overview#agent-server-package-openhandsagent_server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/cloud-workspace.mdx b/sdk/guides/agent-server/cloud-workspace.mdx index d911ff91..a521e4ae 100644 --- a/sdk/guides/agent-server/cloud-workspace.mdx +++ b/sdk/guides/agent-server/cloud-workspace.mdx @@ -209,4 +209,4 @@ This verifies connectivity to the cloud sandbox and ensures the environment is r - **[Docker Sandbox](/sdk/guides/agent-server/docker-sandbox)** - Isolated Docker containers - **[Local Agent Server](/sdk/guides/agent-server/local-server)** - Development without containers - **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options -- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication +- **[Agent Server Architecture](/sdk/arch/overview#agent-server-package-openhandsagent_server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/docker-sandbox.mdx b/sdk/guides/agent-server/docker-sandbox.mdx index 04e3f22e..2f16f1ad 100644 --- a/sdk/guides/agent-server/docker-sandbox.mdx +++ b/sdk/guides/agent-server/docker-sandbox.mdx @@ -606,4 +606,4 @@ http://localhost:8012/vnc.html?autoconnect=1&resize=remote - **[API Sandbox](/sdk/guides/agent-server/api-sandbox)** - Runtime API integration - **[Cloud Workspace](/sdk/guides/agent-server/cloud-workspace)** - OpenHands Cloud managed sandboxes - **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options -- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication +- **[Agent Server Architecture](/sdk/arch/overview#agent-server-package-openhandsagent_server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/local-server.mdx b/sdk/guides/agent-server/local-server.mdx index 455f1296..c5a59e9c 100644 --- a/sdk/guides/agent-server/local-server.mdx +++ b/sdk/guides/agent-server/local-server.mdx @@ -363,4 +363,4 @@ This allows you to inspect the conversation history, analyze agent behavior, and - **[API Sandbox](/sdk/guides/agent-server/api-sandbox)** - Runtime API integration - **[Cloud Workspace](/sdk/guides/agent-server/cloud-workspace)** - OpenHands Cloud managed sandboxes - **[Remote Agent Server Overview](/sdk/guides/agent-server/overview)** - Workspace types and deployment options -- **[Agent Server Architecture](/sdk/arch/agent-server)** - Technical details, endpoints, authentication +- **[Agent Server Architecture](/sdk/arch/overview#agent-server-package-openhandsagent_server)** - Technical details, endpoints, authentication diff --git a/sdk/guides/agent-server/overview.mdx b/sdk/guides/agent-server/overview.mdx index d73b6247..795dfbed 100644 --- a/sdk/guides/agent-server/overview.mdx +++ b/sdk/guides/agent-server/overview.mdx @@ -6,7 +6,7 @@ description: Run agents on remote servers with isolated workspaces for productio Remote Agent Servers package the Software Agent SDK into containers you can deploy anywhere—Kubernetes, VMs, on-prem, or any cloud—with strong isolation. The remote path uses the exact same SDK API as local; switching is just changing the workspace argument. -For technical architecture details (endpoints, authentication, component design), see [Agent Server Architecture](/sdk/arch/agent-server). +For technical architecture details (endpoints, authentication, component design), see the [Agent Server Package section](/sdk/arch/overview#agent-server-package-openhandsagent_server) in the Architecture Overview. ## Switching from Local to Remote @@ -158,5 +158,5 @@ See [Cloud Workspace Guide](/sdk/guides/agent-server/cloud-workspace) for detail - [Cloud Workspace](/sdk/guides/agent-server/cloud-workspace) - OpenHands Cloud managed sandboxes **Architecture:** -- [Agent Server Architecture](/sdk/arch/agent-server) - Technical details, endpoints, authentication +- [Architecture Overview](/sdk/arch/overview#agent-server-package-openhandsagent_server) - Technical details, endpoints, authentication - [Workspace Architecture](/sdk/arch/workspace) - Workspace abstraction and implementations