Skip to main content
Loss of provenance

A previous release had provenance metadata, but this release does not. View details.

OpenCode Agent SDK for Python

Python SDK for building agents backed by OpenCode. Drop-in replacement for claude_agent_sdk with support for any LLM provider (Anthropic, OpenAI, xAI, etc.).

Installation

pip install opencode-agent-sdk

Prerequisites:

  • Python 3.10+
  • An OpenCode server (opencode serve) or the opencode CLI installed locally

Quick Start

import asyncio
from opencode_agent_sdk import SDKClient, AgentOptions, AssistantMessage, TextBlock

async def main():
    client = SDKClient(options=AgentOptions(
        model="claude-haiku-4-5",
        server_url="http://localhost:54321",
    ))

    await client.connect()
    await client.query("What is 2 + 2?")

    async for message in client.receive_response():
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)

    await client.disconnect()

asyncio.run(main())

Why OpenCode Agent SDK?

  • Drop-in Replacement: Seamlessly switch from claude_agent_sdk by just changing your imports.

  • Open Source & Headless: Take full control of your agent infrastructure. No more proprietary black boxes.

  • Multi-Provider Support: Use any LLM (Anthropic, OpenAI, xAI, Google, Locall) via OpenCode's backend.

  • Native SSE Streaming: Real-time response streaming for a better user experience.

  • Advanced Control: Fine-grained tool permission hooks and MCP server support builtin.

  • HTTP mode — communicates with a running opencode serve instance over REST

  • Subprocess mode — spawns opencode acp locally over stdio JSON-RPC

Start the server, then connect:

docker compose up -d   # starts opencode serve on port 54321
from opencode_agent_sdk import SDKClient, AgentOptions

client = SDKClient(options=AgentOptions(
    model="claude-haiku-4-5",
    server_url="http://localhost:54321",
    system_prompt="You are a helpful assistant",
))

await client.connect()
await client.query("Hello!")

async for msg in client.receive_response():
    print(msg)

await client.disconnect()

Subprocess Mode

When server_url is not set, the SDK spawns opencode acp as a child process:

client = SDKClient(options=AgentOptions(
    cwd="/path/to/project",
    model="claude-haiku-4-5",
))

Resuming Sessions

options = AgentOptions(
    resume="session-id-from-previous-run",
    server_url="http://localhost:54321",
)

AgentOptions

Field Type Default Description
cwd str "." Working directory
model str "" Model identifier (e.g. "claude-haiku-4-5")
provider_id str "anthropic" Provider identifier
system_prompt str "" System prompt for the LLM
server_url str "" OpenCode server URL; enables HTTP mode when set
mcp_servers dict {} MCP server configurations
allowed_tools list[str] [] Tools the agent is allowed to use
permission_mode str "" Permission mode for tool execution
hooks dict {} Hook matchers keyed by event type
max_turns int 100 Maximum conversation turns
resume str | None None Session ID to resume

Custom Tools (MCP Servers)

Define tools as Python functions and expose them as in-process MCP servers:

from opencode_agent_sdk import tool, create_sdk_mcp_server, SDKClient, AgentOptions

@tool("greet", "Greet a user", {"type": "object", "properties": {"name": {"type": "string"}}})
def greet_user(args):
    return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}

server = create_sdk_mcp_server("my-tools", tools=[greet_user])

client = SDKClient(options=AgentOptions(
    mcp_servers={"my-tools": server},
    allowed_tools=["mcp__my-tools__greet"],
    server_url="http://localhost:54321",
))

You can mix in-process SDK servers with external MCP servers:

options = AgentOptions(
    mcp_servers={
        "internal": sdk_server,          # In-process SDK server
        "external": {                    # External stdio server
            "command": "external-server",
            "args": ["--port", "8080"],
        },
    }
)

Hooks

Hooks let you intercept and control tool execution. They run deterministically at specific points in the agent loop.

from opencode_agent_sdk import SDKClient, AgentOptions, HookMatcher

async def check_bash_command(input_data, tool_use_id, context):
    tool_input = input_data["tool_input"]
    command = tool_input.get("command", "")

    if "rm -rf" in command:
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Destructive command blocked",
            }
        }
    return {}

options = AgentOptions(
    allowed_tools=["Bash"],
    hooks={
        "PreToolUse": [
            HookMatcher(matcher="Bash", hooks=[check_bash_command]),
        ],
    },
    server_url="http://localhost:54321",
)

client = SDKClient(options=options)
await client.connect()
await client.query("Run: echo hello")

async for msg in client.receive_response():
    print(msg)

await client.disconnect()

Hook event types: "PreToolUse", "Stop"

Types

See src/opencode_agent_sdk/types.py for complete type definitions:

  • AssistantMessage — LLM response containing TextBlock and/or ToolUseBlock
  • ResultMessage — Final message with usage stats, cost, and session info
  • SystemMessage — Internal events (init, tool results, thoughts)
  • TextBlock — Text content from the LLM
  • ToolUseBlock — Tool invocation with name and input
  • HookMatcher — Matches tool names to hook functions

Error Handling

from opencode_agent_sdk._errors import ProcessError

try:
    await client.connect()
except ProcessError as e:
    print(f"Failed with exit code: {e.exit_code}")

Migrating from claude_agent_sdk

This SDK mirrors the claude_agent_sdk API. Migration requires renaming imports:

# Before (claude_agent_sdk)
from claude_agent_sdk import (
    ClaudeAgentOptions, ClaudeSDKClient, AssistantMessage,
    ResultMessage, SystemMessage, TextBlock, ToolUseBlock, HookMatcher,
)
from claude_agent_sdk._errors import ProcessError

# After (opencode_agent_sdk)
from opencode_agent_sdk import (
    AgentOptions, SDKClient, AssistantMessage,
    ResultMessage, SystemMessage, TextBlock, ToolUseBlock, HookMatcher,
)
from opencode_agent_sdk._errors import ProcessError

All method calls, message types, hooks, and tool decorators stay the same. Only the class names change:

claude_agent_sdk opencode_agent_sdk
ClaudeSDKClient SDKClient
ClaudeAgentOptions AgentOptions

Demo: End-to-End Walkthrough

A full working demo that connects to opencode serve, sends a prompt to clone a GitHub repo, and streams the LLM response back through the SDK.

1. Configure API keys

Create a .env file in the project root with your provider key:

ANTHROPIC_API_KEY=sk-ant-...

2. Start the server

docker compose up -d opencode

This builds and starts the opencode serve container on port 54321.

3. Install dependencies

uv sync

4. Run the E2E demo

uv run python scripts/e2e_test.py

Expected output

============================================================
E2E Test: Clone repo & explain project
============================================================
Server: http://127.0.0.1:54321

[*] Connecting ...
[*] Connected.

[>] Prompt:
Clone the repo https://github.com/dingkwang/opencode-agent-sdk-python and then
explain what the project does. Give a concise summary of its purpose,
architecture, and key components.

------------------------------------------------------------

  [system:init]
  [system:step_start]

  [assistant]
  ## opencode-agent-sdk-python
  ### Purpose
  An open-source Python SDK that serves as a drop-in replacement for Anthropic's
  proprietary `claude_agent_sdk`. It delegates all LLM work to OpenCode — an
  open-source headless server that supports any provider ...
  ...

============================================================
  [result] session  = ses_...
           cost     = $0.024723
           turns    = 1
           is_error = False
============================================================

[*] Message counts: {'system': 2, 'assistant': 1, 'result': 1}
[*] E2E test complete.

What's happening

  1. SDKClient creates an HTTP session against opencode serve
  2. query() sends the user prompt via POST /session/{id}/message
  3. receive_response() yields typed messages: SystemMessage (init, step events), AssistantMessage (LLM text/tool calls), and ResultMessage (cost, session ID, turn count)
  4. disconnect() cleans up the session

Customizing the demo

Set a custom server URL via environment variable:

OPENCODE_SERVER_URL=http://your-host:54321 uv run python scripts/e2e_test.py

Running with Docker

# Start opencode serve
docker compose up -d

# Run the integration test
docker compose run --rm test

The Docker setup uses opencode-ai v1.2.6 and exposes the REST API on port 54321. Pass provider API keys via .env (e.g. ANTHROPIC_API_KEY).

Development

# Install dependencies
uv sync

# Run tests
uv run pytest

# Run demo against a running opencode serve
uv run python scripts/opencode_ai_demo.py

# Interactive multi-turn chat
uv run python scripts/chat.py

License

MIT

Metadata

Release files for opencode-agent-sdk 0.4.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Loss of provenance

These files do not have provenance metadata, despite files in a prior release including this data.

We recommend further investigation before installing these files. View details.

Source distribution (sdist)

Source distribution for opencode-agent-sdk 0.4.12
File Size Uploaded Provenance
opencode_agent_sdk-0.4.12.tar.gz 26.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for opencode-agent-sdk 0.4.12
File Interpreter ABI Platform
opencode_agent_sdk-0.4.12-py3-none-any.whl Python 3 none any Details

Total release size: 50.9 kB

Release files / opencode_agent_sdk-0.4.12.tar.gz

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL opencode_agent_sdk-0.4.12.tar.gz
Size 26.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6cfde2b8d76648056a734067f43034f75c6bdecb29ce2abdf09f050b255baf9a
BLAKE2b-256 checksum
How to use checksums
0af271cfe2afa2ce8e90b0a55eeb227ab810395f6e838ded5570c235390ef059
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Release files / opencode_agent_sdk-0.4.12-py3-none-any.whl

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL opencode_agent_sdk-0.4.12-py3-none-any.whl
Size 24.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eda5d9da9fed56dad42944b9f9318e2dfa8db26309af57cd45bc56786be78c26
BLAKE2b-256 checksum
How to use checksums
e3e424d4d3a6d80556a2fa82bdb4fb06b9cdc58a128fbfab9f6a8358184e5b30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Security for opencode-agent-sdk 0.4.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Loss of provenance

A previous release of these files had provenance metadata, but this release does not.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Release comparison

  • Removed 0.4.10 2 files With provenance
  • Added 0.4.12 2 files Without provenance

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page