-
Notifications
You must be signed in to change notification settings - Fork 12
Add guide: app-server + custom agent integration #194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Draft
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
4c4b8ae
docs: Add guide for running V1 app-server with local agent-server and...
openhands-agent b3df7b8
docs: fix MDX code span for alive/server_info to satisfy link checker
openhands-agent d3cf9a9
docs: add developers guide to docs.json nav and polish formatting for...
enyst 67a7969
fix(docs): resolve Mint acorn parse error by removing <code>{...}</co...
enyst cb9d2cd
docs(nav): move local agent-server guide under Web → Advanced Configu...
enyst d38492f
Update openhands/usage/developers/v1-local-agent-server.mdx
enyst 7d5058c
Update openhands/usage/developers/v1-local-agent-server.mdx
enyst 156e8fd
docs: split local GUI runtime vs SDK agent customization\n\n- Scope v...
enyst d34fa62
Update openhands/usage/developers/v1-local-agent-server.mdx
enyst a85c2d9
Update sdk/guides/agent-server/app-integration.mdx
enyst d148877
Update sdk/guides/agent-server/app-integration.mdx
enyst 5af3e36
Merge branch 'main' into docs/v1-local-agent-server-guide
enyst File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| --- | ||
| title: Run OpenHands App-Server with Local SDK Agent-Server | ||
| description: Run the OpenHands V1 app-server backed by a purely local SDK agent-server, no Docker or remote runtime required. | ||
| --- | ||
|
|
||
| This guide shows how to run the OpenHands V1 app-server while spawning a fully local agent-server process (no Docker, no remote runtime). | ||
|
|
||
| <Note> | ||
| Applies to the V1 app-server path enabled under <code>/api/v1</code>. | ||
| </Note> | ||
|
|
||
| ## Prerequisites | ||
| - Python 3.12, Node 22.x, Poetry 1.8+ | ||
| - OpenHands repository checked out | ||
| - <code>software-agent-sdk</code> is an install-time dependency of OpenHands (see <code>pyproject.toml</code>), and provides the <code>openhands.agent_server</code> entrypoint | ||
|
|
||
| ## Where V1 Lives (Execution Path Overview) | ||
| OpenHands V1 exposes its API under <code>/api/v1</code> and keeps the V1 server logic in <code>app_server/</code>: | ||
| - The FastAPI app includes V1 only when <code>ENABLE_V1</code> != <code>"0"</code>. See [server/app.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/server/app.py#L90-L98). | ||
| - The V1 router aggregates <code>app_server</code> endpoints. See [v1_router.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/v1_router.py). | ||
| - For a local runtime, the app-server launches a separate agent-server process (from software-agent-sdk) on a free localhost port via the process sandbox: [process_sandbox_service](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/sandbox/process_sandbox_service.py#L113-L154). It executes <code>python -m openhands.agent_server</code> and probes <code>/alive</code>. | ||
| - This selection comes from env→config wiring. When <code>RUNTIME</code> is <code>local</code> or <code>process</code>, injectors select the process-based sandbox/spec: see [app_server/config.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/config.py#L102-L160) and [process_sandbox_spec_service.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/sandbox/process_sandbox_spec_service.py#L17-L34). | ||
| - On the SDK side, the agent-server exposes <code>/alive</code> and <code>/health</code> (and <code>/api/*</code>). See [server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/server_details_router.py#L27-L41) and bootstrap in [agent_server/__main__.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/__main__.py#L1-L40). | ||
| - The app-server talks to the agent-server using <code>AsyncRemoteWorkspace</code> and the agent-server REST/WebSocket API. See [AsyncRemoteWorkspace](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/workspace/remote/async_remote_workspace.py) and where the app-server builds conversation requests in <code>_build_start_conversation_request_for_user</code> ([source](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/live_status_app_conversation_service.py#L929-L1014)). | ||
|
|
||
| ## Run App-Server with a Local Agent-Server | ||
|
|
||
| ### 1) Build OpenHands and Enable V1 | ||
| By default V1 is enabled (unless <code>ENABLE_V1=0</code>). Ensure you’re on Python 3.12 and have Poetry and Node installed, then: | ||
|
|
||
| ```bash Build | ||
| export INSTALL_DOCKER=0 # No Docker for this guide | ||
| export RUNTIME=process # Force process-based sandbox (spawns sub-process agent-server) | ||
| # optional: export ENABLE_V1=1 # V1 is enabled by default; set explicitly if you disabled it elsewhere | ||
|
|
||
| make build | ||
| ``` | ||
|
|
||
| ### 2) Run Backend and Frontend | ||
| For local development, either run everything together or separately. | ||
|
|
||
| ```bash Full App (Backend + Frontend) | ||
| # Adjust ports/hosts if you’re on a remote machine. | ||
| make run FRONTEND_PORT=12000 FRONTEND_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0 | ||
| ``` | ||
|
|
||
| or start servers individually: | ||
|
|
||
| ```bash Separate Servers | ||
| make start-backend | ||
| make start-frontend | ||
| ``` | ||
|
|
||
| ### 3) Start a V1 Conversation (Spawns Local Agent-Server) | ||
| From the UI (Chat → Start) or via the V1 endpoints under <code>/api/v1</code>, create a new conversation. The app-server will: | ||
| - Start a sandbox using the process sandbox service, which launches a local agent-server process via <code>python -m openhands.agent_server</code> | ||
| - Poll the agent-server <code>/alive</code> endpoint until it reports status <code>ok</code> | ||
| - Store the agent-server URL and a per-sandbox session API key, then reuse it for subsequent operations | ||
|
|
||
| ### 4) Verify the Local Agent-Server | ||
| You can list sandboxes via V1 API and find the exposed agent-server URL; the name in the response is <code>"agent-server"</code>. The health checks are: | ||
| - GET `{agent_server_url}/alive` → `{"status":"ok"}` (see [server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/server_details_router.py#L27-L41)) | ||
| - GET `{agent_server_url}/server_info` for uptime/idle info | ||
|
|
||
| ### 5) How the App-Server Talks to the Agent-Server | ||
| When reading/writing files or executing commands in the conversation’s workspace, the app-server uses <code>AsyncRemoteWorkspace</code> that targets the agent-server. Example usage: [app_conversation_router.read_conversation_file](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/app_conversation_router.py#L335-L409) and throughout [live_status_app_conversation_service](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/live_status_app_conversation_service.py). | ||
|
|
||
| ## Customize the Agent Loaded by the GUI | ||
|
|
||
| For customization paths (skills/MCP, agent presets, or defining a new Agent type the app can instantiate), see: | ||
| - /sdk/guides/agent-server/app-integration | ||
| - /sdk/guides/agent-custom | ||
| - /sdk/guides/custom-tools | ||
|
|
||
| ## Troubleshooting | ||
| - If no agent-server starts when you create a V1 conversation, ensure: | ||
| - <code>ENABLE_V1</code> is not <code>"0"</code> (V1 router included): [server/app.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/server/app.py#L90-L98) | ||
| - <code>RUNTIME</code> = <code>local</code> or <code>process</code> so the process sandbox is selected: [config_from_env](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/config.py#L102-L160) | ||
| - The spawned server is probed via <code>/alive</code>: [process_sandbox_service](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/sandbox/process_sandbox_service.py#L155-L200) | ||
| - To inspect the agent-server API, open its Swagger at `{agent_server_url}/docs` (the server is started via uvicorn in [__main__.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/__main__.py#L1-L40)). | ||
|
|
||
| ## References | ||
| - OpenHands V1 app-server boot and routing: [server/app.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/server/app.py#L90-L98), [v1_router.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/v1_router.py) | ||
| - Sandbox process service (spawns local agent-server): [process_sandbox_service.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/sandbox/process_sandbox_service.py#L113-L200) | ||
| - Env→injector selection for local runtime: [config.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/config.py#L102-L160) | ||
| - Default command and env to start agent-server: [process_sandbox_spec_service.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/sandbox/process_sandbox_spec_service.py#L17-L34) | ||
| - Agent-server app and health endpoints: [__main__.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/__main__.py#L1-L40), [server_details_router.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/server_details_router.py#L27-L41) | ||
| - Agent-server conversation API: [conversation_router.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-agent-server/openhands/agent_server/conversation_router.py) | ||
| - AsyncRemoteWorkspace client: [async_remote_workspace.py](https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/workspace/remote/async_remote_workspace.py) | ||
| - V1 agent composition in app-server: [live_status_app_conversation_service.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/live_status_app_conversation_service.py) | ||
| - Skills loading and merge points: [app_conversation_service_base.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/app_conversation_service_base.py#L56-L115), [skill_loader.py](https://github.com/OpenHands/OpenHands/blob/main/openhands/app_server/app_conversation/skill_loader.py) | ||
| - SDK documentation on agent-server modes: [/sdk/guides/agent-server/overview](/sdk/guides/agent-server/overview), [/sdk/guides/agent-server/local-server](/sdk/guides/agent-server/local-server) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| --- | ||
| title: Integrate SDK Agents with the OpenHands App | ||
| description: How the OpenHands app uses the SDK Agent Server and where to customize the agent that the GUI loads | ||
| --- | ||
|
|
||
| This guide explains how the OpenHands app (V1) composes an SDK Agent when you start a conversation in the GUI, and where you can customize behavior using the SDK. | ||
|
|
||
| <Note> | ||
| Best read alongside: <br/> | ||
| - <a href="/sdk/guides/agent-server/overview">Agent Server Overview</a><br/> | ||
| - <a href="/sdk/guides/agent-server/local-server">Run a Local Agent Server</a><br/> | ||
| - <a href="/sdk/guides/agent-custom">Creating Custom Agent</a> | ||
| </Note> | ||
|
|
||
| ## How the App Loads an SDK Agent | ||
|
|
||
| When you start a V1 conversation from the GUI, the app-server: | ||
| - Launches an SDK Agent Server (locally or via the configured host) | ||
| - Builds a StartConversationRequest that includes an Agent specification | ||
| - Sends that request to the Agent Server's conversation API | ||
|
|
||
| Key references: | ||
| - App builds the V1 router only if V1 is enabled: server/app.py | ||
| - Conversation request assembly: live_status_app_conversation_service.py | ||
| - Agent Server endpoints: conversation_router.py, server_details_router.py | ||
|
|
||
| ## Customization Paths | ||
|
|
||
| ### 1) Skills and MCP (No-Code) | ||
| The app merges skills and MCP server config into the agent context: | ||
| - User skills from `~/.openhands/skills` and `~/.openhands/microagents/` | ||
| - Repo/org skills resolved from your working repository | ||
| - MCP servers from settings and defaults (OpenHands + Tavily) | ||
|
|
||
| This path lets you steer agent behavior without changing code. | ||
|
|
||
| ### 2) Agent Type Selection (Low-Code) | ||
| The app selects an Agent preset based on AgentType (DEFAULT or PLAN). You can: | ||
| - Toggle the AgentType in the Start request (UI or API) | ||
| - Adjust LLM and MCP settings in the UI | ||
|
|
||
| See also SDK presets for default and planning agents. | ||
|
|
||
| ### 3) Define a New Agent Type in the App (Advanced) | ||
| If you need the GUI to instantiate a different agent layout (custom tools, system prompt, etc.): | ||
| 1. Add a new enum value to AgentType in the app | ||
| 2. Extend the builder to construct your custom Agent for that type | ||
| 3. Optionally expose it in the frontend for selection | ||
|
|
||
| This keeps the App as the source of truth for Agent construction while leveraging SDK components. | ||
|
|
||
| ## Validate with the SDK First | ||
|
|
||
| Before wiring into the App, validate your design directly with the SDK: | ||
| - Run the Local Agent Server guide to test endpoints | ||
| - Use the Creating Custom Agent guide to build presets and behaviors | ||
|
|
||
| ## See Also | ||
|
|
||
| - /sdk/guides/agent-custom | ||
| - /sdk/guides/custom-tools | ||
| - /sdk/guides/mcp | ||
| - /sdk/guides/agent-server/overview | ||
| - /sdk/guides/agent-server/local-server |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.