版本要求:本文档针对 CodeBuddy Agent SDK v0.1.0 及以上版本。
Requirements
依赖 | 版本要求 |
Python | >= 3.10 |
CodeBuddy CLI | 已安装 |
异步运行时:SDK 基于
asyncio,所有 API 都是异步的。Installation
uv add codebuddy-agent-sdk
或使用 pip:
pip install codebuddy-agent-sdk
环境变量
变量名 | 说明 | 必需 |
CODEBUDDY_CODE_PATH | CodeBuddy CLI 可执行文件路径 | 可选 |
如果未设置,SDK 会按以下顺序查找 CLI:
1. 环境变量
CODEBUDDY_CODE_PATH2. SDK 包内置的二进制文件
3. 开发环境 monorepo 路径
认证配置
Functions
query()
主要 API 入口,创建一个查询并返回消息异步迭代器。
async def query(*,prompt: str | AsyncIterable[dict[str, Any]],options: CodeBuddyAgentOptions | None = None,transport: Transport | None = None,) -> AsyncIterator[Message]:
参数:
参数 | 类型 | 说明 |
prompt | str | AsyncIterable[dict] | 查询提示词或用户消息流 |
options | CodeBuddyAgentOptions | 配置选项(可选) |
transport | Transport | 自定义传输层(可选) |
返回值:
AsyncIterator[Message] - 消息异步迭代器示例:
from codebuddy_agent_sdk import query, AssistantMessage, TextBlockasync for message in query(prompt="What is 2+2?"):if isinstance(message, AssistantMessage):for block in message.content:if isinstance(block, TextBlock):print(block.text)
Client Class
CodeBuddySDKClient
用于双向交互式对话的客户端类。支持多轮对话、中断和动态控制。
class CodeBuddySDKClient:def __init__(self,options: CodeBuddyAgentOptions | None = None,transport: Transport | None = None,): ...
方法:
connect()
连接到 CodeBuddy。
async def connect(self,prompt: str | AsyncIterable[dict[str, Any]] | None = None) -> None:
query()
发送用户消息。
async def query(self,prompt: str | AsyncIterable[dict[str, Any]],session_id: str = "default",) -> None:
receive_response()
接收消息直到收到 ResultMessage。
async def receive_response(self) -> AsyncIterator[Message]:
receive_messages()
接收所有消息(不会自动停止)。
async def receive_messages(self) -> AsyncIterator[Message]:
disconnect()
断开连接。
async def disconnect(self) -> None:
上下文管理器支持:
async with CodeBuddySDKClient() as client:await client.query("Hello!")async for msg in client.receive_response():print(msg)
mcp_server_status()
获取 MCP 服务器连接状态。
async def mcp_server_status(self) -> list[McpServerStatus]:
Authentication
SDK 提供独立的认证 API,采用 two-phase 设计:先获取登录 URL,再等待用户完成认证。
authenticate()
启动认证流程,返回
AuthFlow 对象。async def authenticate(*,method_id: str = "external",environment: str | None = None,endpoint: str | None = None,codebuddy_code_path: str | None = None,env: dict[str, str] | None = None,timeout: float = 300.0,) -> AuthFlow:
参数:
参数 | 类型 | 说明 |
method_id | str | 认证方法标识(默认 "external") |
environment | str | None | 预定义环境名 |
endpoint | str | None | 自定义端点 URL(与 environment 互斥) |
codebuddy_code_path | str | None | CLI 可执行文件路径 |
env | dict[str, str] | None | 额外环境变量 |
timeout | float | 用户完成登录的超时时间(秒,默认 300) |
返回值:
AuthFlow — 携带登录 URL 的可等待对象示例:
from codebuddy_agent_sdk import authenticate# Two-phase: 获取 URL → 展示给用户 → 等待完成auth = await authenticate()if auth.auth_url:print(f"请访问: {auth.auth_url}")result = await authprint(f"欢迎, {result.userinfo.user_name}")# 已登录时 auth.auth_url 为空,await 立即返回auth = await authenticate()result = await auth # 已登录则立即返回# 自定义超时auth = await authenticate()result = await auth.wait(timeout=60)
AuthFlow
认证流程对象,由
authenticate() 返回。实现了 __await__ 协议,可直接 await。属性:
属性 | 类型 | 说明 |
auth_url | str | 登录 URL(已登录时为空字符串) |
method_id | str | None | 认证方法标识 |
方法:
wait()
等待用户完成认证。
async def wait(self, timeout: float | None = None) -> AuthenticateResponse:
cancel()
取消认证流程并释放资源。
async def cancel(self) -> None:
logout()
登出并清除缓存的认证令牌。
async def logout(*,environment: str | None = None,endpoint: str | None = None,codebuddy_code_path: str | None = None,env: dict[str, str] | None = None,) -> None:
示例:
from codebuddy_agent_sdk import logoutawait logout()
Unstable API
警告:
以下 API 处于实验阶段,接口可能在未来版本中变更。
interrupt()
发送中断信号。
async def interrupt(self) -> None:
set_permission_mode()
动态修改权限模式。
async def set_permission_mode(self, mode: str) -> None:
set_model()
动态修改模型。
async def set_model(self, model: str | None = None) -> None:
Types
CodeBuddyAgentOptions
完整配置选项:
@dataclassclass CodeBuddyAgentOptions:allowed_tools: list[str] = field(default_factory=list)disallowed_tools: list[str] = field(default_factory=list)system_prompt: str | AppendSystemPrompt | None = Nonemcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)permission_mode: PermissionMode | None = Nonecontinue_conversation: bool = Falseresume: str | None = Nonemax_turns: int | None = Nonemodel: str | None = Nonefallback_model: str | None = Nonecwd: str | Path | None = Nonecodebuddy_code_path: str | Path | None = Noneenv: dict[str, str] = field(default_factory=dict)extra_args: dict[str, str | None] = field(default_factory=dict)stderr: Callable[[str], None] | None = Nonehooks: dict[HookEvent, list[HookMatcher]] | None = Noneinclude_partial_messages: bool = Falsefork_session: bool = Falsepersist_session: bool = Trueagents: dict[str, AgentDefinition] | None = Nonesetting_sources: list[SettingSource] | None = Nonecan_use_tool: CanUseTool | None = None
字段 | 类型 | 说明 |
allowed_tools | list[str] | 自动允许的工具白名单 |
disallowed_tools | list[str] | 禁止使用的工具黑名单 |
system_prompt | str | AppendSystemPrompt | 系统提示词配置 |
mcp_servers | dict[str, McpServerConfig] | MCP 服务器配置 |
permission_mode | PermissionMode | 权限模式 |
continue_conversation | bool | 继续最近的会话 |
resume | str | 要恢复的会话 ID |
max_turns | int | 最大对话轮数 |
model | str | 指定模型 |
fallback_model | str | 备用模型 |
cwd | str | Path | 工作目录 |
codebuddy_code_path | str | Path | CLI 可执行文件路径 |
env | dict[str, str] | 环境变量 |
extra_args | dict[str, str | None] | 额外的 CLI 参数 |
stderr | Callable[[str], None] | stderr 回调 |
hooks | dict[HookEvent, list[HookMatcher]] | Hook 配置 |
include_partial_messages | bool | 包含部分消息 |
fork_session | bool | 分叉会话 |
persist_session | bool | 是否持久化会话记录,默认 True。设为 False 时会话只保留在内存中,不写入本地 transcript,文件检查点也会一并跳过;恢复已有会话仍可用,只是不再写入。需要 CLI >= 2.125.1 |
agents | dict[str, AgentDefinition] | 自定义 Agent |
setting_sources | list[SettingSource] | 设置来源 |
can_use_tool | CanUseTool | 权限回调函数 |
max_thinking_tokens | int | 最大思考 token 数(已废弃,请使用 thinking) |
thinking | ThinkingConfig | 思考模式配置: {"type": "adaptive"}、{"type": "enabled", "budget_tokens": N} 或 {"type": "disabled"} |
effort | 'low' | 'medium' | 'high' | 'xhigh' | 模型推理努力程度 |
PermissionMode
PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]
值 | 说明 |
"default" | 默认模式,所有操作需确认 |
"acceptEdits" | 自动批准文件编辑 |
"plan" | 规划模式,仅允许读取 |
"bypassPermissions" | 跳过所有权限检查 |
PermissionResult
PermissionResult = PermissionResultAllow | PermissionResultDeny@dataclassclass PermissionResultAllow:updated_input: dict[str, Any]behavior: Literal["allow"] = "allow"updated_permissions: list[dict[str, Any]] | None = None@dataclassclass PermissionResultDeny:message: strbehavior: Literal["deny"] = "deny"interrupt: bool = False
CanUseTool
CanUseTool = Callable[[str, dict[str, Any], CanUseToolOptions],Awaitable[PermissionResult],]@dataclassclass CanUseToolOptions:tool_use_id: strsignal: Any | None = Noneagent_id: str | None = Nonesuggestions: list[dict[str, Any]] | None = Noneblocked_path: str | None = Nonedecision_reason: str | None = None
AgentDefinition
@dataclassclass AgentDefinition:description: str # Agent 描述prompt: str # 系统提示词tools: list[str] | None = None # 允许的工具disallowed_tools: list[str] | None = None # 禁止的工具model: str | None = None # 使用的模型
McpServerConfig
class McpStdioServerConfig(TypedDict):type: NotRequired[Literal["stdio"]]command: strargs: NotRequired[list[str]]env: NotRequired[dict[str, str]]McpServerConfig = McpStdioServerConfig
HookEvent
HookEvent = (Literal["PreToolUse"]| Literal["PostToolUse"]| Literal["UserPromptSubmit"]| Literal["Stop"]| Literal["SubagentStop"]| Literal["PreCompact"]| Literal["WorktreeCreate"]| Literal["WorktreeRemove"])
HookMatcher
@dataclassclass HookMatcher:matcher: str | None = None # 匹配模式(支持正则)hooks: list[HookCallback] = field(default_factory=list)timeout: float | None = None # 超时时间(秒)
HookCallback
HookCallback = Callable[[Any, str | None, HookContext],Awaitable[HookJSONOutput],]class HookContext(TypedDict):signal: Any | Noneclass SyncHookJSONOutput(TypedDict):continue_: NotRequired[bool]suppressOutput: NotRequired[bool]stopReason: NotRequired[str]decision: NotRequired[Literal["block"]]reason: NotRequired[str]
SettingSource
控制 SDK 从哪些文件系统位置加载配置。
SettingSource = Literal["user", "project", "local"]
值 | 说明 | 位置 |
"user" | 全局用户设置 | ~/.codebuddy/settings.json |
"project" | 项目共享设置 | .codebuddy/settings.json |
"local" | 项目本地设置 | .codebuddy/settings.local.json |
默认行为:当
setting_sources 未指定时,SDK 不加载任何文件系统配置。这提供了完全干净的运行环境。# 默认:不加载任何配置(干净环境)async for msg in query(prompt="..."):pass# 加载项目配置options = CodeBuddyAgentOptions(setting_sources=["project"])# 加载所有配置(类似 CLI 行为)options = CodeBuddyAgentOptions(setting_sources=["user", "project", "local"])
AppendSystemPrompt
@dataclassclass AppendSystemPrompt:append: str # 追加到默认系统提示词的内容
Message Types
Message
所有消息类型的联合:
Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent
说明:
TaskStartedMessage / TaskNotificationMessage 是 SystemMessage 的子类,已被联合覆盖(isinstance / case SystemMessage() 继续匹配),并单独导出以便在调用处做精确类型判断。SystemMessage
@dataclassclass SystemMessage:subtype: strdata: dict[str, Any]
TaskStartedMessage
后台任务(Bash / PowerShell / Workflow / Agent,
run_in_background: true)进入运行态时发出。是 SystemMessage 的子类,isinstance(msg, SystemMessage) 仍然成立。@dataclassclass TaskStartedMessage(SystemMessage):task_id: strdescription: struuid: strsession_id: strtool_use_id: str | None = Nonetask_type: str | None = None # "Bash" / "PowerShell" / "Workflow" / "Agent"
TaskUsage
task_progress / task_notification 携带的用量统计(对齐 Claude Code 的 TaskUsage)。sub-agent(task_type == "Agent")后台任务有值;后台 shell 任务通常省略。class TaskUsage(TypedDict):total_tokens: inttool_uses: intduration_ms: int
TaskProgressMessage
后台任务进度事件。事件驱动(非定时):每完成一次 tool_use 推一条,携带累计
usage 与最近工具名 last_tool_name。后台 shell 任务不发 progress。@dataclassclass TaskProgressMessage(SystemMessage):task_id: strdescription: strusage: TaskUsageuuid: strsession_id: strtool_use_id: str | None = Nonelast_tool_name: str | None = None
TaskUpdatedMessage
后台任务状态变迁事件。
patch 携带本次变更字段(至少 status,终态补 end_time)。生命周期提示:后台任务的终态有时只来
task_updated(patch.status 为终态)而没有配套的 task_notification。跟踪"活跃任务"的消费方应对二者的终态 status 一视同仁——用 TERMINAL_TASK_STATUSES frozenset 判定({"completed", "failed", "stopped", "killed"})。@dataclassclass TaskUpdatedMessage(SystemMessage):task_id: strpatch: dict[str, Any]status: TaskUpdatedStatus | None = None # pending/running/paused/completed/failed/killedsession_id: str | None = Noneuuid: str | None = None
TaskNotificationMessage
后台任务完成 / 失败 / 被停止时发出。在 stdio
stream-json 长连接模式下,任务若在触发它的那轮 result 之后才完成,该消息会被主动推回同一输出流——消费方需用 receive_messages() 持续读取才能收到(query() 与 receive_response() 在首个 ResultMessage 处停止,会错过后台完成事件)。usage 在 sub-agent 任务上携带,shell 任务省略。query() 已自动禁用后台任务:由于 query() 在首个 ResultMessage 处停止并关闭子进程、无法接收跨轮回推事件,SDK 在 query() 路径下会自动注入 CODEBUDDY_CODE_DISABLE_BACKGROUND_TASKS=1(Bash / PowerShell / Agent 的 run_in_background 被隐藏/降级为前台)。若确需在 query() 下保留后台任务,显式在 options.env 或进程环境里设置该变量(任意值,包括 "0")即可覆盖。CodeBuddySDKClient + receive_messages() 路径不受影响。@dataclassclass TaskNotificationMessage(SystemMessage):task_id: strstatus: Literal["completed", "failed", "stopped"]summary: struuid: strsession_id: strtool_use_id: str | None = Noneoutput_file: str | None = None # 后台任务 stdout 落盘路径(文件模式)output_stderr_file: str | None = Noneusage: TaskUsage | None = None
多个并发后台任务靠
task_id 区分;tool_use_id 关联回模型发起该任务的 tool_use。示例(持续读取以接收整体完成后的通知):from codebuddy_agent_sdk import (CodeBuddySDKClient,CodeBuddyAgentOptions,TaskStartedMessage,TaskNotificationMessage,)async def run_background_tasks():options = CodeBuddyAgentOptions(permission_mode="bypassPermissions")async with CodeBuddySDKClient(options=options) as client:await client.query("并行跑两个后台命令,完成后告诉我结果")# 用 receive_messages 持续读——不要用 receive_response(它在首个 result 处停)async for msg in client.receive_messages():if isinstance(msg, TaskStartedMessage):print(f"[started] {msg.task_id} ({msg.task_type}): {msg.description}")elif isinstance(msg, TaskNotificationMessage):print(f"[done] {msg.task_id} status={msg.status} output={msg.output_file}")# 收齐关心的任务后自行 break
UserMessage
@dataclassclass UserMessage:content: str | list[ContentBlock]uuid: str | None = Noneparent_tool_use_id: str | None = None
AssistantMessage
@dataclassclass AssistantMessage:content: list[ContentBlock]model: strparent_tool_use_id: str | None = Noneerror: str | None = None
ResultMessage
@dataclassclass ResultMessage:subtype: strduration_ms: intduration_api_ms: intis_error: boolnum_turns: intsession_id: strtotal_cost_usd: float | None = Noneusage: dict[str, Any] | None = Noneresult: str | None = Noneerrors: list[str] | None = None# Structured error info aligned with `errors` by index.# - Length matches `errors` when present; entry is None if no structured dimension available.# - Field is absent entirely when every entry would be None (backward compatible).# - Each entry may carry: status (HTTP), code (SDK/business), category (network/quota/auth/model_service/...), details (message).errors_info: list[dict[str, Any] | None] | None = None
StreamEvent
@dataclassclass StreamEvent:uuid: strsession_id: strevent: dict[str, Any]parent_tool_use_id: str | None = None
ContentBlock
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock@dataclassclass TextBlock:text: str@dataclassclass ThinkingBlock:thinking: strsignature: str@dataclassclass ToolUseBlock:id: strname: strinput: dict[str, Any]@dataclassclass ToolResultBlock:tool_use_id: strcontent: str | list[dict[str, Any]] | None = Noneis_error: bool | None = None
Input Types
AskUserQuestionInput
@dataclassclass AskUserQuestionInput:questions: list[AskUserQuestionQuestion]answers: dict[str, str] | None = None
AskUserQuestionQuestion
@dataclassclass AskUserQuestionQuestion:question: str # 完整问题文本(应以 ? 结尾)header: str # 简短标签(最多 12 个字符)options: list[AskUserQuestionOption]multi_select: bool # 是否允许多选
AskUserQuestionOption
@dataclassclass AskUserQuestionOption:label: str # 显示文本(1-5 个单词)description: str # 选项说明
Errors
所有异常都继承自
CodeBuddySDKError。CodeBuddySDKError
class CodeBuddySDKError(Exception):"""Base exception for CodeBuddy SDK errors."""pass
CLIConnectionError
当连接到 CLI 失败或未建立连接时抛出。
class CLIConnectionError(CodeBuddySDKError):pass
CLINotFoundError
当找不到 CLI 可执行文件时抛出。
class CLINotFoundError(CodeBuddySDKError):def __init__(self,message: str,platform: str | None = None,arch: str | None = None,): ...
属性:
属性 | 类型 | 说明 |
platform | str | None | 当前平台 |
arch | str | None | 当前架构 |
CLIJSONDecodeError
当 CLI 输出的 JSON 解码失败时抛出。
class CLIJSONDecodeError(CodeBuddySDKError):pass
ProcessError
当 CLI 进程遇到错误时抛出。
class ProcessError(CodeBuddySDKError):pass
CLIStartupError
当 CLI 进程在启动阶段崩溃或未产生任何输出时抛出。
class CLIStartupError(CodeBuddySDKError):def __init__(self,message: str,stderr: str = "",exit_code: int | None = None,): ...
属性:
属性 | 类型 | 说明 |
stderr | str | CLI 进程的 stderr 输出 |
exit_code | int | None | 进程退出码 |
ExecutionError
当执行失败时抛出(如认证错误、API 错误)。包含 ResultMessage 中的 errors 数组。
class ExecutionError(CodeBuddySDKError):def __init__(self, errors: list[str], subtype: str): ...
属性:
属性 | 类型 | 说明 |
errors | list[str] | 错误消息列表 |
subtype | str | 错误子类型 |
AuthenticationError
当认证失败时抛出。
class AuthenticationError(CodeBuddySDKError):def __init__(self, error_type: str, message: str): ...
属性:
属性 | 类型 | 说明 |
error_type | str | 错误类型(如 "timeout", "auth_failed") |
Auth Types
AuthenticateResponse
@dataclass(slots=True)class AuthenticateResponse:userinfo: UserInfo
UserInfo
@dataclass(slots=True)class UserInfo:user_id: struser_name: str = ""user_nickname: str = ""token: str = ""enterprise_id: str | None = Noneenterprise: str | None = None
McpServerStatus
@dataclass(slots=True)class McpServerStatus:name: strstatus: Literal["connected", "failed", "needs-auth", "pending"]server_info: dict[str, Any] | None = None
相关文档
SDK 概览 - 快速入门和使用示例
TypeScript SDK 参考 - TypeScript 版本 API
Hook 参考指南 - 详细的 Hook 配置说明
MCP 集成 - MCP 服务器配置指南