From f07778481eb5c50cefaed72978bc3a956093c56c Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 9 Dec 2025 07:07:07 +0000 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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`