Skip to main content

Qoder Agent SDK for Python

Python SDK for building applications on top of Qoder Agent.

The SDK starts qodercli 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 qoder-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 qodercli, 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.

To reuse the local qodercli login state:

from qoder_agent_sdk import QoderAgentOptions, qodercli_auth

options = QoderAgentOptions(auth=qodercli_auth())

To authenticate with a personal access token:

Generate a Personal Access Token at qoder.com/account/integrations:

  1. Sign in to your Qoder account.
  2. Open the integrations page.
  3. Create a new PAT, choosing the expiry and scopes you need.
  4. Copy the token immediately. The value cannot be retrieved again after the page is closed.

Use separate tokens for local scripts, CI, and production services when possible, so each environment can be revoked independently. Do not hard-code tokens in source code.

from qoder_agent_sdk import QoderAgentOptions, access_token_from_env

options = QoderAgentOptions(auth=access_token_from_env())

access_token_from_env() reads QODER_PERSONAL_ACCESS_TOKEN by default.

Quick Start

import anyio
from qoder_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 qoder_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 qoder_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 qoder_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 qoder_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 qoder_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(
    "先停止当前方向,优先检查失败的测试。",
    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 qodercli commits them locally. A later process can restore the same session before qodercli starts:

qodercli commit -> SDK append(key, entries) -> external store
external store -> SDK load(key) -> temporary QODER_CONFIG_DIR -> qodercli resume
from qoder_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, or the Cloud Agent runtime. 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 qoder_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 qoder_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 qoder_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("qodercli 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"qodercli exited with code {exc.exit_code}")
except CLIJSONDecodeError as exc:
    print(f"Could not parse qodercli 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

qoder_agent_sdk-1.0.10.tar.gz (406.2 kB view details)

Uploaded Source

Built Distributions

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

qoder_agent_sdk-1.0.10-py3-none-win_amd64.whl (60.2 MB view details)

Uploaded Python 3Windows x86-64

qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_x86_64.whl (49.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_aarch64.whl (48.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_x86_64.whl (50.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_aarch64.whl (50.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_x86_64.whl (42.0 MB view details)

Uploaded Python 3macOS 11.0+ x86-64

qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_arm64.whl (38.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file qoder_agent_sdk-1.0.10.tar.gz.

File metadata

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

File hashes

Hashes for qoder_agent_sdk-1.0.10.tar.gz
Algorithm Hash digest
SHA256 2c29e077fa8e75758d1bc4e014f07027a338c8f63521933455d12c13d0478c25
MD5 910e0acd1fd539b02f65af1661f001f4
BLAKE2b-256 658c95c83f3625103c8504532cab111d121d610773c6a6b21a38aff4b81a2ea6

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ba57c2bd2e76ce46b3395a729793b5306a67d50559558e22333835fa11b95bab
MD5 b3bf947b83d59aabde54e23e11c833b0
BLAKE2b-256 facfebae3ad182b55f8d6c1aa4abeff468f13cf7ea0f725a8bd25dccb75899e1

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c19822bfc85d94c9dcb17187dd6353c89191a4db1852ec4a99a65c6ef398d76b
MD5 eb17d553dbbfcc32edfd5bf95644c570
BLAKE2b-256 4ee3011493b6cf7d38323b13317731d4e5f274db8828a696fa1108dc91b4c673

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0d4f51aa7ae8f37bfe6259c3775b617fdf588afc67db9b196bc667da701de329
MD5 357e8ef8830a38d58bfb3129ca078c03
BLAKE2b-256 e310c9c751a9a0b1a6deeba0650f127df1846ed2c2ad58581e122a250d26fb2a

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 c00086750fac739318698f461e1ad88e417af4c39f37741d0f717473da0b164f
MD5 81c5435d11b6a6755fac3421d85fe9ff
BLAKE2b-256 6dfac5a94bca2fceb7e2ce122cf12807126e020f54062c4c180c70871fdc77cc

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 08ecf4dd1ce9be880a2789e2804cf588dcea250ce6684bc8196c968fd13622a2
MD5 aecfe6154968fc4ebc358e285c833213
BLAKE2b-256 13749b8c6c8848a56de15acc2785b75022832e264c971785f63d96a7269fa52e

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 cde668ab49ef7234d6558afce7c0aa3798f8c1efbe6ae062378ca8945c3061a1
MD5 59b94557c0bca4f9fda7f5fbc441c155
BLAKE2b-256 f3041a1910527da7d387661ba1eb95afb995154df8322df4fd6f287b814e07e2

See more details on using hashes here.

File details

Details for the file qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for qoder_agent_sdk-1.0.10-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8d18e2593a4dad792d4af60f265b37e37f88dc83c7ee8dd7dc3155c6c5387a51
MD5 e60d0ccc413662e7cdd8c6e0722fe3a1
BLAKE2b-256 f218fff90bdcc548f61f091ae03a9d788ca739c62d9fafdf1cbe46771bf30590

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.13

8 files

1.0.12

8 files

1.0.11

8 files

This release

1.0.10 This release

8 files

1.0.9

8 files

1.0.8

8 files

1.0.5

8 files

1.0.2

8 files

1.0.1

8 files

1.0.0

8 files

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