A collection of example code for working with the OpenHands API.
Examples are grouped by topic. Some examples span more than one topic and are listed in every section that fits, so a given example may appear more than once.
Jump to a section:
- Sandbox lifecycle
- Conversation monitoring & reacting
- Secrets & authentication
- Plugins, skills & MCP
- Custom agents & tools
- Guardrails
- Hooks
Create, attach to, and tear down sandboxes (runtimes).
| Example | Description |
|---|---|
| start-sandbox | Start a sandbox (no conversation) and run commands via the agent-server REST API |
| clone-and-attach | Clone a repo + run .openhands/setup.sh in a sandbox, then attach a conversation to it |
| archive-sandbox | Archive/delete a conversation to release its Persistent Volume Claim (PVC) and free up storage resources |
Observe conversations and react to their state.
| Example | Description |
|---|---|
| conversation-metrics | CLI tool to retrieve cost and token usage for conversations |
| conversation-tags | Attach arbitrary key-value metadata to a conversation via tags (e.g. an external environment_url) and read it back from AppConversation.tags |
| react-to-state-websocket | React to conversation execution_status changes over the agent-server WebSocket (/sockets/events/{id}) instead of polling — two approaches (Cloud-attach vs. agent-direct) with trade-offs, plus in-sandbox hook alternatives |
| watch-terminal-state | Deep dive on react-to-state-websocket: detect a confirmed terminal execution_status over the WebSocket — handles both event shapes, treats finished as advisory (Stop-hook revertible), and uses log-safe first-message auth |
| server-info-idle | Poll GET /server_info.idle_time — the same idle signal runtime-api uses to reap sandboxes — to detect when the workspace has gone quiet (Cloud-first; --local fallback) |
| finish-callback | Notify an external URL the moment a conversation finishes with a Stop hook (push instead of poll); includes a local receiver server to prove the end-to-end flow |
Inject credentials and manage identity.
| Example | Description |
|---|---|
| per-conversation-secrets | Inject per-conversation secrets via REST API — both as bash env vars and to template an MCP server config (.mcp.json) bundled in a plugin |
| service-account-github-pat | Use one OpenHands SaaS account as a service account, overriding the managed GITHUB_TOKEN with each user's GitHub PAT per conversation |
| gpg-commit-signing | Configure GPG commit signing on every conversation (not just when a repo is selected) with a SessionStart hook that imports a key from a custom secret |
Extend conversations with plugins, skills, and MCP servers.
| Example | Description |
|---|---|
| load-plugin | Minimal: start a conversation with a plugin pre-loaded via the REST API |
| launch-plugin-badge | Build a no-code /launch link, HTML button, or README badge that loads a plugin |
| upload-skills | Upload a local agent-skills directory into a sandbox, then start a conversation that uses them |
| test-mcp-config | Validate MCP server configs (connection/auth) against a sandbox's agent-server via POST /api/mcp/test, before using them in a conversation |
| per-conversation-secrets | Template an MCP server config (.mcp.json) bundled in a plugin using per-conversation secrets injected via REST API (also listed under Secrets & authentication) |
Configure the agent and add custom tools.
| Example | Description |
|---|---|
| custom-agent-no-browser | Configure agent tools via the agent-server API (excludes the browser tool) |
| custom-agent-with-tool | Add custom server-side tools via source file upload + tool_module_qualnames |
| custom-agent-with-pip-tool | Load a custom tool from a published pip package (pip install --target + tool_module_qualnames) |
Constrain what the agent can do with PreToolUse hooks.
| Example | Description |
|---|---|
| command-blacklist | Block dangerous shell commands with PreToolUse hooks (blacklist approach with snarky messages) |
| command-whitelist | Only allow approved shell commands with PreToolUse hooks (whitelist approach for strict security) |
| workspace-isolation | Advanced: Enforce directory boundaries with hooks - prevent agents from navigating/writing outside assigned workspace (based on jpshackelford/lxa) |
Examples that use agent hooks, grouped here by hook type. Each is also listed under its primary topic above.
| Example | Hook | Description |
|---|---|---|
| command-blacklist | PreToolUse | Block dangerous shell commands (blacklist approach with snarky messages) |
| command-whitelist | PreToolUse | Only allow approved shell commands (whitelist approach for strict security) |
| workspace-isolation | PreToolUse | Advanced: Enforce directory boundaries — prevent agents from navigating/writing outside assigned workspace |
| gpg-commit-signing | SessionStart | Import a GPG key from a custom secret to sign commits on every conversation |
| finish-callback | Stop | Notify an external URL the moment a conversation finishes (push instead of poll) |
OpenHands has two API versions:
- V0 API (Legacy) - Deprecated since v1.0.0, scheduled for removal April 1, 2026
- V1 API - Current recommended API
These examples aim to support both API versions where possible, with graceful fallback behavior.
Each example has its own README with installation and usage instructions.
Most examples require an OpenHands API key. Set it as an environment variable:
export OH_API_KEY="your-api-key"Or pass it via command-line argument (see individual example documentation).
- OpenHands Documentation
- OpenHands API Reference
- oh-websocket-example - V0 WebSocket API example
MIT License - see LICENSE for details.