managed-agent-sdk 0.0.2__tar.gz → 0.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/CHANGELOG.md +75 -0
  2. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/PKG-INFO +65 -21
  3. managed_agent_sdk-0.0.4/README.md +162 -0
  4. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/pyproject.toml +1 -1
  5. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/__init__.py +21 -16
  6. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_generated/__init__.py +3 -0
  7. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_generated/actions.py +11 -41
  8. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_generated/defaults.py +19 -8
  9. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_generated/enums.py +1 -16
  10. managed_agent_sdk-0.0.4/src/managed_agent_sdk/_generated/error_map.py +63 -0
  11. managed_agent_sdk-0.0.4/src/managed_agent_sdk/_generated/rest_routes.py +94 -0
  12. managed_agent_sdk-0.0.4/src/managed_agent_sdk/_generated/sensitive_keys.py +24 -0
  13. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_generated/types.py +1 -1
  14. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/_version.py +1 -1
  15. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/acp/__init__.py +4 -3
  16. managed_agent_sdk-0.0.4/src/managed_agent_sdk/acp/client.py +849 -0
  17. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/acp/compat.py +62 -19
  18. managed_agent_sdk-0.0.4/src/managed_agent_sdk/acp/question.py +238 -0
  19. managed_agent_sdk-0.0.4/src/managed_agent_sdk/acp/transport.py +732 -0
  20. managed_agent_sdk-0.0.4/src/managed_agent_sdk/acp_types.py +244 -0
  21. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/agent.py +91 -173
  22. managed_agent_sdk-0.0.4/src/managed_agent_sdk/auth.py +228 -0
  23. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/capi.py +92 -125
  24. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/catalog.py +40 -138
  25. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/client.py +139 -95
  26. managed_agent_sdk-0.0.4/src/managed_agent_sdk/control_plane.py +123 -0
  27. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/errors.py +55 -52
  28. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/external_agent.py +20 -25
  29. managed_agent_sdk-0.0.4/src/managed_agent_sdk/log_file.py +347 -0
  30. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/manifest.py +6 -8
  31. managed_agent_sdk-0.0.4/src/managed_agent_sdk/openapi.py +557 -0
  32. managed_agent_sdk-0.0.4/src/managed_agent_sdk/opts.py +501 -0
  33. managed_agent_sdk-0.0.4/src/managed_agent_sdk/session.py +716 -0
  34. managed_agent_sdk-0.0.4/src/managed_agent_sdk/telemetry.py +829 -0
  35. managed_agent_sdk-0.0.4/src/managed_agent_sdk/trace_context.py +75 -0
  36. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/version.py +26 -83
  37. managed_agent_sdk-0.0.2/README.md +0 -118
  38. managed_agent_sdk-0.0.2/src/managed_agent_sdk/acp/client.py +0 -691
  39. managed_agent_sdk-0.0.2/src/managed_agent_sdk/acp/transport.py +0 -755
  40. managed_agent_sdk-0.0.2/src/managed_agent_sdk/acp_types.py +0 -93
  41. managed_agent_sdk-0.0.2/src/managed_agent_sdk/auth.py +0 -115
  42. managed_agent_sdk-0.0.2/src/managed_agent_sdk/opts.py +0 -299
  43. managed_agent_sdk-0.0.2/src/managed_agent_sdk/session.py +0 -462
  44. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/.gitignore +0 -0
  45. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/LICENSE +0 -0
  46. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/py.typed +0 -0
  47. {managed_agent_sdk-0.0.2 → managed_agent_sdk-0.0.4}/src/managed_agent_sdk/types.py +0 -0
@@ -6,6 +6,81 @@ managed-agent-sdk(Python)的所有重要更新都会记录在这里。
6
6
 
7
7
  ## [未发布]
8
8
 
9
+ ## [0.0.4] - 2026-10-19
10
+
11
+ ### ✨ 新增
12
+
13
+ - 新增 `agent.info()`(请求 `DescribeAgent`)与 `version.info()`(请求 `DescribeAgentVersion`),
14
+ 返回最新数据
15
+ - 新增 WorkBuddy OpenAPI 控制面后端,通过 `ClientOpts(openapi=OpenApiOpts(...))` 选择。
16
+ Agent、Version、Session 与目录方法保持一致,出参统一为 PascalCase
17
+ - `OpenApiOpts` 需要 `enterprise_id` 与 `api_key`,显式传入或读
18
+ `WORKBUDDY_ENTERPRISE_ID` / `WORKBUDDY_API_KEY`;缺企业 ID 时构造抛出 `ValidationError`,
19
+ 缺 API key 时抛出 `AuthError`。服务地址固定在 SDK 内,不对外暴露配置
20
+ - OpenAPI 鉴权支持两种凭证,按 `api_key` 前缀自动选择:`ck_` 前缀的开放平台 key 走
21
+ `X-Api-Key` 头;`pt_` 前缀的幻影令牌走 `Authorization: Bearer` 头。可用
22
+ `OpenApiOpts(auth_scheme=...)` 显式指定,覆盖前缀推断
23
+ - `ClientOpts.transport` 同时适用于 OpenAPI 与 ACP;OpenAPI 的 HTTP 连接池通过
24
+ `aclose()` 释放,新建 Agent 默认不下发到 WorkBuddy 客户端
25
+
26
+ ### 🐛 修复
27
+
28
+ - `session.connect()` 每次建连都请求 `DescribeAgentSession` 获取当前接入点,服务端更换接入点后
29
+ 重新建连不再使用旧地址
30
+
31
+ ## [0.0.3] - 2026-10-09
32
+
33
+ ### 🔒 安全
34
+
35
+ - 不再泄漏 SecretId 与请求签名 —— 官方 SDK 会在 `DEBUG` 级别把完整
36
+ `Authorization` 头打进日志,现已将其 logger(`tencentcloud_sdk_common`)
37
+ 钉在 `WARNING`。确需查看原始请求时,显式对该 logger 设 `DEBUG` 即可
38
+
39
+ ### ⚠️ 不兼容变更
40
+
41
+ - 日志配置合并为 `LoggerOpts(enable, level, sink, file)`,删除
42
+ `ClientOpts` 上原有的 `log_level` 字段,`logger` 的类型由 `Logger` 改为 `LoggerOpts`。原写法
43
+ `ClientOpts(logger=..., log_level="debug")` 改为
44
+ `ClientOpts(logger=LoggerOpts(level="debug"))`
45
+ - 控制台日志**默认开启**(`warn` 级别),原先默认静默。用
46
+ `LoggerOpts(enable=False)` 关闭;关闭后即使宿主配置了 root logger 也不输出
47
+
48
+ ### ✨ 新增
49
+
50
+ - `prompt()` 返回值新增 `refusal`,携带服务端给出的结构化拒绝原因;
51
+ 同时导出 `RefusalReason` 类型
52
+ - `prompt()` 返回值新增 `trace_id`(本轮 W3C trace id)与 `usage`(本轮
53
+ token 消耗);入参新增 `trace_id`,不传时自动生成,每轮通过
54
+ `traceparent` 请求头传给服务端。导出 `UsageInfo` 类型
55
+ - 文件日志:配置 `LoggerOpts(file=LogFileOpts())` 后写入
56
+ `.wma-log/sdk-debug.log`,与控制台分别设置级别;凭据自动脱敏,按大小
57
+ 轮转、按天清理
58
+ - 接入伽利略上报:记录对话轮次的开始、结束、失败等事件,默认开启,可用
59
+ `TelemetryOpts(enabled=False)` 关闭。`aclose()` 会等待上报发送完成
60
+
61
+ ### 🐛 修复
62
+
63
+ - 收到 401 时作废 token 缓存,不再反复用同一张已失效的票重试
64
+ - `invalidate()` 补上世代守卫:换票在途时作废,其结果不再写回缓存
65
+
66
+ ### ✨ 优化
67
+
68
+ - 补齐运行期日志:ACP 数据面(建连、重连、心跳、SSE)与 OneID 换票层
69
+ 此前均无日志
70
+ - 数据面日志改走 `ClientOpts.logger`,`log_level` 对其生效;传了 `logger`
71
+ 未指定级别时按 `"warn"` 兜底
72
+ - 控制面日志带上 TraceId,贯穿请求 / 响应 / 错误三条日志,并写入
73
+ `X-TC-TraceId` 请求头
74
+ - 日志降噪:连接 ID 截断显示,不再逐次记录 token 缓存命中
75
+ - 更正 `aclose()` 的文档说明 —— 它当前是空实现,不调用不会漏资源
76
+
77
+ ### 📖 文档
78
+
79
+ - 快速开始简化为 3 步,去掉多余的 `versions.create()`
80
+ - 新增「回复文本怎么拿」「版本要不要自己建」两节
81
+
82
+ ## [0.0.2] - 2026-09-22
83
+
9
84
  ### ✨ 优化
10
85
 
11
86
  - 优化部分功能
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: managed-agent-sdk
3
- Version: 0.0.2
4
- Summary: Managed Agent SDK (Python) — 控制面走腾讯云 API,数据面走 ACP
3
+ Version: 0.0.4
4
+ Summary: Managed Agent SDK (Python) — 控制面支持腾讯云 API 与 WorkBuddy OpenAPI,数据面使用 ACP
5
5
  Project-URL: Homepage, https://cnb.cool/codebuddy/managed-agent-doc/-/tree/main/python
6
6
  Project-URL: Documentation, https://cnb.cool/codebuddy/managed-agent-doc/-/blob/main/python/api.md
7
7
  Project-URL: Repository, https://cnb.cool/codebuddy/managed-agent-doc
@@ -40,7 +40,7 @@ Description-Content-Type: text/markdown
40
40
 
41
41
  腾讯云 **WorkBuddy 企业版 Managed Agent** 的 Python SDK。
42
42
 
43
- 控制面走腾讯云 API(TC3 签名),数据面走 ACP 协议,两段凭证由 SDK 内部缝合。
43
+ 控制面支持腾讯云 API(TC3 签名)与 WorkBuddy OpenAPI(OAuth2),数据面使用 ACP 协议;SDK 自动获取并缓存数据面凭证。
44
44
 
45
45
  ```bash
46
46
  pip install managed-agent-sdk
@@ -57,7 +57,39 @@ export TENCENTCLOUD_SECRET_ID=你的SecretId
57
57
  export TENCENTCLOUD_SECRET_KEY=你的SecretKey
58
58
  ```
59
59
 
60
- 只支持长期密钥,不支持 STS 临时密钥。数据面(ACP)的凭证由 SDK 用这套密钥自动换取并缓存,无需单独配置。
60
+ 腾讯云 API 支持长期密钥。数据面(ACP)的凭证由 SDK 通过控制面自动换取并缓存,无需单独配置。
61
+
62
+ ### WorkBuddy OpenAPI
63
+
64
+ 配置应用凭证(API key 与企业 ID):
65
+
66
+ ```bash
67
+ export WORKBUDDY_ENTERPRISE_ID=你的企业ID
68
+ export WORKBUDDY_API_KEY=你的APIKey
69
+ ```
70
+
71
+ 传入 `ClientOpts(openapi=OpenApiOpts())` 选择 OpenAPI:
72
+
73
+ ```python
74
+ import asyncio
75
+
76
+ from managed_agent_sdk import ClientOpts, ManagedAgentClient, OpenApiOpts
77
+
78
+
79
+ async def main() -> None:
80
+ async with ManagedAgentClient(ClientOpts(openapi=OpenApiOpts())) as client:
81
+ print((await client.models.list()).items)
82
+
83
+
84
+ asyncio.run(main())
85
+ ```
86
+
87
+ `OpenApiOpts` 的字段均可显式传入;省略时读取对应环境变量。服务地址固定在 SDK 内,
88
+ 不支持配置;每个控制面请求带 `X-Api-Key` 头,缺企业 ID 或 API key 时构造抛出异常。
89
+
90
+ 领域方法及 PascalCase 出参与腾讯云 API 相同;新建 Agent 默认不下发到 WorkBuddy 客户端。
91
+
92
+ 传入 `openapi` 后,`credentials`、`region`、`endpoint`、`api_version`、`language` 不参与控制面请求;同时传入 `proxy` 会抛出 `ValidationError`。`transport` 可配置 OpenAPI 与 ACP 的 HTTP 传输层。
61
93
 
62
94
  ## 快速开始
63
95
 
@@ -67,15 +99,15 @@ import asyncio
67
99
  from managed_agent_sdk import (
68
100
  CreateAgentOpts,
69
101
  CreateSessionOpts,
70
- CreateVersionOpts,
71
102
  ManagedAgentClient,
72
103
  ManifestBuilder,
104
+ PromptOpts,
73
105
  )
74
106
 
75
107
 
76
108
  async def main() -> None:
77
109
  async with ManagedAgentClient() as client:
78
- # 创建 Agent
110
+ # 1. 创建 Agent —— 服务端顺带建好承载 manifest 的 default 版本
79
111
  agent = await client.agents.create(
80
112
  CreateAgentOpts(
81
113
  agent_name="日志分析助手",
@@ -84,21 +116,17 @@ async def main() -> None:
84
116
  )
85
117
  )
86
118
 
87
- # 创建版本(manifest 服务端必填)
88
- version = await agent.versions.create(
89
- CreateVersionOpts(
90
- manifest=ManifestBuilder().system_prompt("你是日志分析专家").build(),
91
- )
92
- )
119
+ # 2. 创建会话(拉起真实沙箱,不会自动回收 —— 尽量复用)
120
+ session = await agent.sessions.create(CreateSessionOpts())
93
121
 
94
- # 创建会话(拉起真实沙箱,不会自动回收 —— 尽量复用)
95
- session = await agent.sessions.create(
96
- CreateSessionOpts(version_id=version.version_id)
97
- )
122
+ # 3. 对话。回复文本走 on_chunk,见下方说明
123
+ def on_chunk(n) -> None:
124
+ u = n.update
125
+ if u.sessionUpdate == "agent_message_chunk" and u.content.type == "text":
126
+ print(u.content.text, end="", flush=True)
98
127
 
99
- # 对话
100
- res = await session.prompt("分析这份日志")
101
- print(res.stop_reason)
128
+ res = await session.prompt("分析这份日志", PromptOpts(on_chunk=on_chunk))
129
+ print(f"\nstop_reason: {res.stop_reason}")
102
130
 
103
131
  await session.disconnect()
104
132
 
@@ -106,7 +134,23 @@ async def main() -> None:
106
134
  asyncio.run(main())
107
135
  ```
108
136
 
109
- `prompt()` 的返回值只携带 `stop_reason`,回复文本从 `on_chunk` 取 —— 流式内容与终局结果分两条通道,这是 ACP 的协议设计。
137
+ ### 回复文本怎么拿
138
+
139
+ `prompt()` 的返回值只携带 `stop_reason` 与 `refusal`,**不含回复正文** ——
140
+ 流式内容与终局结果分两条通道,这是 ACP 的协议设计。两条路都能拿到正文:
141
+
142
+ - **`on_chunk`**(上面的写法):实时增量,适合边生成边展示
143
+ - **`session.messages()`**:轮次结束后按 `EventType == "ASSISTANT"` 取 `Message["Content"]`,
144
+ 适合只要最终结果、不关心过程
145
+
146
+ ### 版本要不要自己建
147
+
148
+ 入门不需要。`agents.create()` 传了 `manifest` / `model` 时,服务端会建好一个
149
+ `default` 版本承载它们;`sessions.create()` 不传 `version_id` 时按 Agent 的
150
+ routing 配置分流,也会落到它。
151
+
152
+ 要灰度多个配置(A/B、逐步放量)时才用 `agent.versions.create()` 显式建版本,
153
+ 再配合 `agent.update_routing()` 分流。
110
154
 
111
155
  ## 配置连接器 / 技能 / 专家
112
156
 
@@ -146,7 +190,7 @@ agent = await client.agents.create(
146
190
 
147
191
  **入参 snake_case,出参 PascalCase。** 出参原样透传云 API 字段名,便于对照官方文档排查。
148
192
 
149
- **不做控制面自动重试。** `Create*` 类接口非幂等且服务端不提供 `ClientToken`,重试 `sessions.create()` 会重复拉起沙箱并产生真实费用。唯一例外是 ACP 断线重连(`Last-Event-ID` 断点续传,不重放 prompt)。
193
+ **控制面重试。** 控制面失败直接抛出异常,不做自动重试。`Create*` 类接口非幂等且服务端不提供 `ClientToken`,重试 `sessions.create()` 会重复拉起沙箱并产生真实费用。ACP 支持断线重连(`Last-Event-ID` 断点续传,不重放 prompt)。
150
194
 
151
195
  **会话即沙箱,且不会自动回收。** `sessions.create()` 每次调用都拉起一个真实沙箱。注意 `disconnect()` **只断 ACP 连接,不释放沙箱** —— 服务端既没有销毁会话的接口,也没有空闲超时回收(`IDLE` 只是「上一轮对话结束」的轮次状态,沙箱照常运行)。要复用会话,别在循环里反复新建。
152
196
 
@@ -0,0 +1,162 @@
1
+ # managed-agent-sdk(Python)
2
+
3
+ 腾讯云 **WorkBuddy 企业版 Managed Agent** 的 Python SDK。
4
+
5
+ 控制面支持腾讯云 API(TC3 签名)与 WorkBuddy OpenAPI(OAuth2),数据面使用 ACP 协议;SDK 自动获取并缓存数据面凭证。
6
+
7
+ ```bash
8
+ pip install managed-agent-sdk
9
+ ```
10
+
11
+ 要求 Python 3.10 ~ 3.14。Node 版见 [`@tencent-ai/managed-agent-sdk`](https://www.npmjs.com/package/@tencent-ai/managed-agent-sdk),两侧 API 语义一致。
12
+
13
+ ## 凭证
14
+
15
+ 从环境变量读取,或在构造时显式传入:
16
+
17
+ ```bash
18
+ export TENCENTCLOUD_SECRET_ID=你的SecretId
19
+ export TENCENTCLOUD_SECRET_KEY=你的SecretKey
20
+ ```
21
+
22
+ 腾讯云 API 支持长期密钥。数据面(ACP)的凭证由 SDK 通过控制面自动换取并缓存,无需单独配置。
23
+
24
+ ### WorkBuddy OpenAPI
25
+
26
+ 配置应用凭证(API key 与企业 ID):
27
+
28
+ ```bash
29
+ export WORKBUDDY_ENTERPRISE_ID=你的企业ID
30
+ export WORKBUDDY_API_KEY=你的APIKey
31
+ ```
32
+
33
+ 传入 `ClientOpts(openapi=OpenApiOpts())` 选择 OpenAPI:
34
+
35
+ ```python
36
+ import asyncio
37
+
38
+ from managed_agent_sdk import ClientOpts, ManagedAgentClient, OpenApiOpts
39
+
40
+
41
+ async def main() -> None:
42
+ async with ManagedAgentClient(ClientOpts(openapi=OpenApiOpts())) as client:
43
+ print((await client.models.list()).items)
44
+
45
+
46
+ asyncio.run(main())
47
+ ```
48
+
49
+ `OpenApiOpts` 的字段均可显式传入;省略时读取对应环境变量。服务地址固定在 SDK 内,
50
+ 不支持配置;每个控制面请求带 `X-Api-Key` 头,缺企业 ID 或 API key 时构造抛出异常。
51
+
52
+ 领域方法及 PascalCase 出参与腾讯云 API 相同;新建 Agent 默认不下发到 WorkBuddy 客户端。
53
+
54
+ 传入 `openapi` 后,`credentials`、`region`、`endpoint`、`api_version`、`language` 不参与控制面请求;同时传入 `proxy` 会抛出 `ValidationError`。`transport` 可配置 OpenAPI 与 ACP 的 HTTP 传输层。
55
+
56
+ ## 快速开始
57
+
58
+ ```python
59
+ import asyncio
60
+
61
+ from managed_agent_sdk import (
62
+ CreateAgentOpts,
63
+ CreateSessionOpts,
64
+ ManagedAgentClient,
65
+ ManifestBuilder,
66
+ PromptOpts,
67
+ )
68
+
69
+
70
+ async def main() -> None:
71
+ async with ManagedAgentClient() as client:
72
+ # 1. 创建 Agent —— 服务端顺带建好承载 manifest 的 default 版本
73
+ agent = await client.agents.create(
74
+ CreateAgentOpts(
75
+ agent_name="日志分析助手",
76
+ model="deepseek-v3",
77
+ manifest=ManifestBuilder().system_prompt("你是日志分析专家").build(),
78
+ )
79
+ )
80
+
81
+ # 2. 创建会话(拉起真实沙箱,不会自动回收 —— 尽量复用)
82
+ session = await agent.sessions.create(CreateSessionOpts())
83
+
84
+ # 3. 对话。回复文本走 on_chunk,见下方说明
85
+ def on_chunk(n) -> None:
86
+ u = n.update
87
+ if u.sessionUpdate == "agent_message_chunk" and u.content.type == "text":
88
+ print(u.content.text, end="", flush=True)
89
+
90
+ res = await session.prompt("分析这份日志", PromptOpts(on_chunk=on_chunk))
91
+ print(f"\nstop_reason: {res.stop_reason}")
92
+
93
+ await session.disconnect()
94
+
95
+
96
+ asyncio.run(main())
97
+ ```
98
+
99
+ ### 回复文本怎么拿
100
+
101
+ `prompt()` 的返回值只携带 `stop_reason` 与 `refusal`,**不含回复正文** ——
102
+ 流式内容与终局结果分两条通道,这是 ACP 的协议设计。两条路都能拿到正文:
103
+
104
+ - **`on_chunk`**(上面的写法):实时增量,适合边生成边展示
105
+ - **`session.messages()`**:轮次结束后按 `EventType == "ASSISTANT"` 取 `Message["Content"]`,
106
+ 适合只要最终结果、不关心过程
107
+
108
+ ### 版本要不要自己建
109
+
110
+ 入门不需要。`agents.create()` 传了 `manifest` / `model` 时,服务端会建好一个
111
+ `default` 版本承载它们;`sessions.create()` 不传 `version_id` 时按 Agent 的
112
+ routing 配置分流,也会落到它。
113
+
114
+ 要灰度多个配置(A/B、逐步放量)时才用 `agent.versions.create()` 显式建版本,
115
+ 再配合 `agent.update_routing()` 分流。
116
+
117
+ ## 配置连接器 / 技能 / 专家
118
+
119
+ 三类资源的**配置入口不统一**,这是最容易配错的地方:
120
+
121
+ | 资源 | 查询 | 配置入口 | 最终落点 |
122
+ | --- | --- | --- | --- |
123
+ | 连接器(MCP) | `client.connectors.list()` | `connector_ids`(Action 入参) | 服务端物化成 manifest 的 `mcp_servers` |
124
+ | 技能 | `client.skills.list()` | `ManifestBuilder.skills()` | manifest 的 `skills` |
125
+ | 专家 | `client.experts.list()` | `ManifestBuilder.experts()` | manifest 的 `experts` |
126
+
127
+ 技能与专家进 manifest,连接器**不进** —— 只把 ID 交给服务端,由它查网关地址后物化。
128
+ 自己往 manifest 里写 `mcp_servers` 会与之重复。
129
+
130
+ ```python
131
+ skills = await client.skills.list("BUILTIN", ListSkillsOpts(limit=50))
132
+ connectors = await client.connectors.list_active()
133
+
134
+ agent = await client.agents.create(
135
+ CreateAgentOpts(
136
+ agent_name="运维助手",
137
+ manifest=(
138
+ ManifestBuilder()
139
+ .system_prompt("你是运维专家")
140
+ .skills([{"type": "builtin", "id": s["SkillId"]} for s in skills.items])
141
+ .build()
142
+ ),
143
+ connector_ids=[c["ConnectorId"] for c in connectors.items], # 独立入参
144
+ )
145
+ )
146
+ ```
147
+
148
+ `connector_ids` 是该版本最终要绑的完整集合,服务端按它做全量覆盖 ——
149
+ 改绑定直接传新集合,解绑从列表里去掉即可,传 `[]` 解绑全部。
150
+
151
+ ## 两条约定
152
+
153
+ **入参 snake_case,出参 PascalCase。** 出参原样透传云 API 字段名,便于对照官方文档排查。
154
+
155
+ **控制面重试。** 控制面失败直接抛出异常,不做自动重试。`Create*` 类接口非幂等且服务端不提供 `ClientToken`,重试 `sessions.create()` 会重复拉起沙箱并产生真实费用。ACP 支持断线重连(`Last-Event-ID` 断点续传,不重放 prompt)。
156
+
157
+ **会话即沙箱,且不会自动回收。** `sessions.create()` 每次调用都拉起一个真实沙箱。注意 `disconnect()` **只断 ACP 连接,不释放沙箱** —— 服务端既没有销毁会话的接口,也没有空闲超时回收(`IDLE` 只是「上一轮对话结束」的轮次状态,沙箱照常运行)。要复用会话,别在循环里反复新建。
158
+
159
+ ## 文档
160
+
161
+ 完整 API 参考、错误码表、已知问题见
162
+ [Managed Agent SDK 文档](https://cnb.cool/codebuddy/managed-agent-doc/-/blob/main/python/README.md)。
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
  [project]
6
6
  name = "managed-agent-sdk"
7
7
  dynamic = ["version"]
8
- description = "Managed Agent SDK (Python) — 控制面走腾讯云 API,数据面走 ACP"
8
+ description = "Managed Agent SDK (Python) — 控制面支持腾讯云 API 与 WorkBuddy OpenAPI,数据面使用 ACP"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10,<3.15"
11
11
  license = { text = "MIT" }
@@ -49,9 +49,15 @@ from .acp_types import (
49
49
  EmbeddedResource,
50
50
  ImageContent,
51
51
  PromptResponse,
52
+ QuestionAnswer,
53
+ QuestionItem,
54
+ QuestionOption,
55
+ QuestionRequest,
56
+ RefusalReason,
52
57
  ResourceLink,
53
58
  SessionNotification,
54
59
  TextContent,
60
+ UsageInfo,
55
61
  )
56
62
  from .agent import (
57
63
  Agent,
@@ -70,8 +76,6 @@ from .catalog import (
70
76
  ConnectorRegistry,
71
77
  ExpertPage,
72
78
  ExpertRegistry,
73
- ListConnectorsOpts,
74
- ListExpertsOpts,
75
79
  ListSkillsOpts,
76
80
  SkillPage,
77
81
  SkillRegistry,
@@ -122,23 +126,21 @@ from .opts import (
122
126
  DEFAULT_REGION,
123
127
  DEFAULT_TIMEOUT_MS,
124
128
  MAX_PAGE_LIMIT,
125
- AgentListOpts,
126
- AgentSortBy,
127
129
  ClientOpts,
128
130
  ConnectOpts,
129
131
  Credentials,
130
- Filter,
131
132
  Language,
133
+ LogFileOpts,
132
134
  Logger,
135
+ LoggerOpts,
133
136
  LogLevel,
137
+ OpenApiOpts,
134
138
  Page,
135
139
  PageOpts,
136
140
  RequestOpts,
137
- SessionListOpts,
138
- SessionSortBy,
139
- SortDirection,
140
141
  )
141
142
  from .session import MessageListOpts, PromptOpts, Session
143
+ from .telemetry import TelemetryOpts, TurnTelemetryOpts
142
144
  from .types import (
143
145
  A2AConfig,
144
146
  A2ASkillItem,
@@ -194,6 +196,11 @@ __all__ = [
194
196
  "ResourceLink",
195
197
  "EmbeddedResource",
196
198
  "PromptResponse",
199
+ "QuestionAnswer",
200
+ "QuestionItem",
201
+ "QuestionOption",
202
+ "QuestionRequest",
203
+ "RefusalReason",
197
204
  "SessionNotification",
198
205
  "AcpConnectionState",
199
206
  "NotificationListener",
@@ -226,10 +233,10 @@ __all__ = [
226
233
  "UpdateVersionOpts",
227
234
  "MessageListOpts",
228
235
  "PromptOpts",
236
+ "TelemetryOpts",
237
+ "TurnTelemetryOpts",
229
238
  "A2ASkill",
230
- "ListConnectorsOpts",
231
239
  "ListSkillsOpts",
232
- "ListExpertsOpts",
233
240
  "ManifestSkillRef",
234
241
  "ManifestExpertRef",
235
242
  "ManifestRefType",
@@ -275,9 +282,6 @@ __all__ = [
275
282
  "MessageEventType",
276
283
  "ToolCallStatus",
277
284
  "CapiErrorType",
278
- "AgentSortBy",
279
- "SessionSortBy",
280
- "SortDirection",
281
285
  "SkillSource",
282
286
  "ExpertSource",
283
287
  "PublishStatus",
@@ -290,14 +294,15 @@ __all__ = [
290
294
  "ClientOpts",
291
295
  "RequestOpts",
292
296
  "PageOpts",
293
- "AgentListOpts",
294
- "SessionListOpts",
295
297
  "Page",
296
- "Filter",
297
298
  "Credentials",
299
+ "OpenApiOpts",
298
300
  "Logger",
301
+ "LogFileOpts",
302
+ "LoggerOpts",
299
303
  "LogLevel",
300
304
  "Language",
305
+ "UsageInfo",
301
306
  # ── 错误 ────────────────────────────────
302
307
  "CloudAgentError",
303
308
  "ValidationError",
@@ -5,4 +5,7 @@ from __future__ import annotations
5
5
  from .actions import * # noqa: F403
6
6
  from .defaults import * # noqa: F403
7
7
  from .enums import * # noqa: F403
8
+ from .error_map import * # noqa: F403
9
+ from .rest_routes import * # noqa: F403
10
+ from .sensitive_keys import * # noqa: F403
8
11
  from .types import * # noqa: F403
@@ -46,19 +46,11 @@ DESCRIBE_AGENT_LIST: Final[ActionMapping] = {
46
46
  "request": [
47
47
  ("offset", "Offset"),
48
48
  ("limit", "Limit"),
49
- ("filters", "Filters"),
50
- ("sort_by", "SortBy"),
51
- ("sort_direction", "SortDirection"),
52
49
  ],
53
50
  "response": {"kind": "page", "items": "AgentSet", "totalCount": "TotalCount"},
54
51
  "pagination": {"style": "offset_limit", "max": 100},
55
52
  }
56
- """Agent 列表。可用 filter 名:AgentName(子串匹配)/ Model(精确匹配,
57
-
58
- 命中「最新版本引用该模型」的 Agent);多个 filter 之间是 AND。
59
-
60
- filters 的 name 拼错时服务端静默返回空列表而非报错。
61
- """
53
+ """Agent 列表。"""
62
54
 
63
55
  MODIFY_AGENT: Final[ActionMapping] = {
64
56
  "action": "ModifyAgent",
@@ -162,17 +154,13 @@ DESCRIBE_AGENT_VERSION_LIST: Final[ActionMapping] = {
162
154
  ("agent_id", "AgentId"),
163
155
  ("offset", "Offset"),
164
156
  ("limit", "Limit"),
165
- ("filters", "Filters"),
166
157
  ],
167
158
  "response": {"kind": "page", "items": "AgentVersionSet", "totalCount": "TotalCount"},
168
159
  "pagination": {"style": "offset_limit", "max": 100},
169
160
  }
170
- """版本列表。可用 filter 名 VersionType,取值是大写枚举 DEFAULT / TEST / PROD
171
-
172
- —— 服务端只认大写,传小写会被当作「不过滤」而返回全部。
161
+ """版本列表。集合字段名是 AgentVersionSet(原 VersionSet 与 Skill 版本接口
173
162
 
174
- 集合字段名是 AgentVersionSet(原 VersionSet 与 Skill 版本接口同名但元素
175
- 类型不同,服务端已改名)。
163
+ 同名但元素类型不同,服务端已改名)。
176
164
  """
177
165
 
178
166
  MODIFY_AGENT_VERSION: Final[ActionMapping] = {
@@ -213,7 +201,7 @@ CREATE_AGENT_SESSION: Final[ActionMapping] = {
213
201
  只断 ACP 连接。循环建会话会持续堆积资源 —— 应复用同一会话,配置变更走
214
202
  MigrateAgentSession。
215
203
 
216
- 出参是窄响应,不含 AgentId / VersionId,SDK 用已知值补齐。
204
+ 出参是窄响应,不含 AgentId / VersionId。
217
205
  """
218
206
 
219
207
  DESCRIBE_AGENT_SESSION: Final[ActionMapping] = {
@@ -224,10 +212,7 @@ DESCRIBE_AGENT_SESSION: Final[ActionMapping] = {
224
212
  ],
225
213
  "response": {"kind": "object"},
226
214
  }
227
- """会话详情。出参含 EndpointSet,返回的会话可直接用于数据面。
228
-
229
- 不同 Action 返回字段集不同,SDK 用合并而非覆盖更新快照,避免窄响应清空已知值。
230
- """
215
+ """会话详情。出参含 EndpointSet,SDK 每次建立 ACP 连接时都调用它获取当前接入点。"""
231
216
 
232
217
  DESCRIBE_AGENT_SESSION_LIST: Final[ActionMapping] = {
233
218
  "action": "DescribeAgentSessionList",
@@ -236,15 +221,13 @@ DESCRIBE_AGENT_SESSION_LIST: Final[ActionMapping] = {
236
221
  ("offset", "Offset"),
237
222
  ("limit", "Limit"),
238
223
  ("filters", "Filters"),
239
- ("sort_by", "SortBy"),
240
- ("sort_direction", "SortDirection"),
241
224
  ],
242
225
  "response": {"kind": "page", "items": "SessionSet", "totalCount": "TotalCount"},
243
226
  "pagination": {"style": "offset_limit", "max": 100},
244
227
  }
245
- """会话列表(服务端为租户级)。可用 filter 名:SessionId / Status /
228
+ """会话列表(服务端为租户级)。Filters 不对调用方开放,只由 SDK 内部下发:
246
229
 
247
- AgentId / UserId。agent.sessions.list() 会自动注入 AgentId filter 收窄。
230
+ agent.sessions.list() 注入 AgentId filter 收窄到本 Agent。
248
231
  """
249
232
 
250
233
  MIGRATE_AGENT_SESSION: Final[ActionMapping] = {
@@ -262,7 +245,7 @@ MIGRATE_AGENT_SESSION: Final[ActionMapping] = {
262
245
  已建立的 ACP 连接都保持不变,用户无感。
263
246
 
264
247
  服务端入参名是 TargetVersionId,不是 VersionId。
265
- 出参是窄响应、不一定回显版本,但我们明确知道迁到了哪个版本。
248
+ 出参是窄响应、不一定回显版本;确认迁移结果用 DescribeAgentSession。
266
249
  """
267
250
 
268
251
  BIND_EXTERNAL_AGENT: Final[ActionMapping] = {
@@ -339,7 +322,6 @@ DESCRIBE_BUILTIN_MODEL_LIST: Final[ActionMapping] = {
339
322
  "request": [
340
323
  ("offset", "Offset"),
341
324
  ("limit", "Limit"),
342
- ("filters", "Filters"),
343
325
  ],
344
326
  "response": {"kind": "page", "items": "BuiltinModelSet", "totalCount": "TotalCount"},
345
327
  "pagination": {"style": "offset_limit", "max": 100},
@@ -367,6 +349,7 @@ DESCRIBE_MESSAGE_EVENT_LIST: Final[ActionMapping] = {
367
349
  (另有 DescribeSessionMessageList 尚未实现,SDK 不接)。
368
350
 
369
351
  服务端把 AgentId 列为必填,只传 SessionId 会报 InvalidParameter。
352
+ Filters 只由 SDK 内部下发:session.messages() 的 eventTypes 转为 EventType filter。
370
353
  """
371
354
 
372
355
  DESCRIBE_USER_ACCESS_TOKEN: Final[ActionMapping] = {
@@ -408,9 +391,7 @@ DESCRIBE_CONNECTOR_LIST: Final[ActionMapping] = {
408
391
  整除(服务端要求 Offset 落在页边界上,非页边界直接报错),SDK 本地提前
409
392
  拦截,省一次必然失败的往返。
410
393
 
411
- 服务端认可三个 filter 名:Name(子串)/ Status(精确,ACTIVE|DISABLED)/
412
- Source(精确,ENTERPRISE_AGENT|ASSISTANT)。与技能 / 专家不同,
413
- 连接器域对未知 filter 名静默忽略而非报错。
394
+ Filters 只由 SDK 内部下发:connectors.listActive() 注入 Status=ACTIVE。
414
395
  """
415
396
 
416
397
  DESCRIBE_SKILL_LIST: Final[ActionMapping] = {
@@ -418,7 +399,6 @@ DESCRIBE_SKILL_LIST: Final[ActionMapping] = {
418
399
  "domain": "skill",
419
400
  "request": [
420
401
  ("source", "Source"),
421
- ("filters", "Filters"),
422
402
  ("account_id", "AccountId"),
423
403
  ("agent_id", "AgentId"),
424
404
  ("offset", "Offset"),
@@ -429,12 +409,7 @@ DESCRIBE_SKILL_LIST: Final[ActionMapping] = {
429
409
  }
430
410
  """技能列表(租户级)。Source 必填 —— 服务端把它当数据通路判别而非筛选条件。
431
411
 
432
- AUTHORIZED 链路服务端强制只返回已发布且启用的技能;另两条通路默认不过滤。
433
-
434
- 服务端认可四个 filter 名:SkillId(精确多值 OR,最多 100 个)/
435
- Keyword(子串,只取首个值)/ PublishStatus / Status。
436
- 与其他域不同:未知 filter 名直接报错;带 SkillId 时切换为按 ID 批量查询,
437
- offset / limit 被忽略。
412
+ AUTHORIZED 链路服务端强制只返回已发布且启用的技能;另两条通路草稿与停用项都会返回。
438
413
  """
439
414
 
440
415
  DESCRIBE_EXPERT_LIST: Final[ActionMapping] = {
@@ -442,7 +417,6 @@ DESCRIBE_EXPERT_LIST: Final[ActionMapping] = {
442
417
  "domain": "expert",
443
418
  "request": [
444
419
  ("source", "Source"),
445
- ("filters", "Filters"),
446
420
  ("offset", "Offset"),
447
421
  ("limit", "Limit"),
448
422
  ],
@@ -452,10 +426,6 @@ DESCRIBE_EXPERT_LIST: Final[ActionMapping] = {
452
426
  """专家列表(租户级)。Source 必填,且只有 BUILTIN / CUSTOM ——
453
427
 
454
428
  服务端校验白名单不含 AUTHORIZED(与技能不同)。
455
-
456
- 服务端认可三个 filter 名:ExpertId(精确多值 OR,最多 100 个)/
457
- Keyword(子串,只取首个值)/ PublishStatus(精确,**大小写敏感** ——
458
- 技能侧做了大写归一,专家侧没做)。专家不支持 Status filter。
459
429
  """
460
430
 
461
431