Skip to main content

Qoder Agent SDK for Python

Python SDK for building applications on top of Qoder Agent.

The SDK starts qodercn for you, streams agent messages back to Python, and lets your application configure tools, permissions, working directories, MCP servers, hooks, and interactive sessions.

Installation

pip install qodercn-agent-sdk

Prerequisites:

  • Python 3.10+
  • A Qoder account or another authentication method supported by your host application

CLI Behavior

Published platform wheels include a bundled qodercn, so a separate CLI installation is not required for normal SDK use. If you prefer to use a system-wide CLI or a pinned local build, pass QoderAgentOptions(cli_path=...).

Authentication

Every SDK query needs an explicit authentication option.

Authentication method Identity Use case
Personal Access Token (PAT) A Qoder user Automation that needs the user's permissions and data
Service Account An organization workload Services and jobs that should not depend on a personal account
Local qodercn session The signed-in user Interactive development on a workstation

For a PAT, generate a token at qoder.cn/account/integrations, store it in a secret manager, and expose it through the default environment variable:

export QODERCN_PERSONAL_ACCESS_TOKEN=your-token
from qodercn_agent_sdk import QoderAgentOptions, access_token_from_env

options = QoderAgentOptions(auth=access_token_from_env())

For a Service Account, read the key from your secret manager and pass it directly to the SDK:

from qodercn_agent_sdk import QoderAgentOptions, service_account

# Get the Service Account key from the host's secret manager adapter.
service_account_key = read_secret("qoder-service-account-key")
options = QoderAgentOptions(
    auth=service_account(service_account_key=service_account_key)
)

The SDK and CLI obtain and refresh short-lived Service Account tokens for this authentication method. A host can retain the Service Account key and use service_account(fetch_service_account_token=...) to obtain and refresh short-lived SATs for qodercn. See the host callback example for a complete Token exchange and query. To reuse a signed-in developer workstation, use qodercli_auth(). See the SDK authentication guide for complete setup instructions and security guidance.

Quick Start

import anyio
from qodercn_agent_sdk import QoderAgentOptions, qodercli_auth, query


async def main() -> None:
    options = QoderAgentOptions(auth=qodercli_auth())

    async for message in query(
        prompt="What is 2 + 2?",
        options=options,
    ):
        print(message)


anyio.run(main)

Basic Usage

query() runs a single SDK query and returns an async iterator of response messages.

from qodercn_agent_sdk import (
    AssistantMessage,
    QoderAgentOptions,
    TextBlock,
    qodercli_auth,
    query,
)

options = QoderAgentOptions(
    auth=qodercli_auth(),
    system_prompt="You are a helpful assistant.",
    max_turns=1,
)

async for message in query(prompt="Explain this repository", options=options):
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, TextBlock):
                print(block.text)

Tools and Permissions

Qoder Agent can use tools such as file reads, file edits, shell commands, and MCP tools. allowed_tools is an approval allowlist: listed tools are auto-approved, while unlisted tools continue through permission_mode and can_use_tool for a decision. It does not remove tools from the agent's available toolset. To block tools, use disallowed_tools.

from qodercn_agent_sdk import QoderAgentOptions, qodercli_auth, query

options = QoderAgentOptions(
    auth=qodercli_auth(),
    allowed_tools=["Read", "Edit"],
    disallowed_tools=["Bash"],
    permission_mode="acceptEdits",
)

async for message in query(
    prompt="Update the README introduction.",
    options=options,
):
    print(message)

For application-specific approval flows, provide can_use_tool:

from qodercn_agent_sdk import (
    PermissionResultAllow,
    PermissionResultDeny,
    QoderAgentOptions,
    ToolPermissionContext,
    qodercli_auth,
)


async def can_use_tool(
    tool_name: str,
    tool_input: dict,
    context: ToolPermissionContext,
):
    if tool_name == "Bash":
        return PermissionResultDeny(message="Shell commands are disabled here.")
    return PermissionResultAllow()


options = QoderAgentOptions(
    auth=qodercli_auth(),
    can_use_tool=can_use_tool,
)

Working Directory

Use cwd to run the agent in a specific project directory:

from pathlib import Path

from qodercn_agent_sdk import QoderAgentOptions, qodercli_auth

options = QoderAgentOptions(
    auth=qodercli_auth(),
    cwd=Path("/path/to/project"),
)

Interactive Sessions

Use QoderSDKClient when you need a long-lived, bidirectional session instead of a single query() call.

from qodercn_agent_sdk import QoderAgentOptions, QoderSDKClient, qodercli_auth

options = QoderAgentOptions(auth=qodercli_auth())

async with QoderSDKClient(options=options) as client:
    await client.query("Inspect this project and summarize the main modules.")

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

QoderSDKClient is useful for chat interfaces, follow-up prompts, interrupts, runtime permission changes, MCP server management, and other workflows that need state across multiple turns.

Use message priority to steer a turn that is already running:

await client.query(
    "Stop the current direction and inspect the failing tests first.",
    priority="now",
)

priority="now" stops the current response and handles the message immediately. priority="next" is the default and uses the next suitable point. priority="later" waits until the current response finishes. should_query=False adds the message to the conversation without starting a response by itself; its processing time still follows priority.

Assign a session-unique message_uuid to messages that need tracking or cancellation, and do not reuse UUIDs within a session. await client.interrupt() stops the current response and returns None. await client.cancel_async_message(message_uuid) returns True when the queued message is cancelled and False when it can no longer be cancelled.

External Session Storage

Use session_store when a host needs durable transcripts outside the local machine. The SDK mirrors entries after qodercn commits them locally. A later process can restore the same session before qodercn starts:

qodercn commit -> SDK append(key, entries) -> external store
external store -> SDK load(key) -> temporary QODERCN_CONFIG_DIR -> qodercn resume
from qodercn_agent_sdk import (
    InMemorySessionStore,
    QoderAgentOptions,
    qodercli_auth,
    query,
)

session_store = InMemorySessionStore()

options = QoderAgentOptions(
    auth=qodercli_auth(),
    cwd="/path/to/project",
    session_store=session_store,
)

async for message in query(prompt="Inspect this project.", options=options):
    print(message)

resume_options = QoderAgentOptions(
    auth=qodercli_auth(),
    cwd="/path/to/project",
    resume="11111111-1111-4111-8111-111111111111",
    session_store=session_store,
)

Every store implements async append(key, entries) and load(key). Implement list_sessions(project_key) for continue_conversation=True and session listing, list_subkeys(key) to restore child-agent transcripts, and delete(key) for deletion. Entries are opaque JSON dictionaries and must remain in append order. A child transcript uses an opaque subpath such as subagents/agent-<id>; the key does not include the on-disk .jsonl extension.

When load() returns None or an empty list for an explicit resume, the SDK falls back to the same local session ID. Missing or empty child transcripts do not prevent restoration of the main session, and unsafe subpaths are ignored.

session_store_flush="batched" is the default. "eager" starts each append without waiting for the result boundary. Final append failures are emitted as non-fatal SDKMirrorErrorMessage values. load_timeout_ms defaults to 60,000 ms. Session storage cannot be combined with file checkpointing, a custom transport. It requires the built-in subprocess transport.

The existing local session helpers remain synchronous. External stores use the async helpers list_sessions_from_store, get_session_info_from_store, get_session_messages_from_store, rename_session_via_store, tag_session_via_store, fork_session_via_store, and delete_session_via_store. Local and external child-agent transcripts are available through list_subagents / get_subagent_messages and list_subagents_from_store / get_subagent_messages_from_store. Use import_session_to_store to copy an existing local main transcript, child-agent transcripts, and metadata into a store.

Production stores

The SDK exports the SessionStore protocol but does not ship a production-ready external storage implementation. Implement the protocol against shared storage operated by your application, then validate its append/load ordering, project isolation, subkey handling, and deletion behavior with run_session_store_conformance.

Custom Tools

You can expose Python functions to Qoder Agent as in-process SDK MCP servers. This avoids managing a separate MCP subprocess for simple application-local tools.

from qodercn_agent_sdk import (
    QoderAgentOptions,
    QoderSDKClient,
    create_sdk_mcp_server,
    qodercli_auth,
    tool,
)


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


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

options = QoderAgentOptions(
    auth=qodercli_auth(),
    mcp_servers={"tools": server},
    allowed_tools=["mcp__tools__greet"],
)

async with QoderSDKClient(options=options) as client:
    await client.query("Greet Alice.")
    async for message in client.receive_response():
        print(message)

Hooks

Hooks are deterministic Python callbacks invoked at specific points in the agent loop. They are useful for validation, policy checks, logging, and application-specific feedback.

from qodercn_agent_sdk import HookMatcher, QoderAgentOptions, qodercli_auth


async def block_script(input_data, tool_use_id, context):
    if input_data["tool_name"] != "Bash":
        return {}

    command = input_data["tool_input"].get("command", "")
    if "./deploy.sh" in command:
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Deployment scripts require review.",
            }
        }
    return {}


options = QoderAgentOptions(
    auth=qodercli_auth(),
    hooks={
        "PreToolUse": [
            HookMatcher(matcher="Bash", hooks=[block_script]),
        ],
    },
)

Error Handling

from qodercn_agent_sdk import (
    CLIConnectionError,
    CLIJSONDecodeError,
    CLINotFoundError,
    ProcessError,
    QoderAgentOptions,
    QoderSDKError,
    qodercli_auth,
    query,
)

try:
    async for message in query(
        prompt="Hello Qoder",
        options=QoderAgentOptions(auth=qodercli_auth()),
    ):
        print(message)
except CLINotFoundError:
    print("qodercn was not found. Install a platform wheel or set cli_path.")
except CLIConnectionError as exc:
    print(f"Connection failed: {exc}")
except ProcessError as exc:
    print(f"qodercn exited with code {exc.exit_code}")
except CLIJSONDecodeError as exc:
    print(f"Could not parse qodercn output: {exc}")
except QoderSDKError as exc:
    print(f"SDK error: {exc}")

License and Terms

Copyright (c) 2026 Qoder

Use of this software is governed by the Qoder Product Service Terms:

https://qoder.com/product-service

By installing or using this package, you agree to those terms.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qodercn_agent_sdk-1.0.13.tar.gz (125.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

qodercn_agent_sdk-1.0.13-py3-none-win_amd64.whl (63.3 MB view details)

Uploaded Python 3Windows x86-64

qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_x86_64.whl (49.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_aarch64.whl (49.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_x86_64.whl (50.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_aarch64.whl (50.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_x86_64.whl (43.0 MB view details)

Uploaded Python 3macOS 11.0+ x86-64

qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_arm64.whl (39.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file qodercn_agent_sdk-1.0.13.tar.gz.

File metadata

  • Download URL: qodercn_agent_sdk-1.0.13.tar.gz
  • Upload date:
  • Size: 125.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.14

File hashes

Hashes for qodercn_agent_sdk-1.0.13.tar.gz
Algorithm Hash digest
SHA256 da3d02e704d5d3937baa90be18efdadf0882a1d51da0617d3eff79f0d388a610
MD5 4a90122131f270fc7b68cf3693cbdd2e
BLAKE2b-256 e4b2df3a45c311bb44d8c5a48c0ea63e532fcaeef87a0bee36e5cf1c96a63135

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 3fadc1c7e10c7cf85e43779a49e25063735fcbf5b4b008d0a8dcd06c8127f008
MD5 ecfdf9e4d5a7c94e7882d3d23f812ba6
BLAKE2b-256 812f81390c22ea93ab63c9588be2db97549a425735082c84cb9481686e9d1c7e

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8ef198eeae9f05a2c9c2e8d8b91c598ebf32c81d849babd4defa57a78bd7825a
MD5 82793e5c26a44d8bdfa1fdac7f0f0bd8
BLAKE2b-256 95d0906d09407296bc194beef0b8a3049bb20c2728e971f296e8617096601b58

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 db6a893b1767104f1d47c4c2cb7b9a68d9ff6c72d827f1635d1587dbd9936803
MD5 274f5002045989d55fdc873bd4af575d
BLAKE2b-256 060f8b3974da001b7c2cf0a03024f19373c5500918ebece9249487d1b25b1634

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 cab6e78f8f73170bebcd20244cef3528b2d74d5b5b7edcc4fe3a9bd768e16fa2
MD5 e0f5a28ba5ff2e7a725e7bfb53686dfe
BLAKE2b-256 b6593b8047b12c74c7ca1a13e5b451908c42aef51ed0848f745b0944e718c7ae

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 50feccd0c5d596659e086e9942f41712149666f242b67211f2e0d7f1cb3f1636
MD5 bc5ad10b9df6080f9256a3f0f51d6bad
BLAKE2b-256 fcf082778e4bca26f6d084c64c6c0bb62d09a8a7c587f3bbd6aa6ddf1e151905

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 0ae5dbc306454389a25811a495b3c4fdab34d7e93d340210fb736401adcc9c30
MD5 78473c5c049a9aa151b7aaaf7d7b4f87
BLAKE2b-256 f0719c0f81a6fd8a66162fd18d0db34052fc120ccbb68eb2460f853fb8b9f842

See more details on using hashes here.

File details

Details for the file qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for qodercn_agent_sdk-1.0.13-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 820b8952b23db20e882070818b3e640e540abb51c7e1de4bb6c33e319ce12fdc
MD5 f78b0dc7ce248c4279d1f6a9860efdb5
BLAKE2b-256 fc6234b43ccd708b8939a6041416fb5159b77661c4b523445a78c02c074c09b6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page