- 人工智能
- 大模型
- AI Agent
- Agent 框架
- 多智能体
- 工具调用
- MCP 服务
【免费下载链接】harness-sdk
Build an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python & TypeScript - any model, any cloud.
本文是面向 AI 编码助手与人类贡献者的harness-py包开发指南。strands-harness(导入名strands_harness)是 Strands 生态中「一次调用即可得到预配置 Agent」的 Python 库层,它把模型解析、系统提示词、内置工具、上下文管理与可选的会话持久化组合成一个普通的strands.Agent。读完本文,你将掌握:create_harness()工厂的组装原理与全部可覆盖默认值、内置工具与插件的挂载方式、开发环境搭建与提交前检查流程,以及该包独有的 Python 风格约定(导入规范、显式优先透传、effort 映射、Ruff 规则等)。
本文内容以 harness-py/AGENTS.md(harness-py/CLAUDE.md 指向的包内开发指南)为主体骨架,并结合
harness-py/下的源码、测试与配置逐层展开验证。
包定位:一个薄组合层,而非又一个 Agent 框架
strands-harness的设计哲学在 harness-py/AGENTS.md 中一句话讲透:它是一个预配置的 Strands Agent,一次调用即可完成组装。它不是一个独立的 Agent 框架,而是位于strands-agentsSDK 之上的薄组合层(thin composition layer):把「解析好的模型 + 官方系统提示词 + 内置工具 + 上下文管理 + 可选会话持久化」接入一个普通的strands.Agent。
三个关键特性决定了这个包的边界:
- 每个默认值都可覆盖:从模型、effort 到会话目录,所有默认值都通过
create_harness()的关键字参数暴露; - 返回值是普通
Agent:调用者拿到的是标准的strands.Agent实例,构造之后仍可继续修改、扩展或替换 harness 组装好的任何部分; - 纯库,无 CLI:
strands终端命令位于strands-cli/(TypeScript),本包不提供命令行入口。
从源码结构看,这一「薄」定位直接体现在包内模块划分上——每个文件只承担一个职责:
harness-py/ ├── src/strands_harness/ │ ├── agent.py # create_harness(): 一次调用完成组装的工厂 │ ├── models.py # resolve_model(): "provider/name" -> Model,按 provider 映射 effort(推理)配置 │ ├── prompt.py # HARNESS_CONTRACT + build_system_prompt() │ ├── defaults.py # 默认模型、effort、上下文管理器、工具、会话/skills/记忆目录 │ ├── tools/ # harness 自研内置工具:file_tools.py(读/写/改)、web_fetch.py │ └── plugins/ # 内置功能插件:todos.py、environment.py ├── tests/ # pytest 测试套件(与模块布局一一对应) └── pyproject.toml # 构建配置、依赖、包内工具设置开发环境搭建与质量检查
安装与开发依赖
创建虚拟环境并以开发模式安装(含[dev]额外依赖):
python -m venv .venv && source .venv/bin/activate pip install -e ".[dev]"[dev]额外依赖会拉取可选的模型 provider(OpenAI、Anthropic、Gemini),因此完整测试套件无需额外配置即可运行。从 harness-py/pyproject.toml 可以看到,dev集合中还包含pytest、pytest-asyncio、ruff,以及全部可选 provider(strands-agents[openai,anthropic,gemini,ollama,litellm]),MCP 测试夹具则固定在mcp>=1.23.0,<2.0.0(因为夹具使用 mcp v1 的 FastMCP API,而 SDK 允许的 mcp 2.x 已重命名该 API)。
提交前检查
打开 Pull Request 之前运行三项检查:
ruff format . # 格式化 ruff check . # 代码检查 pytest # 运行测试套件Ruff 的规则集在 harness-py/pyproject.toml 中定义:行宽 120,启用E(pycodestyle 错误)、F(Pyflakes)、I(isort 导入排序)、UP(pyupgrade)、B(bugbear)五组规则。配置是包内独立的,仓库根目录另有一份共享副本;*.md被排除在格式化之外(与 TypeScript 侧 prettier 只检查src/test而不碰 README 的做法对称)。
create_harness():一次调用组装一个完整 Agent
工厂函数create_harness()定义在 harness-py/src/strands_harness/agent.py,是整个包的入口。它只接受关键字参数,签名覆盖了模型、effort、指令、工具、插件、MCP 服务器、内置工具、后台任务、缓存、上下文管理、会话、skills、记忆、内置插件、干预等多个维度,并把任何未识别关键字通过**agent_kwargs原样透传给Agent。
组装流程(源码级)
从create_harness的实现(agent.py)可以看到组装顺序:
setup_telemetry()—— 按OTEL_TRACES_EXPORTER环境变量一次性接线导出器(见下文「遥测」小节);- 归一化
builtin_tools(_normalize_builtin_tools)、session(_session_config)、memory(_memory_config); - 判定
web_search服务方式:"exa"/ 模型原生 / 关闭(_web_search_mode); - 解析模型(
resolve_model),并把system_prompt写入agent_kwargs(除非调用者显式传了system_prompt); - 组装消费方工具 + MCP 服务器加载的工具 + 内置工具;
- 按需挂载 offloader 插件、skills 插件、内置插件(todos/environment);
- 解析记忆管理器(
resolve_memory); - 执行工具名冲突预检(
_check_name_collisions); - 解析后台任务策略(
_resolve_background_tasks),构造Agent并移除沙箱自带工具(_drop_sandbox_tools),返回。
返回值与显式优先
返回的Agent是标准 SDK 对象,可继续修改。create_harness(**agent_kwargs)会把未识别的关键字直接透传给Agent,且显式值永远优先于其对应的 harness 默认值——例如传入session_manager、memory_manager或system_prompt时,这些显式值胜出。这是该包的核心约定之一,扩展新选项时须保持。
模型参数(model、effort)
model接受四类值:
Model或ModelRouter实例(原样使用);"provider/name"字符串,如"anthropic/claude-fable-5";- 裸的 Bedrock 模型 id(自动归属
bedrockprovider); None,使用 harness 默认模型bedrock/global.anthropic.claude-opus-5(见 harness-py/src/strands_harness/defaults.py)。
effort(推理强度)默认"auto",可取"off"、"minimal"、"low"、"medium"、"high"、"xhigh"、"max"。它在 harness-py/src/strands_harness/models.py 中被映射到各 provider 自己的请求字段,并在 harness 内做本地校验——不支持的级别在 harness 就报错,而不是等下游请求失败:
- Anthropic 系列(direct 与 Bedrock 上)映射为 thinking 块(adaptive/extended),
_CLAUDE_MAX_TOKENS按型号家族钳制max_tokens(如claude-opus-128k、claude-haiku-64k,_CLAUDE_MAX_TOKENS_BY_VERSION对 4-5/4.5 版本固定 64k); - OpenAI(Responses API)映射为
params["reasoning"] = {"effort": ...},级别集为minimal/low/medium/high/xhigh/none; - Gemini 映射为
thinking_config.thinking_level; - Bedrock 按模型家族细分(GPT-5.6/6-astra、gpt-oss、qwen、xai 各有独立级别集,见
_BEDROCK_GPT_LEVELS等); - 无推理级别集的 provider(如 ollama)只接受
auto与off,否则抛错。
注意:当model是Model/ModelRouter实例时,非"auto"的effort会被忽略并记录警告(应在实例上直接配置推理),因为实例的 provider 未知。
系统提示词(instructions、system_prompt)
harness-py/src/strands_harness/prompt.py 提供HARNESS_CONTRACT(模型无关的行为契约)与build_system_prompt()。契约强调四条行为准则:有足够信息就行动(不重复求证已确立的事实)、先探索再改动(理解上下文与约定后再改)、完成前必须验证(做不到验证就明说)、不可逆/越界操作先确认。instructions是追加在契约之后的领域块(身份、范围、任务策略),context_parts追加在最后(如时间戳、请求级提示)。传入完整system_prompt时instructions被忽略。契约不声明身份或领域,这属于消费方的instructions。
内置工具(builtin_tools)
默认启用集合定义在 defaults.py:
("shell", "read", "write", "edit", "web_fetch", "web_search", "programmatic_tool_caller", "subagent")builtin_tools接受列表或映射两种形态(归一化逻辑在 options.py):
- 列表 = 精确固定:只启用列出的名字,
[]全部关闭; - 映射 = 在默认集合上编辑:
False移除、True添加、配置字典「添加并配置」;"*"键(默认True)是起始集合,写False表示从零开始逐个启用。例如{"subagent": False}是「默认集减去 subagent」,{"*": False, "read": True}是精确固定为只读工具。
各可配置工具的配置键(在 types/agent.py 中定义为*ConfigTypedDict):
| 工具 | 配置键 | 说明 |
|---|---|---|
read | media: bool | 是否把图片/二进制文档作为可视媒体返回,默认取决于模型是否支持媒体块;False时始终以文本描述 |
shell | description: str | 展示给模型的工具描述,省略用 SDK 默认 |
web_fetch | model、transport | model指定摘要模型(Model/ModelRouter实例或"provider/name");transport为"curl"(默认,在 agent 沙箱内执行 curl)或"direct"(从 harness 进程用标准库直连,绕过沙箱) |
programmatic_tool_caller | allowed_tools: list[str] \| None、timeout: float \| None | 限定代码可调用的其他工具名;单次运行的墙钟超时(含工具调用),None不限时 |
subagent | max_depth: int | 子代理可继续委派的层数上限,默认 2 |
web_search三种状态(见 agent.py):
False:关闭;"exa":换成 Exa 托管的搜索工具(任何模型可用;第三方服务会接收查询,无 key 可用,EXA_API_KEY可解除限流;开启时会打警告日志);- 默认/
True:启用模型原生 web 搜索——OpenAI、Anthropic、Google(Gemini)以及 bedrock-mantle 上的 GPT-5/GPT-6 模型支持(见models.py中Provider.web_search标志与_has_web_search对 Mantle 的收窄);Bedrock Converse 与其它 Mantle 模型无此机制,在那些模型上显式点名web_search会抛ValueError。
subagent工具通过build_default_subagent(create_harness, parent_config, ...)构造,子代理是完整的 harness 成员:继承模型、内置工具、内置插件、skills、干预策略与消费方plugins/hooks/tools(可收窄、不可放宽工具集),委派深度有界(DEFAULT_SUBAGENT_MAX_DEPTH = 2),且subagent调用始终在后台运行(_ALWAYS_BACKGROUND_TOOL_NAMES)。
插件(plugins、builtin_plugins)
plugins传入消费方 SDK 插件(先运行),builtin_plugins选择内置功能插件,默认["todos", "environment"]:
- todos(plugins/todos.py):提供
todo_write工具,把结构化任务列表写入agent.state,并通过ContextInjector(everyTurn触发)在每个模型调用前以<system-reminder>形式临时回显列表——注入是瞬态的、永不进入持久历史,因此多步工作中列表始终保持可见; - environment(plugins/environment.py):每次用户轮次前注入平台、当前日期、工作目录、项目
AGENTS.md全文(截断上限 16,000 字符)以及向下两级目录发现的其它AGENTS.md/README.md链接(链接而非内容,保持块小巧)。日期每轮重算,其余发现结果按 agent 记忆化;所有读取都走 agent 的 sandbox 通道(uname -s、pwd),因此对本地、Docker、SSH 沙箱一致有效。_SKIP_DIRS跳过node_modules、dist、build、__pycache__等依赖/构建/VCS 目录。
MCP 服务器(mcp_servers)
接受标准的mcpServers配置:JSON 文件路径或映射本身(扁平{name: {...}}映射,或放在mcpServers键下的映射)。每台服务器的工具被发现并加入工具列表,SDK 管理连接与生命周期。默认按服务器名加前缀(<server>_<tool>)防止冲突;服务器启动失败只产生「无工具」而不使构造失败,需用"continue_on_error": false使失败致命;"prefix": ""可去掉前缀。加载后的 MCP 客户端会作为消费方工具参与名称冲突检查,并会被提供给subagent委派。
会话、skills 与记忆(session、skills、memory)
三者默认全部开启,且都是文件后端:
session(默认True):通过SnapshotSessionManager把运行快照写入./.agent/sessions({"id": ..., "dir": ...}可指定 id 与根目录;id 会被清洗为[a-z0-9_-])。不自动跨运行恢复:无id时每次运行新建会话;要续接,从返回的agent.session_id读出 id 并在下次传入session={"id": ...}。False/None关闭(对话仅存内存,卸载产物进入临时目录);skills(默认True):通过AgentSkills插件做渐进式披露(progressive disclosure)。True在./.agent/skills目录存在时加载之,否则是 no-op;SkillSources(技能目录、父目录、SKILL.md、https://URL 或解析后的Skill)原样透传;AgentSkills实例原样使用;文件系统来源经 agent 沙箱读取;memory(默认True):通过MemoryManager把 Agent 学到的持久事实蒸馏为 markdown 文件(默认./.agent/memory),每轮搜索并注入命中项,独立于会话持久化,跨会话存活。{"dir": ...}移动存储目录,{"stores": [...]}换成自有存储(harness 仍保有注入策略:注入开启、search_memory开启、无add_memory写工具);子代理委派共享只读视图(_ReadOnlyStore包装,见 memory.py)。蒸馏用与web_fetch摘要相同的小模型异步执行(每几轮一次),短运行可能来不及触发——用async with agent:作用域或调用agent.shutdown()(异步代码await agent.shutdown_async())在关闭边界刷盘。
上下文管理与缓存(context_manager、caching)
context_manager默认"auto":接受策略名("auto"/"agentic")、ContextManagerConfig映射(自动转成ContextManager(**config))、ContextManager实例或False/None(关闭)。开启时,大型工具结果还会卸载到磁盘(上下文中保留预览与引用),让 Agent 能在压缩前跑得更久。
caching默认开启(DEFAULT_CACHING = "auto"):Bedrock 与 Anthropic direct 由 harness 设置缓存点并缓存工具定义(CacheConfig(strategy="auto", tools_ttl=True));OpenAI、Gemini(2.5 及更新型号)、bedrock-mantle、litellm 服务端自动缓存。False/None关闭 harness 配置的部分;在不支持的 provider 上显式开启会抛错,对预构建Model实例则警告并忽略(须在实例上配置)。
干预(interventions)与后台任务(background_tasks)
interventions默认None(关闭,所有调用直接执行),interventions.py 用确定性字符串文法(不做内容嗅探)解析:
"ask":每个工具调用都请求批准(HumanInTheLoop(ask=...));"smart":由 SDK 的 LLM 风险分类器标记危险调用;- 任意其它字符串:作为自然语言风险策略,成为分类器的提示词;
- 以
.cedar结尾的路径:加载CedarAuthorization策略(需pip install 'strands-agents[cedar]'); HumanInTheLoop/CedarAuthorization实例或它们的列表:完全自控;同类处理器的名称冲突会在构造期抛出(每种类型一个,Cedar + 一个人工门可共存)。
subagent子代理继承干预策略,无法绕过门禁。background_tasks默认None:模型可为任何兼容工具选择后台执行;subagent始终后台运行;False关闭,或传BackgroundTasksConfig策略控制其它工具、并发、完成与超时。
工具名冲突预检
_check_name_collisions(agent.py)在构造期检查内置工具、消费方tools、插件产出工具、记忆工具四类来源:-/_仅差别的名字视为冲突(与 SDK 工具注册表一致),冲突立即抛ValueError并点名落败来源,而不是让某个工具静默消失。MCP 工具名要等客户端连接后才可知,故跳过预检(但其默认加前缀降低了冲突概率)。
遥测:OTEL 追踪接线
telemetry.py 是 harness 在遥测上的唯一职责:只接线导出器,且仅在要求时。它读取标准OTEL_TRACES_EXPORTER选择器(otlp/console/none,逗号分隔),未设置或为none时完全不做任何事——不遵循 OTEL 规范默认的otlp,避免静默立起指向localhost:4318的导出器拖慢进程退出。端点、头与协议通过常规OTEL_EXPORTER_OTLP_*变量配置。追踪是进程级的(provider 挂在 OpenTelemetry 全局 API 上),因此每个进程最多设置一次(_configured标志),多次构造 Agent 或generalist每调用构造一个 Agent 都不会堆叠重复导出器。
Python 风格约定速览
harness-py/AGENTS.md 列出本包专属约定,与根 AGENTS.md 中的跨包规则(与harness-ts/的公开面一致性、共享默认值、单一系统提示词产物、evergreen 注释规则)互补:
- 导入置于文件顶部,绝不在函数内内联——唯一例外是重的可选依赖必须保持惰性:
models.py的各 provider builder 函数内部导入模型类,保证未安装某 provider extra 时strands-harness仍可安装使用;核心strands依赖(session manager、offloader、skills 插件)始终可用,在agent.py顶部照常导入; - 显式优先透传(explicit-wins passthrough):
create_harness(**agent_kwargs)把未识别关键字直通Agent,显式值优先于对应默认值; - Provider effort 配置:
models.py把统一的一个effort级别映射到各 provider 自己的请求字段并做本地校验,让不支持的级别在 harness 内失败而非下游报错,校验保持在本地; - Ruff 约束样式(行宽 120;
E、F、I、UP、B规则),配置在包内pyproject.toml,仓库根目录有共享副本; - 公开函数带类型注解,包随附
py.typed(py.typed文件存在于 harness-py/src/strands_harness/ 下)。
跨包规则统一在根 AGENTS.md 陈述一次,本包文件只展示 Python 惯用法与 Python 专属规则;当规则同时适用于两个包时,改根文件而非本包文件。
测试体系:与模块布局一一对应
tests/目录镜像src/strands_harness/的模块布局,pyproject.toml中testpaths = ["tests"]、asyncio_mode = "auto"。测试覆盖包括:
- tests/test_agent.py:工厂组装、默认值覆盖、冲突预检等;
- tests/test_config.py、tests/test_models.py、tests/test_prompt.py:配置归一化、模型解析、系统提示词拼接;
- tests/test_interventions.py、tests/test_memory.py、tests/test_telemetry.py:干预文法、记忆解析、遥测环境变量行为;
- tests/plugins/:todos 与 environment 插件的注入行为;
- tests/tools/:文件工具、
web_fetch、web_search、programmatic tool caller 等内置工具(含 echo_mcp_server.py 等 MCP 测试服务器); - tests_integ/:端到端集成测试(如 test_e2e.py),命中真实模型,可用
pip install -e '.[integ]'自足安装后以pytest tests_integ --reruns 2运行(pytest-rerunfailures重试偶发 LLM 偏差)。
小结
harness-py的价值在于把「生产级 Agent 的琐碎组装」收敛为一次调用,同时把每个旋钮都暴露出来。开发者在 harness-py/src/strands_harness/agent.py 的create_harness签名上就能看清全部可配置面;想深入某一机制(原生搜索、thinking 映射、记忆蒸馏、干预文法),对应源码文件都有精确的 docstring 与实现可循。遵循本文的开发命令与约定(pip install -e ".[dev]"+ruff format/check+pytest,以及导入、透传、effort 校验、类型注解五条约定),即可与这个包的维护节奏保持一致。
- 人工智能
- 大模型
- AI Agent
- Agent 框架
- 多智能体
- 工具调用
- MCP 服务
【免费下载链接】harness-sdk
Build an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python & TypeScript - any model, any cloud.
相关推荐
Strands Agents 上手指南:用 create_harness() 构建端到端可控的 AI Agent Harness
Strands Agents 上手指南:用 create_harness 构建端到端可控的 AI Agent Harness 本文以 harness sdk 仓
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务MongoDB 分片集合 $group 下推(Pushdown)行为解析:基于 query_golden_sharding 黄金测试的全面验证
MongoDB 分片集合 $group 下推(Pushdown)行为解析:基于 query_golden_sharding 黄金测试的全面验证 本文以 Mong
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务harness-sdk strands-review 技能全解析:用 Task Reviewer SOP 在本地预演 `/strands review` 的代码审查
harness sdk strands review 技能全解析:用 Task Reviewer SOP 在本地预演 /strands review 的代码审查
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考