本篇导读
前十八篇已经覆盖了 SDK 的主要能力和测试体系。
这一篇回答一个更工程化的问题:
如果要给 OpenAI Agents Python SDK 做一个高质量改动,应该怎么组织?这里的“高质量”不只是代码能跑。
它至少包含:
- 变更边界清楚。
- 公共 API 兼容性可解释。
- 导入路径和
__all__没有破坏。 - runtime 行为有测试覆盖。
- docs 和 examples 与行为同步。
- 可选依赖不会污染顶层导入。
- PR 描述能让 reviewer 快速判断风险。
- 验证命令真实跑过,结果可复现。
本篇重点回答十个问题:
- 修改前应该先读哪些仓库规则。
- 为什么公开 API 的参数顺序也是兼容性契约。
- 新增公开 symbol 时为什么要同步
__init__.py和__all__。 - 扩展模块应该放在哪些目录。
- 可选依赖为什么要做 lazy import 或清晰报错。
- 修改 runtime 行为时怎样选择参考文档。
- docs/ref 和用户文档如何同步。
- 如何准备测试和验证记录。
- PR template 需要填写什么。
- 如何写出清晰的变更主题和有序变更内容。
第十九篇关注的源码入口
这一篇主要看这些文件:
AGENTS.md .agents/references/README.md .agents/references/*.md .github/PULL_REQUEST_TEMPLATE/pull_request_template.md src/agents/__init__.py src/agents/extensions docs/ref docs/scripts/generate_ref_files.py tests/test_source_compat_constructors.py tests/extensions最关键的是:
| 文件 | 作用 |
|---|---|
AGENTS.md | 贡献规则、验证规则、兼容性要求 |
.agents/references/README.md | runtime 边界参考地图 |
src/agents/__init__.py | 顶层公开导出契约 |
src/agents/extensions | 扩展能力存放位置 |
docs/ref | API reference 文档入口 |
docs/scripts/generate_ref_files.py | reference stub 生成脚本 |
tests/test_source_compat_constructors.py | 公开构造器兼容性回归测试 |
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md | PR 描述模板 |
先给结论:贡献流程从“边界判断”开始
不要一上来就改代码。
更稳的流程是:
1. 判断变更属于哪个运行边界 2. 阅读对应源码和 maintainer reference 3. 判断是否触及公开 API 或持久化格式 4. 设计兼容策略 5. 写 focused test 6. 实现小步变更 7. 跑相关测试和完整验证栈 8. 同步 docs / examples 9. 准备 PR 描述和 test plan这不是流程主义。
Agent SDK 的很多行为是跨模块联动的。
例如一个新的 tool call item,可能影响:
- model output processing。
- stream events。
- RunState serialization。
- session replay。
- tracing。
- tests。
- docs。
如果只在一个文件里“把功能加上”,很容易漏掉外部行为面。
仓库规则的入口是 AGENTS.md
AGENTS.md是本仓库的贡献入口。
它规定了几类强约束:
- 必须使用哪些验证流程。
- 什么时候需要实现策略判断。
- 公开 API 兼容性要求。
- Git worktree 和 branch 安全。
- docs、security、platform 行为注意事项。
- runtime 模块的架构参考。
其中最容易被低估的是:
公共 API 兼容性SDK 的用户代码可能已经写了:
RunConfig(None,provider,None,handoff_input_filter)即使你更喜欢 keyword arguments,也不能因此破坏已有 positional call。
判断变更类型
修改前先把变更分类。
| 变更类型 | 典型路径 | 风险 |
|---|---|---|
| runtime 行为 | src/agents/run.py、run_internal/ | 高 |
| 公开 API | src/agents/__init__.py、dataclass、constructor | 高 |
| provider 适配 | src/agents/models/、extensions/models/ | 中到高 |
| session / RunState | memory/、run_state.py | 高 |
| sandbox | src/agents/sandbox/ | 高 |
| optional extension | src/agents/extensions/ | 中 |
| docs | docs/、docs/ref | 中 |
| examples | examples/ | 中 |
| tests only | tests/ | 低到中 |
分类的目的不是贴标签。
而是决定:
- 要读哪些 reference。
- 要补哪些测试。
- 是否需要兼容层。
- 是否需要文档或 example。
- PR 描述里要说明哪些风险。
.agents/references是维护者地图
.agents/references/README.md是一张 runtime 边界地图。
例如:
| 要改的内容 | 应读 reference |
|---|---|
| Agent 字段、clone、instructions | agent-definition-and-run-context.md |
| Runner turn loop、handoff、guardrails | runner-lifecycle.md |
| 新增 run item 或 stream event | run-item-lifecycle.md |
| function tool schema | function-and-output-schema.md |
| tool lookup、namespace、approval | tool-identity.md |
| tool 执行、并发、timeout | tool-execution-lifecycle.md |
| session persistence | session-persistence.md |
| RunState 序列化 | runstate-schema.md |
| provider adapter | model-provider-boundaries.md |
| tracing | tracing-lifecycle.md |
| realtime | realtime-session-lifecycle.md |
| voice | voice-pipeline-lifecycle.md |
| sandbox | sandbox-runtime-boundary.md |
这些文件不是用户文档。
它们记录的是维护者需要守住的实现边界。
如果你要改某个 runtime 边界,先读对应 reference,可以少踩很多坑。
公开 API 兼容性:字段顺序也是契约
AGENTS.md明确要求:
Treat the parameter and dataclass field order of exported runtime APIs as a compatibility contract.意思是:
- 公开构造器的参数顺序不能随便改。
- dataclass 字段顺序不能随便插入。
- 新增可选参数时优先追加到末尾。
- 如果无法避免重排,要加兼容层和回归测试。
这对 SDK 很重要。
因为很多用户会写 positional arguments。
例如:
config=RunConfig(None,MultiProvider(),None,keep_handoff_input)如果你在中间插入一个字段,用户代码不会立刻报类型错误。
更糟的是,它可能静默绑定到错误字段。
兼容性测试保护什么
tests/test_source_compat_constructors.py就是在保护这类行为。
它会断言旧 positional pattern 仍然有效。
例如:
config=RunConfig(None,MultiProvider(),None,keep_handoff_input)assertconfig.handoff_input_filteriskeep_handoff_inputassertconfig.session_settingsisNone它还覆盖:
RunConfig字段追加后的 positional binding。ToolExecutionConfig构造顺序。ModelSettings字段位置。FunctionToolguardrail 参数位置。AgentHookContextpositional 参数。ToolContext旧构造方式。RunResult和RunResultStreaming旧构造方式。
这些测试看起来“很机械”。
但它们保护的是 SDK 用户的源代码兼容性。
新增公开参数的推荐方式
如果要给公开 dataclass 或 constructor 加参数,优先:
追加到末尾例如:
@dataclassclassPublicConfig:existing_a:strexisting_b:intnew_option:bool=False不要这样:
@dataclassclassPublicConfig:existing_a:strnew_option:bool=Falseexisting_b:int=0后者会改变第二个 positional argument 的含义。
如果新字段逻辑上更靠前,也要优先保兼容。
API 的逻辑美观不能压过用户代码兼容性。
__init__.py和__all__是导入契约
顶层src/agents/__init__.py导出了大量 symbol。
例如:
from.runimportRunConfig,Runnerfrom.toolimportFunctionTool,function_tool __all__=["Agent","Runner","RunConfig","FunctionTool","function_tool",]这意味着:
fromagentsimportRunner,RunConfig,function_tool是公开路径。
如果新增公开 symbol,却忘记导出,会出现两个问题:
- 用户无法从预期路径导入。
- docs/ref 或示例可能和真实 API 不一致。
如果移动 symbol,也要保留旧导入路径或给出明确迁移策略。
lazy export 的意义
顶层agents.__init__有一个例子:
def__getattr__(name:str)->Any:ifname=="SQLiteSession":from.memory.sqlite_sessionimportSQLiteSessionglobals()[name]=SQLiteSessionreturnSQLiteSession这是 lazy export。
它的价值是:
- 保留公开导入路径。
- 避免顶层 import 触发额外依赖或副作用。
- 延迟加载较重模块。
扩展模块里也有类似思路。
例如agents.extensions.memory用_LAZY_EXPORTS管理可选依赖后端。
可选依赖不能污染顶层导入
扩展模块常常依赖第三方库。
例如:
- Redis。
- MongoDB。
- SQLAlchemy。
- Dapr。
- LiteLLM。
- E2B。
- Modal。
- Daytona。
这些依赖不能让:
importagents直接失败。
src/agents/extensions/memory/_optional_imports.py提供了清晰错误:
defraise_optional_dependency_error(export_name,*,dependency_name,extra_name):raiseImportError(f"{export_name}requires the '{dependency_name}' extra. "f"Install it with: pip install openai-agents[{extra_name}]")这类错误比裸ModuleNotFoundError更友好。
用户能知道该安装哪个 extra。
扩展模块应该放在哪里
src/agents/extensions目前包含几类扩展:
src/agents/extensions/ ├── handoff_filters.py ├── handoff_prompt.py ├── memory/ ├── models/ ├── sandbox/ ├── tool_output_trimmer.py ├── visualization.py └── experimental/可以这样判断放置位置:
| 新增能力 | 推荐位置 |
|---|---|
| memory backend | src/agents/extensions/memory/ |
| third-party model provider | src/agents/extensions/models/ |
| sandbox provider | src/agents/extensions/sandbox/<provider>/ |
| handoff helper | src/agents/extensions/handoff_*.py |
| tracing / visualization helper | src/agents/extensions/下独立模块 |
| 尚不稳定实验能力 | src/agents/extensions/experimental/ |
原则是:
核心 runtime 放 src/agents/。 可选能力和第三方集成放 extensions。不要为了方便把重依赖直接塞进顶层 runtime。
新增 model provider 的边界
如果要新增 provider adapter,先判断它是不是核心 provider。
核心 OpenAI provider 在:
src/agents/models/第三方或可选 provider 更适合:
src/agents/extensions/models/参考现有文件:
litellm_model.py litellm_provider.py any_llm_model.py any_llm_provider.pyprovider adapter 要重点处理:
- input item 转换。
- tool call 转换。
- streaming chunk 转换。
- usage 统计。
- retry 语义。
- tracing payload。
- provider-specific unsupported fields。
- optional dependency error。
测试优先放在:
tests/models/ tests/extensions/新增 session backend 的边界
Session backend 有两类:
- 核心 SDK session。
- optional extension session。
例如SQLiteSession是核心 memory 能力的一部分。
而 Redis、MongoDB、SQLAlchemy 等放在:
src/agents/extensions/memory/新增 session backend 要确认:
- 是否实现
Session协议。 - 是否支持并发访问。
- 是否支持按 turn 保存。
- 是否需要事务或原子写。
- 是否处理序列化失败。
- 是否有清理方法。
- optional dependency 是否懒加载。
测试可以参考:
tests/extensions/memory/test_redis_session.py tests/extensions/memory/test_mongodb_session.py tests/extensions/memory/test_sqlalchemy_session.py新增 sandbox provider 的边界
Sandbox provider 的入口在:
src/agents/extensions/sandbox/现有 provider 包括:
- E2B。
- Modal。
- Daytona。
- Runloop。
- Vercel。
- Cloudflare。
- Blaxel。
新增 provider 需要实现:
BaseSandboxClient.create()。BaseSandboxClient.resume()。BaseSandboxClient.delete()。BaseSandboxSession.exec()。- read/write/mkdir。
- workspace persist/hydrate。
- snapshot 或 fallback。
- shutdown。
- optional dependency import。
- provider error redaction。
还要考虑:
- PTY 是否支持。
- exposed port 是否支持。
- mount 是否支持。
- session_state 如何序列化。
- resume 后是否能复用 workspace。
测试应放在:
tests/extensions/sandbox/ tests/sandbox/如果涉及通用 sandbox 行为,不要只写 provider-specific 测试。
新增 tool 或 tool 行为的边界
Tool 是 SDK 的核心公开面。
改 tool 相关逻辑前,至少判断影响哪一层:
| 修改点 | 相关测试 |
|---|---|
| function schema | test_function_schema.py、test_strict_schema.py |
| function tool decorator | test_function_tool_decorator.py |
| tool identity | test_tool_identity.py |
| tool execution | test_tool_guardrails.py、test_run_internal_* |
| approval | test_hitl_*、test_run_context_approvals.py |
| hosted tools | test_tool_converter.py、model provider tests |
如果新增 tool output 类型,还要检查:
- item conversion。
- stream event。
- session persistence。
- tracing。
- serialization。
- docs。
这类改动通常不是单文件改动。
runtime 行为变更必须对齐 streaming 和 non-streaming
Runner 有非流式和流式路径。
如果修改 turn loop、tool execution、handoff、guardrail、approval 或错误处理,要问:
流式路径和非流式路径是否行为一致?例如:
- 非流式能抛出的异常,流式是否能传播。
- 非流式会生成的 run item,流式是否有对应 event。
- 非流式会保存 session,流式 cleanup 是否也保存。
- tool approval 在 resume 后是否两边一致。
这类边界应参考:
.agents/references/runner-lifecycle.md .agents/references/run-item-lifecycle.md .agents/references/tool-execution-lifecycle.mdRunState 和持久化格式要更谨慎
如果修改RunState序列化 shape,风险会更高。
因为这可能影响:
- pause/resume。
- HITL approval。
- agent identity。
- previous run items。
- tool call state。
- sandbox resume state。
这种改动要读:
.agents/references/runstate-schema.md还要考虑:
- schema version。
- backward read。
- migration。
- regression tests。
- 最新 release tag 之后的 unreleased churn 是否需要兼容。
不是所有 main 分支上的中间形态都必须保留兼容。
但已经发布的格式必须认真处理。
docs 和 examples 是行为契约的一部分
AGENTS.md明确提醒:
Documentation is published to the live site.所以 docs 不是随便写的说明。
它会影响用户对 SDK 行为的理解。
如果 runtime 行为变了,通常要同步:
docs/。docs/ref/。- examples。
- tests。
如果 docs 描述的是尚未发布的 SDK 行为,要小心:
- 是否应该等 SDK release 后再发布 docs。
- 是否应该拆成后续 PR。
- 是否需要在 PR 描述里说明版本关系。
不要让文档提前承诺尚未可用的行为。
docs/ref 如何生成
docs/ref是 API reference stub。
docs/scripts/generate_ref_files.py会扫描:
src/agents/**/*.py并为缺失的公开模块生成:
# `Module Title` ::: agents.some.module脚本会跳过以下文件:
ifpy_file.name.startswith("_"):continue这说明:
- 非私有模块应有机会出现在 reference。
- 私有
_xxx.py默认不生成 reference。 - 新增公开模块后要检查 docs/ref 是否需要 stub。
构建 docs 时会运行:
makebuild-docs它会先生成 ref 文件,再运行 MkDocs build。
不要编辑翻译目录
文档规则里明确说:
不要编辑 docs/ja、docs/ko、docs/zh这些是生成内容。
英文源文档才是可编辑源。
如果你改了翻译文件,后续生成流程可能覆盖它。
这类改动也会让 review 噪声很大。
测试策略:从影响面倒推
新增或修改行为时,测试不要只靠直觉。
先问:
这个变更影响哪些外部可观察行为?然后选择测试:
| 影响面 | 测试策略 |
|---|---|
| schema / payload | snapshot 或结构断言 |
| Runner turn loop | FakeModel + RunResult 断言 |
| streaming | stream event 顺序断言 |
| session persistence | save/load/roundtrip |
| RunState | JSON roundtrip 和 backward-read |
| tracing | normalized span snapshot |
| sandbox | path、manifest、snapshot、cleanup |
| provider | fake transport / payload / retry |
第十八篇已经讲过验证命令。
第十九篇要强调的是:
测试选择要对应变更边界。低风险贡献点怎么选
如果只是想熟悉项目,不建议一上来改 Runner。
更适合从低风险点开始:
- 为已有 helper 补测试。
- 补充一个错误路径测试。
- 改善 docs 中过时的小段说明。
- 给 optional extension 增加 import regression test。
- 修复 example 中的小兼容问题。
- 给已有测试加更明确的断言。
不适合新手第一步就改:
- RunState schema。
- Runner turn loop。
- tool identity。
- provider streaming converter。
- sandbox materialization。
- Realtime listener lifecycle。
这些区域不是不能改。
而是需要先读 reference,并准备更完整测试矩阵。
PR template 要填什么
PR 模板只有四个部分:
### Summary ### Test plan ### Issue number ### Checks看起来简单,但要填得有信息密度。
Summary 应该说明:
- 改了什么。
- 解决什么问题。
- 是否有行为变化。
Test plan 应该说明:
- 跑了哪些 focused tests。
- 是否跑了完整验证脚本。
- 如果没跑,原因是什么。
- 如果环境失败,失败命令和缺失依赖是什么。
Issue number 应该写:
Closes #1234或者说明没有关联 issue。
Checks 里要真实勾选,不要为了好看勾。
变更主题怎么写
用户偏好里要求:
生成汉语的变更主题和有序变更内容项。这适合本地交付,也适合转成 PR summary。
好的变更主题应该:
- 短。
- 说明主要对象。
- 使用动词。
- 不塞多个不相关主题。
示例:
变更主题:完善 function tool schema 的 Annotated 字段处理不要写:
变更主题:一些修改也不要写:
变更主题:修复问题并优化代码顺便改文档如果有多个不相关主题,应该拆 PR。
有序变更内容怎么写
有序变更内容应该按影响面写。
示例:
1. 更新 function schema 解析逻辑,保留 Annotated 中的 Field 描述。 2. 增加 schema snapshot 测试,覆盖默认值和参数描述。 3. 更新文档示例,说明 Annotated 的推荐写法。这样 reviewer 可以快速看出:
- runtime 改了哪里。
- 测试覆盖了哪里。
- docs 是否同步。
不要把命令输出塞进变更内容。
命令放在 test plan。
PR 描述示例
一个结构清晰的 PR 描述可以这样写:
### Summary 更新 function tool schema 解析,使 `Annotated` 参数中的 `Field` 描述可以稳定进入生成的 JSON schema。 ### Test plan 1. `uv run pytest tests/test_function_tool_decorator.py` 2. `bash .agents/skills/code-change-verification/scripts/run.sh` ### Issue number Closes #1234这个描述有几个优点:
- Summary 说明行为变化。
- Test plan 有 focused test 和完整验证。
- Issue number 能自动关联问题。
Release note 思路
并不是每个 PR 都需要 release note。
但 PR 描述里可以提前判断:
| 变更 | 是否值得 release note |
|---|---|
| 新公开 API | 通常需要 |
| 用户可见行为变化 | 通常需要 |
| bug fix | 视影响范围 |
| docs-only | 通常不需要 |
| internal refactor | 通常不需要 |
| tests-only | 不需要 |
如果需要 release note,可以写成用户视角:
Fixed function tool schema generation for `Annotated` parameters with `Field` metadata.不要写成内部实现视角:
Changed _schema_helper branch condition.用户关心的是行为。
什么时候需要implementation-strategy
如果变更涉及这些内容,需要先做实现策略判断:
- exported API。
- runtime behavior。
- external configuration。
- persisted schema。
- wire protocol。
- durable external state。
核心问题是:
这是否影响已发布版本中的用户行为?如果是,要考虑兼容层、迁移、测试和文档。
如果只是 main 分支上尚未发布的中间接口,则可以更直接地重写。
但这个判断必须基于 latest release tag,而不是主观感觉。
什么时候需要 OpenAI 平台知识
如果改动涉及 OpenAI API 或平台能力,例如:
- Responses API。
- Chat Completions。
- tools。
- streaming。
- Realtime API。
- auth。
- models。
- rate limits。
- MCP。
就不要靠猜。
应使用 authoritative docs,并同时检查本地 SDK 代码。
平台行为和 SDK 行为是两个层次:
平台文档说明 API 怎么工作。 本仓库代码说明 SDK 怎么适配它。写 docs 或 examples 时,两边都要对齐。
什么时候需要安全审查意识
这些改动要天然带安全意识:
- sandbox manifest。
- host path materialization。
- archive extraction。
- remote mount。
- provider credential。
- MCP tool payload。
- tracing redaction。
- exception chaining。
- logs 和 telemetry。
第十七篇已经讲过 sandbox 安全边界。
这里再强调一次:
不要让不可信输入声明自己的权限。权限应该来自可信应用代码,而不是模型、远程文件或序列化 manifest 自己声称。
分支和 worktree 安全
贡献规则要求:
默认留在用户当前 checkout 和当前分支。不要擅自:
- 创建分支。
- 切换分支。
- 创建 worktree。
- reset。
- checkout 覆盖文件。
如果确实需要隔离分支,要先说明原因并获得同意。
这是协作安全问题。
当前工作区可能有用户未提交改动。
随意切换或重置会破坏用户工作。
小步提交和小步 review
高质量 PR 应该尽量小。
一个 PR 最好只解决一个主题。
例如:
好:修复 sandbox remote mount policy 对 read-only mount 的提示。 差:重构 sandbox、顺手改 docs、再加一个 provider。小 PR 的好处:
- reviewer 更容易判断风险。
- 测试范围更清晰。
- 回滚成本低。
- release note 更准确。
- 行为变化更容易解释。
如果一个问题必须跨多个模块,也要在 PR 描述里讲清楚模块之间的因果关系。
常见误区一:只改源码,不改测试
runtime 行为变更没有测试,就是把回归风险留给 reviewer 和用户。
应该优先问:
这个行为之前为什么没被测试挡住?然后补一个能挡住同类问题的测试。
不是所有改动都需要大测试矩阵。
但用户可见行为变化至少要有 focused test。
常见误区二:新增公开 symbol 但忘记导出
如果新增了一个用户应该使用的类型,只在内部模块定义是不够的。
要检查:
- 预期 import path。
__all__。- docs/ref。
- import regression test。
如果它是可选依赖相关 symbol,要确保:
未安装 optional dependency 时,顶层 import 不失败。常见误区三:docs 代码片段没跑通
Docs 里的 runnable snippet 是 API 契约。
写示例前要确认:
- 参数名真实存在。
- import path 正确。
- async / sync 调用方式正确。
- provider extra 是否说明。
- 代码和当前 SDK 行为一致。
不要把想象中的 API 写进文档。
这会比没有文档更糟。
常见误区四:PR 描述只写“fix bug”
Reviewer 需要知道:
- bug 是什么。
- 影响谁。
- 为什么这个修复是正确边界。
- 有没有兼容性风险。
- 怎么测试。
“fix bug” 没有提供这些信息。
更好的写法是:
修复 streaming tool call arguments 在异常路径下未 flush 的问题, 并增加流式事件测试覆盖异常传播和 terminal output backfill。这能让 reviewer 直接定位风险面。
常见误区五:把 optional dependency 变成 hard dependency
如果在顶层文件直接写:
importredis可能导致未安装 Redis extra 的用户无法导入 SDK。
更稳的做法是:
- 把重依赖 import 放在扩展模块内部。
- 用 lazy export 延迟导入。
- 抛出清晰的 extra 安装提示。
- 增加 import regression test。
这对 SDK 很关键。
因为很多用户只使用核心 Agent,不应该被 Redis、MongoDB、Modal、E2B 这类依赖影响。
一个完整贡献检查清单
提交前可以按这个清单过一遍:
- 是否读了对应
.agents/references。 - 是否判断了公开 API 兼容性。
- 是否保留 positional argument 语义。
- 是否同步
__init__.py和__all__。 - optional dependency 是否不会破坏顶层 import。
- runtime 行为是否有 focused test。
- streaming 和 non-streaming 是否一致。
- RunState 或持久化格式是否有 backward-read 测试。
- docs/examples 是否同步。
- inline snapshot 是否人工审过 diff。
- 是否跑了相关 focused tests。
- 是否跑了完整验证栈。
- PR Summary 是否说明问题和解决方案。
- Test plan 是否列出真实命令。
- Issue number 是否填写。
这份清单不是每一项都必须适用。
但每一项都值得主动判断。
实践任务一:选择低风险改动点
一个适合入门的任务:
为一个已有 helper 增加错误路径测试。例如:
- 找到一个路径校验 helper。
- 读已有测试文件。
- 增加一个非法输入用例。
- 跑该测试文件。
- 跑完整验证栈。
这类任务能练习:
- 阅读源码。
- 找测试位置。
- 写最小断言。
- 使用仓库命令。
- 准备 PR test plan。
实践任务二:准备汉语变更说明
本地交付可以这样写:
变更主题:补充 workspace path 非法输入回归测试 变更内容项: 1. 新增相对路径逃逸用例,覆盖 `pkg/../../secret.txt`。 2. 断言错误类型和错误上下文,避免只检查异常字符串。 3. 运行 focused pytest 验证 workspace path 测试通过。这个说明能直接转成 PR Summary。
如果 PR 面向英文项目,可以再翻译成英文 PR 描述。
实践任务三:准备 PR test plan
测试计划可以这样写:
Test plan: 1. `uv run pytest tests/sandbox/test_workspace_paths.py` 2. `bash .agents/skills/code-change-verification/scripts/run.sh`如果只改 Markdown 教程:
Test plan: 1. Not run. Markdown-only blog update; no runtime code, tests, or build config changed.但如果改的是docs/且影响用户行为,通常还要考虑:
makebuild-docstest plan 的重点是真实、准确、可复现。
本篇小结
第十九篇主要看清了扩展与贡献的工程边界:
- 修改前先判断变更属于哪个 runtime boundary。
.agents/references是维护者级别的边界地图。- 公开 API 的参数顺序和 dataclass 字段顺序是兼容性契约。
- 新增公开 symbol 要同步 import path、
__all__、docs/ref 和测试。 - optional dependency 不能破坏顶层导入。
- 扩展能力应优先放在
src/agents/extensions下合适子目录。 - runtime 行为变更要覆盖 streaming、non-streaming、serialization、tracing 等相邻面。
- docs 和 examples 是用户可见行为契约。
- PR 描述要说明改了什么、为什么改、怎么验证。
- 高质量贡献是代码、测试、文档、验证和说明共同完成的结果。
下一篇是本系列最后一篇综合实战。
我们会把前面学过的 Agent、tools、handoffs、sessions、tracing 和 streaming 组合起来,构建一个接近真实业务的多 Agent 研究助手,并按工程流程完成实现、验证和复盘。