A dependency-free Python SDK that drives the APTO Code CLI over stream-json stdio, mirroring the Claude Agent SDK interface.
Project description
apto-code-sdk
A dependency-free Python SDK for the APTO Code CLI (a Claude-Code-style
coding agent). It spawns the apto CLI over stream-json stdio and yields
typed messages, mirroring the interface of the official
Claude Agent SDK
(query() async iterator, an options dataclass, typed message objects).
It exists because the official Claude Agent SDK only locates the claude binary
on PATH and offers no way to point at a forked, locally-served CLI. This SDK
drives any apto-compatible CLI you name, wrapping the same subprocess +
process-group hygiene the APTO research driver uses by hand.
Install
pip install apto-code-sdk
Zero runtime dependencies (Python ≥ 3.10, stdlib only). You must have the apto
CLI installed separately (this SDK drives it; it does not bundle it).
Usage
import asyncio
from apto_code_sdk import query, AptoCodeOptions, AssistantMessage, ResultMessage, TextBlock
async def main():
opts = AptoCodeOptions(
binary="apto", # name on PATH, or an absolute path
permission_mode="bypassPermissions", # non-interactive one-shot runs need this
model="deepseek-v4-flash",
)
async for message in query(prompt="List three prime numbers.", options=opts):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
elif isinstance(message, ResultMessage):
print("turns:", message.num_turns, "cost:", message.total_cost_usd)
asyncio.run(main())
For non-async callers (e.g. a thread-pool driver) there is a blocking collector:
from apto_code_sdk import query_sync
messages = query_sync(prompt="Say hi.", options=opts)
Message types
query() yields, in stream order: SystemMessage (e.g. the init event),
AssistantMessage (with TextBlock / ThinkingBlock / ToolUseBlock content),
UserMessage (tool results fed back), and finally one ResultMessage — whose
arrival ends the iteration. Every message also carries .raw (the original
decoded dict) so a field this version does not model yet is never lost.
The SDK reports what the CLI did; it does not judge whether the run "succeeded" for you — that contract belongs to your caller.
Reasoning models & thinking blocks
Reasoning models (e.g. DeepSeek-V4) emit chain-of-thought that is meant to be
ephemeral — separated from the answer and dropped between turns. When the
deployment separates it (a server reasoning parser plus a router that maps the
model's reasoning_content to a thinking block), the SDK surfaces it as a
ThinkingBlock and the TextBlock / ResultMessage.result stay clean.
If instead you see the CoT inline in a TextBlock (e.g.
…reasoning</think>answer), the chain-of-thought is not being separated
upstream — fix it in the model server / router config, not here. The SDK is a
faithful transport: it reports the content the CLI produced and never strips
text. Leaving leaked CoT inline is harmful to multi-turn agents, since it
pollutes the context fed back into later turns.
AptoCodeOptions
| field | maps to | notes |
|---|---|---|
binary |
argv[0] | "apto" (PATH) or an absolute path |
cwd, env |
subprocess | env is merged over os.environ |
permission_mode |
--permission-mode |
default / acceptEdits / plan / bypassPermissions |
allowed_tools / disallowed_tools |
--allowedTools / --disallowedTools |
comma-joined |
system_prompt / append_system_prompt |
--system-prompt / --append-system-prompt |
|
model |
--model |
|
max_turns |
--max-turns |
|
add_dirs |
--add-dir (repeated) |
|
settings / setting_sources |
--settings / --setting-sources |
|
session_persistence |
--no-session-persistence when False |
default False (one-shot) |
include_partial_messages |
--include-partial-messages |
|
extra_args |
any flag | escape hatch: {"flag": "value" or None} |
Runtime knobs (SDK-side, not CLI flags): step_timeout (wall-clock seconds →
kills the process group on expiry), post_result_grace (kill a process that
lingers past its terminal result — e.g. a sealed container), ready_check
(a callable; return True to terminate early once a required output appears),
log_path (tee the raw stream-json transcript for provenance).
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file apto_code_sdk-0.1.0.tar.gz.
File metadata
- Download URL: apto_code_sdk-0.1.0.tar.gz
- Upload date:
- Size: 11.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcbfea448bdf5e5669e19a29c0ab76dd24accf3eeedfe55230cd925c09239631
|
|
| MD5 |
9a0fef1eb923ce933df2631bca9f2279
|
|
| BLAKE2b-256 |
2c0e867f317c4d3b6cb8ec27c8d15ce51da0097e3b0e2241a6ca8373cab41b84
|
File details
Details for the file apto_code_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: apto_code_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25d79fc531fb697522aa2e37ff8967f544140473d936b0b5c2204958c751a4be
|
|
| MD5 |
cc2b532b4dda8449f1c3d3bad0126152
|
|
| BLAKE2b-256 |
1d0fd62677322f6f08f1ccf9af4e75ae7ce0d1fc9db55ca3bdab355c47224087
|