概述
给生成产物增强一组面向用户自定义代码的扩展接口,重点补齐当前扩展体系里的三个缺口:
hooks 从“单个无参、观察型 Hooks 子类”升级为可组合、可参数化、可显式配置的生命周期扩展点。
- 工具 / 模型调用增加薄 middleware / policy 层,支持审计、脱敏、校验、限流、缓存、重试、拒绝等横切能力,无需改核心 loop。
- 引入轻量
capability 包装模式与 forge add 样板,把 tools / hooks / prompt additions / config schema 等扩展打包成普通 Python 模块,提升产物可扩展性,但不引入任何 agent 编排框架。
本 issue 来自一次代码梳理 + 联网对比调研。当前 HarnessSmith 的方向是对的:薄注册表 + 装饰器 + config.yaml 接线;下一步要做的是把“能扩展”变成“好扩展、可发现、可配置、可验证”。
背景 / 现状
当前产物已提供这些自定义接口:
- Tools:
@registry.tool(...) / Registry.register(),由 tools allowlist + risk 控制暴露面。
- Paradigms:
@register_paradigm("name"),由 paradigms.enabled/default 选择。
- Context conditions / strategies:
@register_condition / @register_strategy,由 context.triggers / context.strategy 接线。
- Memory backends:
@register_memory,仅在 memory.enabled 生成时存在。
- Hooks:
Hooks.before_step/after_step/before_tool/after_tool/on_error,由 hooks: "pkg.mod:Class" 挂载。
- Extensions loader:
extensions: [pkg.mod],启动时 import 模块,让上述装饰器副作用生效。
- Interaction:
Asker / ToolConfirmer,支撑 ask_question 与 HITL tool confirmation。
- Prompts / rules / MCP / Skills:作为运行期可调或 spec 开关能力,与注册表体系协作。
主要缺口:
hooks 只能配置一个无参类,不能多 hook 组合,不能从 config 传参数。
- hook 粒度偏少:没有
before_model / after_model / wrap_model_call / wrap_tool_call。
before_tool 目前是观察型;真正拒绝发生在 allowlist/HITL 边界,缺少显式 tool policy / middleware 契约。
extensions / hooks 已是运行期字段,但 Web /config 面板未暴露,用户仍需手改 YAML。
- 独立扩展模块需要记得 import;
AGENTS.md 中部分示例仍引导改内置文件或手动改 __init__。
- 没有
LLM provider registry;新增 provider 仍要改 llm.py / router。
- 没有“扩展包”或
forge add 样板,用户要自己摸清文件位置、配置字段与测试方式。
竞品 / 主流 harness 参考
- LangChain / LangGraph:middleware 已是一等扩展点,常见 hook 包括
before_agent / before_model / after_model / after_agent、wrap_model_call / wrap_tool_call;HITL 依赖 checkpoint + interrupt。
- OpenAI Agents SDK:提供 function tools、guardrails、handoffs、sessions、tracing,并区分
RunHooks 与 AgentHooks;hook 粒度覆盖 agent / LLM / tool / handoff 生命周期。
- Pydantic AI:用
Capabilities 打包 tools、instructions、model settings、hooks;适合做可复用扩展包。
- AG2 / AutoGen:agent middleware 覆盖
on_turn / on_llm_call / on_tool_execution / on_human_input;另有工具级 middleware。
- CrewAI:event bus + event listener 用于观测和集成;Flows 提供 state / guardrail / persistence。
- LlamaIndex:Workflows 用 typed events +
@step + Context store 管理显式流程和状态。
对 HarnessSmith 的启发:可以吸收 middleware / guardrail / capability / event 的思想,但实现必须保持 own-your-code + 薄产物:普通 Python 函数/类、显式配置、无 agent 框架依赖、关闭零痕迹。
方案概要
A. 显式 hooks 配置增强
将当前:
hooks: "agent_harness.harness.hooks:AuditHooks"
扩展为兼容旧写法的新结构:
hooks:
- class: "agent_harness.ext.audit:AuditHooks"
enabled: true
config:
redact_args: true
log_tool_results: false
- class: "agent_harness.ext.metrics:MetricsHooks"
enabled: true
要求:
- 兼容旧字符串写法。
- 多 hook 按配置顺序执行;
after_* 是否反向执行需明确并测试。
- 单个 hook 异常走
on_error / debug log,避免吞掉核心 loop 错误语义。
- Web 流式
_StreamHooks 继续能与用户 hooks 组合。
B. 增加 model/tool 生命周期点
在不把 hook 变成复杂引擎的前提下,补齐生命周期:
before_run / after_run 或 before_turn / after_turn。
before_model(messages, tools, profile)。
after_model(response, usage, profile)。
wrap_model_call(call_next, request) 可选,用于缓存 / fallback / retry / 观测。
before_tool(call) / after_tool(call, result) 保留。
wrap_tool_call(call_next, call) 或独立 ToolPolicy,用于参数校验 / 拒绝 / 结果脱敏 / 限流。
on_stream_delta / on_thinking_delta 可选,用于 UI/日志/指标。
on_budget_block / on_context_compact / on_session_checkpoint 可选,用于可观测性。
薄优先建议:先做 before_model / after_model / wrap_tool_call 或 ToolPolicy,不要一次性做全事件总线。
C. Tool policy / middleware
新增一个独立于 risk 的薄契约,使工具级策略显式可配:
tool_policies:
- class: "agent_harness.ext.security:SecretBlockPolicy"
tools: ["shell", "write_file", "desktop-commander__*"]
config:
block_patterns: ["sk-", "AKIA"]
能力:
- 执行前校验参数,可返回拒绝 observation。
- 执行后可脱敏结果或裁剪结果。
- 可统计耗时 / token / result size。
- 与现有 HITL
confirm 分层:confirm 是内置人审 policy,tool policy 是用户扩展 policy。
D. Capability bundle
提供一个很薄的“能力包”模式,避免用户在多个文件里手动接线:
# src/agent_harness/ext/github_capability.py
from agent_harness.harness.capabilities import capability
@capability("github")
def github():
return {
"tools": [search_issues, create_issue],
"hooks": [AuditHooks],
"prompt_additions": ["You may use GitHub tools for repo operations."],
"config_schema": GithubConfig,
"env": ["GITHUB_TOKEN"],
}
运行期:
capabilities:
- module: "agent_harness.ext.github_capability"
name: github
enabled: true
config:
default_repo: "owner/repo"
注意:这不是插件框架 / marketplace,只是“一个模块声明一组普通 Python 扩展”的接线糖。
E. Web / CLI 可发现性补齐
- Web
/config 增加 Extensions / Hooks 页面或 System 页字段。
/registries 扩展到 tools、hooks、capabilities、policies、LLM providers。
info 输出:
- 已 import 的 extension modules。
- 已注册工具及 risk / allowlist / policy。
- 已挂 hooks / tool policies / capabilities。
- 未解析名字给出“把模块加入 extensions[]”的修复建议。
F. forge add 样板
新增开发期命令,不让产物运行期依赖 HarnessSmith:
harnessmith forge add tool my_tool
harnessmith forge add hook audit
harnessmith forge add paradigm review
harnessmith forge add memory-backend sqlite
harnessmith forge add capability github
输出:新增用户模块、测试样板、config.yaml 接线提示或安全 patch。forge add 属 v1+ 增量再生成方向,可拆独立 issue / slice。
交付物
生成产物模板层
harness/hooks.py.j2:新增 hook 组合器 / 新生命周期点 / 参数化构造约定。
harness/extensions.py.j2:加载多个 hooks / policies / capabilities;旧 hooks: string 兼容。
harness/paradigms/__init__.py.j2:在 generate() / run_tool() 边界接入 model/tool middleware。
harness/config.py.j2 + config.yaml.j2:新增 runtime 字段,保持 extra="forbid" 与注释清楚。
interfaces/cli.py.j2:更新 _prepare_runtime() / info 输出。
interfaces/web.py.j2 + web_index.html.j2:暴露 extensions / hooks / registries。
AGENTS.md.j2 / README.md.j2:统一推荐“独立模块 + extensions[]”;新增扩展示例。
tests/*.j2:覆盖 hooks 组合、旧写法兼容、model/tool middleware、Web/CLI 可发现性、黄金路径。
生成器层(可后续拆分)
forge add 样板命令:若纳入本片,需更新 generator/CLI/docs/tests;否则另立 issue。
任务拆解
验收标准(退出门禁)
需人审决策(命中 CLAUDE.md §6 的点)
- 可能改运行期配置 schema,但不一定改
HarnessSpec:若仅改产物 config.yaml / Config,不命中 §6.1;若把 capability / hook 作为生成期结构开关,则需人审。
- 默认产物不得新增运行期依赖:本片必须用 stdlib + 已有依赖完成;如引入第三方 middleware/event 库则命中 §6.2,不建议。
- 禁止 agent 编排框架:不得引入 LangChain / LangGraph / ADK / workflow DSL / 动态图引擎。
- hook 是否允许改变控制流:需要定口径。建议:观察型 hooks 默认只观测;能拒绝/改写的能力放在显式
ToolPolicy / wrap_* 中,语义更清楚。
- capability 是否进首版:能力包会提升体验,但可能扩大范围;可先做 hooks + tool policy,capability / forge add 后续拆片。
非目标
- 不做通用插件 marketplace。
- 不做 LangGraph / CrewAI Flow 式 workflow DSL。
- 不把多 agent supervisor、RAG、eval 平台混进本片。
- 不给默认产物增加新运行期依赖。
- 不改变“产物运行期不依赖 HarnessSmith”的边界;
forge add 若做,也只能是开发期 codemod。
- 不把 hook 当生产级安全边界;真正隔离仍靠 Docker / 不编译危险能力 / 后端凭证作用域。
风险
- 范围蔓延:middleware / capability 很容易演变成框架。必须坚持“普通 Python + 显式 registry + 显式 config”。
- hook 顺序与异常语义:多 hook 组合后,异常传播、
on_error、after 反向顺序需要写清并测试。
- 密钥泄露路径:model/tool hooks 能看到 messages / arguments / results,文档和默认实现必须提醒 trace/debug/redaction 边界。
- Web 配置面复杂度:新增列表型 hooks / policies 后,Web 表单要保持简单,不能拖累默认 UX。
- 兼容性:旧
hooks 字符串、现有 extensions[]、现有 tests/presets 必须保持可用。
建议落地顺序
- P0:多 hooks + 参数化配置 + Web/CLI 可见。
- P0:model 调用 hooks + tool policy / tool middleware。
- P1:capability bundle(只做模块声明与接线,不做 marketplace)。
- P1:
@register_llm_provider。
- P1 / v1+:
forge add 扩展样板。
- P2:产物内薄 eval / golden-task harness,用于验证自定义扩展。
参考
- 项目定位与扩展原则:
docs/02-development/00-overview.md §3 / §6 / §8。
- 当前模板扩展点:
harnessmith/templates/src/__project_slug__/harness/hooks.py.j2、extensions.py.j2、tools.py.j2、context.py.j2、paradigms/__init__.py.j2、memory.py.j2。
- 当前入口接线:
interfaces/cli.py.j2::_prepare_runtime、interfaces/web.py.j2::_EDITABLE_FIELDS / /registries。
- 用户扩展指南:
harnessmith/templates/AGENTS.md.j2。
- 外部参考:LangChain middleware、OpenAI Agents SDK lifecycle hooks / guardrails、Pydantic AI capabilities、AG2 middleware / tool middleware、CrewAI event listeners、LlamaIndex workflows。
概述
给生成产物增强一组面向用户自定义代码的扩展接口,重点补齐当前扩展体系里的三个缺口:
hooks从“单个无参、观察型 Hooks 子类”升级为可组合、可参数化、可显式配置的生命周期扩展点。capability包装模式与forge add样板,把 tools / hooks / prompt additions / config schema 等扩展打包成普通 Python 模块,提升产物可扩展性,但不引入任何 agent 编排框架。本 issue 来自一次代码梳理 + 联网对比调研。当前 HarnessSmith 的方向是对的:薄注册表 + 装饰器 +
config.yaml接线;下一步要做的是把“能扩展”变成“好扩展、可发现、可配置、可验证”。背景 / 现状
当前产物已提供这些自定义接口:
@registry.tool(...)/Registry.register(),由toolsallowlist +risk控制暴露面。@register_paradigm("name"),由paradigms.enabled/default选择。@register_condition/@register_strategy,由context.triggers/context.strategy接线。@register_memory,仅在memory.enabled生成时存在。Hooks.before_step/after_step/before_tool/after_tool/on_error,由hooks: "pkg.mod:Class"挂载。extensions: [pkg.mod],启动时 import 模块,让上述装饰器副作用生效。Asker/ToolConfirmer,支撑ask_question与 HITL tool confirmation。主要缺口:
hooks只能配置一个无参类,不能多 hook 组合,不能从 config 传参数。before_model/after_model/wrap_model_call/wrap_tool_call。before_tool目前是观察型;真正拒绝发生在 allowlist/HITL 边界,缺少显式 tool policy / middleware 契约。extensions/hooks已是运行期字段,但 Web/config面板未暴露,用户仍需手改 YAML。AGENTS.md中部分示例仍引导改内置文件或手动改__init__。LLM provider registry;新增 provider 仍要改llm.py/ router。forge add样板,用户要自己摸清文件位置、配置字段与测试方式。竞品 / 主流 harness 参考
before_agent/before_model/after_model/after_agent、wrap_model_call/wrap_tool_call;HITL 依赖 checkpoint + interrupt。RunHooks与AgentHooks;hook 粒度覆盖 agent / LLM / tool / handoff 生命周期。Capabilities打包 tools、instructions、model settings、hooks;适合做可复用扩展包。on_turn/on_llm_call/on_tool_execution/on_human_input;另有工具级 middleware。@step+ Context store 管理显式流程和状态。对 HarnessSmith 的启发:可以吸收 middleware / guardrail / capability / event 的思想,但实现必须保持 own-your-code + 薄产物:普通 Python 函数/类、显式配置、无 agent 框架依赖、关闭零痕迹。
方案概要
A. 显式 hooks 配置增强
将当前:
扩展为兼容旧写法的新结构:
要求:
after_*是否反向执行需明确并测试。on_error/ debug log,避免吞掉核心 loop 错误语义。_StreamHooks继续能与用户 hooks 组合。B. 增加 model/tool 生命周期点
在不把 hook 变成复杂引擎的前提下,补齐生命周期:
before_run/after_run或before_turn/after_turn。before_model(messages, tools, profile)。after_model(response, usage, profile)。wrap_model_call(call_next, request)可选,用于缓存 / fallback / retry / 观测。before_tool(call)/after_tool(call, result)保留。wrap_tool_call(call_next, call)或独立ToolPolicy,用于参数校验 / 拒绝 / 结果脱敏 / 限流。on_stream_delta/on_thinking_delta可选,用于 UI/日志/指标。on_budget_block/on_context_compact/on_session_checkpoint可选,用于可观测性。薄优先建议:先做
before_model/after_model/wrap_tool_call或ToolPolicy,不要一次性做全事件总线。C. Tool policy / middleware
新增一个独立于
risk的薄契约,使工具级策略显式可配:能力:
confirm分层:confirm 是内置人审 policy,tool policy 是用户扩展 policy。D. Capability bundle
提供一个很薄的“能力包”模式,避免用户在多个文件里手动接线:
运行期:
注意:这不是插件框架 / marketplace,只是“一个模块声明一组普通 Python 扩展”的接线糖。
E. Web / CLI 可发现性补齐
/config增加 Extensions / Hooks 页面或 System 页字段。/registries扩展到 tools、hooks、capabilities、policies、LLM providers。info输出:F.
forge add样板新增开发期命令,不让产物运行期依赖 HarnessSmith:
输出:新增用户模块、测试样板、
config.yaml接线提示或安全 patch。forge add属 v1+ 增量再生成方向,可拆独立 issue / slice。交付物
生成产物模板层
harness/hooks.py.j2:新增 hook 组合器 / 新生命周期点 / 参数化构造约定。harness/extensions.py.j2:加载多个 hooks / policies / capabilities;旧hooks: string兼容。harness/paradigms/__init__.py.j2:在generate()/run_tool()边界接入 model/tool middleware。harness/config.py.j2+config.yaml.j2:新增 runtime 字段,保持extra="forbid"与注释清楚。interfaces/cli.py.j2:更新_prepare_runtime()/info输出。interfaces/web.py.j2+web_index.html.j2:暴露extensions/hooks/ registries。AGENTS.md.j2/README.md.j2:统一推荐“独立模块 + extensions[]”;新增扩展示例。tests/*.j2:覆盖 hooks 组合、旧写法兼容、model/tool middleware、Web/CLI 可发现性、黄金路径。生成器层(可后续拆分)
forge add样板命令:若纳入本片,需更新 generator/CLI/docs/tests;否则另立 issue。任务拆解
hooks新配置模型,兼容旧字符串写法。CompositeHooks/ 参数化 hook 构造 / 顺序规则。before_model/after_model。wrap_tool_call或ToolPolicy契约。/config暴露extensions/hooks;/registries增补扩展注册项。info增补 extensions/hooks/policies/capabilities/tool risk 与 allowlist 状态。AGENTS.md扩展指南,统一独立模块写法。capabilities与forge add纳入本片,或拆为后续 issue。验收标准(退出门禁)
hooks: "pkg.mod:Class"仍可用。_StreamHooks与用户 hooks 可组合。config收到参数。extensions[]导入失败、hook 类不存在、hook 类型不匹配时给出 cleanConfigError。/config可编辑并保存 extensions/hooks;/registries能看到自定义注册项。info能列出扩展、hooks、工具 risk / allowlist / policy 状态。pyproject.toml不含langchain/langgraph/adk。uv sync && pytest→ mock function-calling 工具调用。CLAUDE.md §5.2跑全量 golden + Docker 冒烟 +uvx harnessmith new冒烟。ReadLintsclean。需人审决策(命中
CLAUDE.md §6的点)HarnessSpec:若仅改产物config.yaml/Config,不命中 §6.1;若把 capability / hook 作为生成期结构开关,则需人审。ToolPolicy/wrap_*中,语义更清楚。非目标
forge add若做,也只能是开发期 codemod。风险
on_error、after 反向顺序需要写清并测试。hooks字符串、现有extensions[]、现有 tests/presets 必须保持可用。建议落地顺序
@register_llm_provider。forge add扩展样板。参考
docs/02-development/00-overview.md§3 / §6 / §8。harnessmith/templates/src/__project_slug__/harness/hooks.py.j2、extensions.py.j2、tools.py.j2、context.py.j2、paradigms/__init__.py.j2、memory.py.j2。interfaces/cli.py.j2::_prepare_runtime、interfaces/web.py.j2::_EDITABLE_FIELDS//registries。harnessmith/templates/AGENTS.md.j2。