openai-agents-python-sdk 源码解析 | 第十九篇:扩展与贡献:从阅读源码到提交高质量 PR
2026/8/4 12:55:07 网站建设 项目流程

本篇导读

前十八篇已经覆盖了 SDK 的主要能力和测试体系。

这一篇回答一个更工程化的问题:

如果要给 OpenAI Agents Python SDK 做一个高质量改动,应该怎么组织?

这里的“高质量”不只是代码能跑。

它至少包含:

  1. 变更边界清楚。
  2. 公共 API 兼容性可解释。
  3. 导入路径和__all__没有破坏。
  4. runtime 行为有测试覆盖。
  5. docs 和 examples 与行为同步。
  6. 可选依赖不会污染顶层导入。
  7. PR 描述能让 reviewer 快速判断风险。
  8. 验证命令真实跑过,结果可复现。

本篇重点回答十个问题:

  1. 修改前应该先读哪些仓库规则。
  2. 为什么公开 API 的参数顺序也是兼容性契约。
  3. 新增公开 symbol 时为什么要同步__init__.py__all__
  4. 扩展模块应该放在哪些目录。
  5. 可选依赖为什么要做 lazy import 或清晰报错。
  6. 修改 runtime 行为时怎样选择参考文档。
  7. docs/ref 和用户文档如何同步。
  8. 如何准备测试和验证记录。
  9. PR template 需要填写什么。
  10. 如何写出清晰的变更主题和有序变更内容。

第十九篇关注的源码入口

这一篇主要看这些文件:

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.mdruntime 边界参考地图
src/agents/__init__.py顶层公开导出契约
src/agents/extensions扩展能力存放位置
docs/refAPI reference 文档入口
docs/scripts/generate_ref_files.pyreference stub 生成脚本
tests/test_source_compat_constructors.py公开构造器兼容性回归测试
.github/PULL_REQUEST_TEMPLATE/pull_request_template.mdPR 描述模板

先给结论:贡献流程从“边界判断”开始

不要一上来就改代码。

更稳的流程是:

1. 判断变更属于哪个运行边界 2. 阅读对应源码和 maintainer reference 3. 判断是否触及公开 API 或持久化格式 4. 设计兼容策略 5. 写 focused test 6. 实现小步变更 7. 跑相关测试和完整验证栈 8. 同步 docs / examples 9. 准备 PR 描述和 test plan

这不是流程主义。

Agent SDK 的很多行为是跨模块联动的。

例如一个新的 tool call item,可能影响:

  1. model output processing。
  2. stream events。
  3. RunState serialization。
  4. session replay。
  5. tracing。
  6. tests。
  7. docs。

如果只在一个文件里“把功能加上”,很容易漏掉外部行为面。

仓库规则的入口是 AGENTS.md

AGENTS.md是本仓库的贡献入口。

它规定了几类强约束:

  1. 必须使用哪些验证流程。
  2. 什么时候需要实现策略判断。
  3. 公开 API 兼容性要求。
  4. Git worktree 和 branch 安全。
  5. docs、security、platform 行为注意事项。
  6. runtime 模块的架构参考。

其中最容易被低估的是:

公共 API 兼容性

SDK 的用户代码可能已经写了:

RunConfig(None,provider,None,handoff_input_filter)

即使你更喜欢 keyword arguments,也不能因此破坏已有 positional call。

判断变更类型

修改前先把变更分类。

变更类型典型路径风险
runtime 行为src/agents/run.pyrun_internal/
公开 APIsrc/agents/__init__.py、dataclass、constructor
provider 适配src/agents/models/extensions/models/中到高
session / RunStatememory/run_state.py
sandboxsrc/agents/sandbox/
optional extensionsrc/agents/extensions/
docsdocs/docs/ref
examplesexamples/
tests onlytests/低到中

分类的目的不是贴标签。

而是决定:

  1. 要读哪些 reference。
  2. 要补哪些测试。
  3. 是否需要兼容层。
  4. 是否需要文档或 example。
  5. PR 描述里要说明哪些风险。

.agents/references是维护者地图

.agents/references/README.md是一张 runtime 边界地图。

例如:

要改的内容应读 reference
Agent 字段、clone、instructionsagent-definition-and-run-context.md
Runner turn loop、handoff、guardrailsrunner-lifecycle.md
新增 run item 或 stream eventrun-item-lifecycle.md
function tool schemafunction-and-output-schema.md
tool lookup、namespace、approvaltool-identity.md
tool 执行、并发、timeouttool-execution-lifecycle.md
session persistencesession-persistence.md
RunState 序列化runstate-schema.md
provider adaptermodel-provider-boundaries.md
tracingtracing-lifecycle.md
realtimerealtime-session-lifecycle.md
voicevoice-pipeline-lifecycle.md
sandboxsandbox-runtime-boundary.md

这些文件不是用户文档。

它们记录的是维护者需要守住的实现边界。

如果你要改某个 runtime 边界,先读对应 reference,可以少踩很多坑。

公开 API 兼容性:字段顺序也是契约

AGENTS.md明确要求:

Treat the parameter and dataclass field order of exported runtime APIs as a compatibility contract.

意思是:

  1. 公开构造器的参数顺序不能随便改。
  2. dataclass 字段顺序不能随便插入。
  3. 新增可选参数时优先追加到末尾。
  4. 如果无法避免重排,要加兼容层和回归测试。

这对 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

它还覆盖:

  1. RunConfig字段追加后的 positional binding。
  2. ToolExecutionConfig构造顺序。
  3. ModelSettings字段位置。
  4. FunctionToolguardrail 参数位置。
  5. AgentHookContextpositional 参数。
  6. ToolContext旧构造方式。
  7. RunResultRunResultStreaming旧构造方式。

这些测试看起来“很机械”。

但它们保护的是 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,却忘记导出,会出现两个问题:

  1. 用户无法从预期路径导入。
  2. docs/ref 或示例可能和真实 API 不一致。

如果移动 symbol,也要保留旧导入路径或给出明确迁移策略。

lazy export 的意义

顶层agents.__init__有一个例子:

def__getattr__(name:str)->Any:ifname=="SQLiteSession":from.memory.sqlite_sessionimportSQLiteSessionglobals()[name]=SQLiteSessionreturnSQLiteSession

这是 lazy export。

它的价值是:

  1. 保留公开导入路径。
  2. 避免顶层 import 触发额外依赖或副作用。
  3. 延迟加载较重模块。

扩展模块里也有类似思路。

例如agents.extensions.memory_LAZY_EXPORTS管理可选依赖后端。

可选依赖不能污染顶层导入

扩展模块常常依赖第三方库。

例如:

  1. Redis。
  2. MongoDB。
  3. SQLAlchemy。
  4. Dapr。
  5. LiteLLM。
  6. E2B。
  7. Modal。
  8. 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 backendsrc/agents/extensions/memory/
third-party model providersrc/agents/extensions/models/
sandbox providersrc/agents/extensions/sandbox/<provider>/
handoff helpersrc/agents/extensions/handoff_*.py
tracing / visualization helpersrc/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.py

provider adapter 要重点处理:

  1. input item 转换。
  2. tool call 转换。
  3. streaming chunk 转换。
  4. usage 统计。
  5. retry 语义。
  6. tracing payload。
  7. provider-specific unsupported fields。
  8. optional dependency error。

测试优先放在:

tests/models/ tests/extensions/

新增 session backend 的边界

Session backend 有两类:

  1. 核心 SDK session。
  2. optional extension session。

例如SQLiteSession是核心 memory 能力的一部分。

而 Redis、MongoDB、SQLAlchemy 等放在:

src/agents/extensions/memory/

新增 session backend 要确认:

  1. 是否实现Session协议。
  2. 是否支持并发访问。
  3. 是否支持按 turn 保存。
  4. 是否需要事务或原子写。
  5. 是否处理序列化失败。
  6. 是否有清理方法。
  7. 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 包括:

  1. E2B。
  2. Modal。
  3. Daytona。
  4. Runloop。
  5. Vercel。
  6. Cloudflare。
  7. Blaxel。

新增 provider 需要实现:

  1. BaseSandboxClient.create()
  2. BaseSandboxClient.resume()
  3. BaseSandboxClient.delete()
  4. BaseSandboxSession.exec()
  5. read/write/mkdir。
  6. workspace persist/hydrate。
  7. snapshot 或 fallback。
  8. shutdown。
  9. optional dependency import。
  10. provider error redaction。

还要考虑:

  1. PTY 是否支持。
  2. exposed port 是否支持。
  3. mount 是否支持。
  4. session_state 如何序列化。
  5. resume 后是否能复用 workspace。

测试应放在:

tests/extensions/sandbox/ tests/sandbox/

如果涉及通用 sandbox 行为,不要只写 provider-specific 测试。

新增 tool 或 tool 行为的边界

Tool 是 SDK 的核心公开面。

改 tool 相关逻辑前,至少判断影响哪一层:

修改点相关测试
function schematest_function_schema.pytest_strict_schema.py
function tool decoratortest_function_tool_decorator.py
tool identitytest_tool_identity.py
tool executiontest_tool_guardrails.pytest_run_internal_*
approvaltest_hitl_*test_run_context_approvals.py
hosted toolstest_tool_converter.py、model provider tests

如果新增 tool output 类型,还要检查:

  1. item conversion。
  2. stream event。
  3. session persistence。
  4. tracing。
  5. serialization。
  6. docs。

这类改动通常不是单文件改动。

runtime 行为变更必须对齐 streaming 和 non-streaming

Runner 有非流式和流式路径。

如果修改 turn loop、tool execution、handoff、guardrail、approval 或错误处理,要问:

流式路径和非流式路径是否行为一致?

例如:

  1. 非流式能抛出的异常,流式是否能传播。
  2. 非流式会生成的 run item,流式是否有对应 event。
  3. 非流式会保存 session,流式 cleanup 是否也保存。
  4. tool approval 在 resume 后是否两边一致。

这类边界应参考:

.agents/references/runner-lifecycle.md .agents/references/run-item-lifecycle.md .agents/references/tool-execution-lifecycle.md

RunState 和持久化格式要更谨慎

如果修改RunState序列化 shape,风险会更高。

因为这可能影响:

  1. pause/resume。
  2. HITL approval。
  3. agent identity。
  4. previous run items。
  5. tool call state。
  6. sandbox resume state。

这种改动要读:

.agents/references/runstate-schema.md

还要考虑:

  1. schema version。
  2. backward read。
  3. migration。
  4. regression tests。
  5. 最新 release tag 之后的 unreleased churn 是否需要兼容。

不是所有 main 分支上的中间形态都必须保留兼容。

但已经发布的格式必须认真处理。

docs 和 examples 是行为契约的一部分

AGENTS.md明确提醒:

Documentation is published to the live site.

所以 docs 不是随便写的说明。

它会影响用户对 SDK 行为的理解。

如果 runtime 行为变了,通常要同步:

  1. docs/
  2. docs/ref/
  3. examples。
  4. tests。

如果 docs 描述的是尚未发布的 SDK 行为,要小心:

  1. 是否应该等 SDK release 后再发布 docs。
  2. 是否应该拆成后续 PR。
  3. 是否需要在 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

这说明:

  1. 非私有模块应有机会出现在 reference。
  2. 私有_xxx.py默认不生成 reference。
  3. 新增公开模块后要检查 docs/ref 是否需要 stub。

构建 docs 时会运行:

makebuild-docs

它会先生成 ref 文件,再运行 MkDocs build。

不要编辑翻译目录

文档规则里明确说:

不要编辑 docs/ja、docs/ko、docs/zh

这些是生成内容。

英文源文档才是可编辑源。

如果你改了翻译文件,后续生成流程可能覆盖它。

这类改动也会让 review 噪声很大。

测试策略:从影响面倒推

新增或修改行为时,测试不要只靠直觉。

先问:

这个变更影响哪些外部可观察行为?

然后选择测试:

影响面测试策略
schema / payloadsnapshot 或结构断言
Runner turn loopFakeModel + RunResult 断言
streamingstream event 顺序断言
session persistencesave/load/roundtrip
RunStateJSON roundtrip 和 backward-read
tracingnormalized span snapshot
sandboxpath、manifest、snapshot、cleanup
providerfake transport / payload / retry

第十八篇已经讲过验证命令。

第十九篇要强调的是:

测试选择要对应变更边界。

低风险贡献点怎么选

如果只是想熟悉项目,不建议一上来改 Runner。

更适合从低风险点开始:

  1. 为已有 helper 补测试。
  2. 补充一个错误路径测试。
  3. 改善 docs 中过时的小段说明。
  4. 给 optional extension 增加 import regression test。
  5. 修复 example 中的小兼容问题。
  6. 给已有测试加更明确的断言。

不适合新手第一步就改:

  1. RunState schema。
  2. Runner turn loop。
  3. tool identity。
  4. provider streaming converter。
  5. sandbox materialization。
  6. Realtime listener lifecycle。

这些区域不是不能改。

而是需要先读 reference,并准备更完整测试矩阵。

PR template 要填什么

PR 模板只有四个部分:

### Summary ### Test plan ### Issue number ### Checks

看起来简单,但要填得有信息密度。

Summary 应该说明:

  1. 改了什么。
  2. 解决什么问题。
  3. 是否有行为变化。

Test plan 应该说明:

  1. 跑了哪些 focused tests。
  2. 是否跑了完整验证脚本。
  3. 如果没跑,原因是什么。
  4. 如果环境失败,失败命令和缺失依赖是什么。

Issue number 应该写:

Closes #1234

或者说明没有关联 issue。

Checks 里要真实勾选,不要为了好看勾。

变更主题怎么写

用户偏好里要求:

生成汉语的变更主题和有序变更内容项。

这适合本地交付,也适合转成 PR summary。

好的变更主题应该:

  1. 短。
  2. 说明主要对象。
  3. 使用动词。
  4. 不塞多个不相关主题。

示例:

变更主题:完善 function tool schema 的 Annotated 字段处理

不要写:

变更主题:一些修改

也不要写:

变更主题:修复问题并优化代码顺便改文档

如果有多个不相关主题,应该拆 PR。

有序变更内容怎么写

有序变更内容应该按影响面写。

示例:

1. 更新 function schema 解析逻辑,保留 Annotated 中的 Field 描述。 2. 增加 schema snapshot 测试,覆盖默认值和参数描述。 3. 更新文档示例,说明 Annotated 的推荐写法。

这样 reviewer 可以快速看出:

  1. runtime 改了哪里。
  2. 测试覆盖了哪里。
  3. 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

这个描述有几个优点:

  1. Summary 说明行为变化。
  2. Test plan 有 focused test 和完整验证。
  3. 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

如果变更涉及这些内容,需要先做实现策略判断:

  1. exported API。
  2. runtime behavior。
  3. external configuration。
  4. persisted schema。
  5. wire protocol。
  6. durable external state。

核心问题是:

这是否影响已发布版本中的用户行为?

如果是,要考虑兼容层、迁移、测试和文档。

如果只是 main 分支上尚未发布的中间接口,则可以更直接地重写。

但这个判断必须基于 latest release tag,而不是主观感觉。

什么时候需要 OpenAI 平台知识

如果改动涉及 OpenAI API 或平台能力,例如:

  1. Responses API。
  2. Chat Completions。
  3. tools。
  4. streaming。
  5. Realtime API。
  6. auth。
  7. models。
  8. rate limits。
  9. MCP。

就不要靠猜。

应使用 authoritative docs,并同时检查本地 SDK 代码。

平台行为和 SDK 行为是两个层次:

平台文档说明 API 怎么工作。 本仓库代码说明 SDK 怎么适配它。

写 docs 或 examples 时,两边都要对齐。

什么时候需要安全审查意识

这些改动要天然带安全意识:

  1. sandbox manifest。
  2. host path materialization。
  3. archive extraction。
  4. remote mount。
  5. provider credential。
  6. MCP tool payload。
  7. tracing redaction。
  8. exception chaining。
  9. logs 和 telemetry。

第十七篇已经讲过 sandbox 安全边界。

这里再强调一次:

不要让不可信输入声明自己的权限。

权限应该来自可信应用代码,而不是模型、远程文件或序列化 manifest 自己声称。

分支和 worktree 安全

贡献规则要求:

默认留在用户当前 checkout 和当前分支。

不要擅自:

  1. 创建分支。
  2. 切换分支。
  3. 创建 worktree。
  4. reset。
  5. checkout 覆盖文件。

如果确实需要隔离分支,要先说明原因并获得同意。

这是协作安全问题。

当前工作区可能有用户未提交改动。

随意切换或重置会破坏用户工作。

小步提交和小步 review

高质量 PR 应该尽量小。

一个 PR 最好只解决一个主题。

例如:

好:修复 sandbox remote mount policy 对 read-only mount 的提示。 差:重构 sandbox、顺手改 docs、再加一个 provider。

小 PR 的好处:

  1. reviewer 更容易判断风险。
  2. 测试范围更清晰。
  3. 回滚成本低。
  4. release note 更准确。
  5. 行为变化更容易解释。

如果一个问题必须跨多个模块,也要在 PR 描述里讲清楚模块之间的因果关系。

常见误区一:只改源码,不改测试

runtime 行为变更没有测试,就是把回归风险留给 reviewer 和用户。

应该优先问:

这个行为之前为什么没被测试挡住?

然后补一个能挡住同类问题的测试。

不是所有改动都需要大测试矩阵。

但用户可见行为变化至少要有 focused test。

常见误区二:新增公开 symbol 但忘记导出

如果新增了一个用户应该使用的类型,只在内部模块定义是不够的。

要检查:

  1. 预期 import path。
  2. __all__
  3. docs/ref。
  4. import regression test。

如果它是可选依赖相关 symbol,要确保:

未安装 optional dependency 时,顶层 import 不失败。

常见误区三:docs 代码片段没跑通

Docs 里的 runnable snippet 是 API 契约。

写示例前要确认:

  1. 参数名真实存在。
  2. import path 正确。
  3. async / sync 调用方式正确。
  4. provider extra 是否说明。
  5. 代码和当前 SDK 行为一致。

不要把想象中的 API 写进文档。

这会比没有文档更糟。

常见误区四:PR 描述只写“fix bug”

Reviewer 需要知道:

  1. bug 是什么。
  2. 影响谁。
  3. 为什么这个修复是正确边界。
  4. 有没有兼容性风险。
  5. 怎么测试。

“fix bug” 没有提供这些信息。

更好的写法是:

修复 streaming tool call arguments 在异常路径下未 flush 的问题, 并增加流式事件测试覆盖异常传播和 terminal output backfill。

这能让 reviewer 直接定位风险面。

常见误区五:把 optional dependency 变成 hard dependency

如果在顶层文件直接写:

importredis

可能导致未安装 Redis extra 的用户无法导入 SDK。

更稳的做法是:

  1. 把重依赖 import 放在扩展模块内部。
  2. 用 lazy export 延迟导入。
  3. 抛出清晰的 extra 安装提示。
  4. 增加 import regression test。

这对 SDK 很关键。

因为很多用户只使用核心 Agent,不应该被 Redis、MongoDB、Modal、E2B 这类依赖影响。

一个完整贡献检查清单

提交前可以按这个清单过一遍:

  1. 是否读了对应.agents/references
  2. 是否判断了公开 API 兼容性。
  3. 是否保留 positional argument 语义。
  4. 是否同步__init__.py__all__
  5. optional dependency 是否不会破坏顶层 import。
  6. runtime 行为是否有 focused test。
  7. streaming 和 non-streaming 是否一致。
  8. RunState 或持久化格式是否有 backward-read 测试。
  9. docs/examples 是否同步。
  10. inline snapshot 是否人工审过 diff。
  11. 是否跑了相关 focused tests。
  12. 是否跑了完整验证栈。
  13. PR Summary 是否说明问题和解决方案。
  14. Test plan 是否列出真实命令。
  15. Issue number 是否填写。

这份清单不是每一项都必须适用。

但每一项都值得主动判断。

实践任务一:选择低风险改动点

一个适合入门的任务:

为一个已有 helper 增加错误路径测试。

例如:

  1. 找到一个路径校验 helper。
  2. 读已有测试文件。
  3. 增加一个非法输入用例。
  4. 跑该测试文件。
  5. 跑完整验证栈。

这类任务能练习:

  1. 阅读源码。
  2. 找测试位置。
  3. 写最小断言。
  4. 使用仓库命令。
  5. 准备 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-docs

test plan 的重点是真实、准确、可复现。

本篇小结

第十九篇主要看清了扩展与贡献的工程边界:

  1. 修改前先判断变更属于哪个 runtime boundary。
  2. .agents/references是维护者级别的边界地图。
  3. 公开 API 的参数顺序和 dataclass 字段顺序是兼容性契约。
  4. 新增公开 symbol 要同步 import path、__all__、docs/ref 和测试。
  5. optional dependency 不能破坏顶层导入。
  6. 扩展能力应优先放在src/agents/extensions下合适子目录。
  7. runtime 行为变更要覆盖 streaming、non-streaming、serialization、tracing 等相邻面。
  8. docs 和 examples 是用户可见行为契约。
  9. PR 描述要说明改了什么、为什么改、怎么验证。
  10. 高质量贡献是代码、测试、文档、验证和说明共同完成的结果。

下一篇是本系列最后一篇综合实战。

我们会把前面学过的 Agent、tools、handoffs、sessions、tracing 和 streaming 组合起来,构建一个接近真实业务的多 Agent 研究助手,并按工程流程完成实现、验证和复盘。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询