Skip to main content

Open-source Agent SDK for Python. Runs the full agent loop in-process — no local CLI required.

Project description

Open Agent SDK (Python)

PyPI version Python License: MIT

Open-source Agent SDK that runs the full agent loop in-process — no subprocess or CLI required. Deploy anywhere: cloud, serverless, Docker, CI/CD.

Also available in TypeScript: open-agent-sdk-typescript and Go: open-agent-sdk-go

Get started

pip install open-agent-sdk

Set your API key:

export CODEANY_API_KEY=your-api-key

Third-party providers (e.g. OpenRouter) are supported via CODEANY_BASE_URL:

export CODEANY_BASE_URL=https://openrouter.ai/api
export CODEANY_API_KEY=sk-or-...
export CODEANY_MODEL=anthropic/claude-sonnet-4

Quick start

Streaming query

import asyncio
from open_agent_sdk import create_agent

async def main():
    agent = create_agent(
        allowed_tools=["Read", "Glob"],
        permission_mode="bypassPermissions",
    )
    async for event in agent.query("Read pyproject.toml and tell me the project name."):
        if event.get("type") == "assistant":
            for block in event["message"]["content"]:
                if "text" in block:
                    print(block["text"])

asyncio.run(main())

Simple blocking prompt

import asyncio
from open_agent_sdk import query

async def main():
    result = await query("What files are in this project?")
    print(result.text)
    print(f"Turns: {result.num_turns}, Tokens: {result.usage.input_tokens + result.usage.output_tokens}")

asyncio.run(main())

Multi-turn conversation

import asyncio
from open_agent_sdk import create_agent

async def main():
    agent = create_agent(max_turns=5)

    r1 = await agent.prompt('Create a file /tmp/hello.txt with "Hello World"')
    print(r1.text)

    r2 = await agent.prompt("Read back the file you just created")
    print(r2.text)

    print(f"Session messages: {len(agent.get_messages())}")

asyncio.run(main())

Custom tools

import asyncio
from open_agent_sdk import create_agent, get_all_base_tools
from open_agent_sdk.tools.types import define_tool

async def calc(input_data, ctx):
    expr = input_data["expression"]
    result = eval(expr)  # use ast.literal_eval in production
    return f"{expr} = {result}"

calculator = define_tool(
    name="Calculator",
    description="Evaluate a math expression",
    input_schema={
        "properties": {"expression": {"type": "string"}},
        "required": ["expression"],
    },
    is_read_only=True,
    call=calc,
)

async def main():
    agent = create_agent(tools=[*get_all_base_tools(), calculator])
    r = await agent.prompt("Calculate 2**10 * 3")
    print(r.text)

asyncio.run(main())

Custom tools (in-process MCP server)

import asyncio
from open_agent_sdk import create_agent, create_sdk_mcp_server
from open_agent_sdk.tools.types import define_tool

async def get_weather_handler(input_data, ctx):
    city = input_data["city"]
    return f"{city}: 22°C, sunny"

get_weather = define_tool(
    name="get_weather",
    description="Get the temperature for a city",
    input_schema={
        "properties": {"city": {"type": "string", "description": "City name"}},
        "required": ["city"],
    },
    is_read_only=True,
    call=get_weather_handler,
)

async def main():
    server = create_sdk_mcp_server(name="weather", tools=[get_weather])
    agent = create_agent(mcp_servers={"weather": server})
    async for msg in agent.query("What is the weather in Tokyo?"):
        if msg.get("type") == "result":
            print(f"Done: ${msg.get('total_cost_usd', 0):.4f}")

asyncio.run(main())

MCP server integration

import asyncio
from open_agent_sdk import create_agent

async def main():
    agent = create_agent(
        mcp_servers={
            "filesystem": {
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
            },
        },
    )

    result = await agent.prompt("List files in /tmp")
    print(result.text)

asyncio.run(main())

Subagents

import asyncio
from open_agent_sdk import create_agent

async def main():
    agent = create_agent(
        agents={
            "code-reviewer": {
                "description": "Expert code reviewer",
                "prompt": "Analyze code quality. Focus on security and performance.",
                "tools": ["Read", "Glob", "Grep"],
            },
        },
    )
    async for msg in agent.query("Use the code-reviewer agent to review src/main.py"):
        if msg.get("type") == "result":
            print("Done")

asyncio.run(main())

Permissions

import asyncio
from open_agent_sdk import create_agent

async def main():
    # Read-only agent — can only analyze, not modify
    agent = create_agent(
        allowed_tools=["Read", "Glob", "Grep"],
        permission_mode="dontAsk",
    )
    async for _ in agent.query("Review the code in src/ for best practices."):
        pass

asyncio.run(main())

API reference

Top-level functions

Function Description
query(prompt, model=None, **options) One-shot blocking query, returns QueryResult
create_agent(**options) Create a reusable agent with session persistence
define_tool(name, description, input_schema, call) Low-level tool definition helper
get_all_base_tools() Get all 10 built-in tools
create_sdk_mcp_server(name, tools) Bundle tools into an in-process MCP server
list_sessions() List persisted sessions
fork_session(source_session_id) Fork a session for branching

Agent methods

Method Description
agent.query(prompt) Streaming query, returns AsyncGenerator
agent.prompt(text) Blocking query, returns QueryResult
agent.get_messages() Get conversation history
agent.clear() Reset session
agent.set_model(model) Change model mid-session
agent.session_id Get current session ID (property)

Options

Option Type Default Description
model str claude-sonnet-4-6 LLM model ID
api_key str CODEANY_API_KEY API key
base_url str Custom API endpoint
cwd str os.getcwd() Working directory
system_prompt str System prompt override
append_system_prompt str Append to default system prompt
tools list[ToolDefinition] All built-in Available tools
allowed_tools list[str] Tool allow-list
disallowed_tools list[str] Tool deny-list
permission_mode str bypassPermissions default / acceptEdits / dontAsk / bypassPermissions / plan
can_use_tool Callable Custom permission callback
max_turns int 10 Max agentic turns
max_budget_usd float Spending cap
max_tokens int 16384 Max output tokens per turn
thinking ThinkingConfig disabled Extended thinking
mcp_servers dict MCP server connections
agents dict Subagent definitions
resume str Resume session by ID
session_id str auto Explicit session ID
persist_session bool False Persist session to disk
env dict[str, str] Environment variables passed to agent

Environment variables

Variable Description
CODEANY_API_KEY API key (required)
CODEANY_AUTH_TOKEN Alternative auth token
CODEANY_MODEL Default model override
CODEANY_BASE_URL Custom API endpoint

Built-in tools

Tool Description
Bash Execute shell commands
Read Read files with line numbers
Write Create / overwrite files
Edit Precise string replacement in files
Glob Find files by pattern
Grep Search file contents with regex
WebFetch Fetch and parse web content
WebSearch Search the web
Agent Spawn subagents for parallel work
AskUserQuestion Ask the user for input

Architecture

┌──────────────────────────────────────────────────────┐
│                   Your Application                    │
│                                                       │
│   from open_agent_sdk import create_agent             │
└────────────────────────┬─────────────────────────────┘
                         │
              ┌──────────▼──────────┐
              │       Agent         │  Session state, tool pool,
              │  query() / prompt() │  MCP connections
              └──────────┬──────────┘
                         │
              ┌──────────▼──────────┐
              │    QueryEngine      │  Agentic loop:
              │   submit_message()  │  API call → tools → repeat
              └──────────┬──────────┘
                         │
         ┌───────────────┼───────────────┐
         │               │               │
   ┌─────▼─────┐  ┌─────▼─────┐  ┌─────▼─────┐
   │  LLM API  │  │  10 Tools │  │    MCP     │
   │  Client   │  │ Bash,Read │  │  Servers   │
   │ (streaming)│  │ Edit,...  │  │ stdio/SSE/ │
   └───────────┘  └───────────┘  │ HTTP/SDK   │
                                  └───────────┘

Key internals:

Component Description
QueryEngine Core agentic loop with auto-compact, retry, tool orchestration
Auto-compact Summarizes conversation when context window fills up
Micro-compact Truncates oversized tool results
Retry Exponential backoff for rate limits and transient errors
Token estimation Rough token counting for budget and compaction thresholds
Hook system 20 lifecycle events (PreToolUse, PostToolUse, SessionStart, …)
Session storage Persist / resume / fork sessions on disk
Context injection Git status + AGENT.md automatically injected into system prompt

Examples

# File Description
01 examples/01_simple_query.py Streaming query with event loop
02 examples/02_multi_tool.py Multi-tool orchestration
03 examples/03_multi_turn.py Multi-turn session persistence
04 examples/04_prompt_api.py Blocking prompt() API
05 examples/05_custom_system_prompt.py Custom system prompt
06 examples/06_mcp_server.py MCP server integration
07 examples/07_custom_tools.py Custom tools with define_tool()
08 examples/08_query_function.py query() function API
09 examples/09_subagents.py Subagent delegation
10 examples/10_permissions.py Read-only agent with tool restrictions
11 examples/11_custom_mcp_tools.py define_tool() + create_sdk_mcp_server()

Run any example:

python examples/01_simple_query.py

License

MIT

Project details


Download files

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

Source Distribution

open_agent_sdk_py-0.2.0.tar.gz (61.2 kB view details)

Uploaded Source

Built Distribution

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

open_agent_sdk_py-0.2.0-py3-none-any.whl (76.8 kB view details)

Uploaded Python 3

File details

Details for the file open_agent_sdk_py-0.2.0.tar.gz.

File metadata

  • Download URL: open_agent_sdk_py-0.2.0.tar.gz
  • Upload date:
  • Size: 61.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.14

File hashes

Hashes for open_agent_sdk_py-0.2.0.tar.gz
Algorithm Hash digest
SHA256 af0516493c204ad195d72b42ffd78df0352a85fca9355f174c29dba91a3051e4
MD5 2ea609101440cc9fa1634df20acee83d
BLAKE2b-256 fb55ede9add32089a8e22361381c5afc08e3df15ab61cc212e5344934b77a10f

See more details on using hashes here.

File details

Details for the file open_agent_sdk_py-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for open_agent_sdk_py-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a38c5df04c8d2c6c8557d3b2f62134d0d0d9e928b40491f7065c28d5f566a5cf
MD5 115821c02b370d069c95a26cc3d4947a
BLAKE2b-256 e029ebf52caa8f9b7989e84a1ffabcfbbb8945cb639fa0feafb4aa16c7c0f204

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 Pingdom Monitoring Sentry Error logging StatusPage Status page