- 人工智能
- 大模型
- 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.
导读
本文基于开源仓库中的 Python SDK 变更记录 python/v0.1.5(发布于 2025-05-26,包名strands-agents),逐条拆解该版本的核心变更:动态 System Prompt 覆盖、推理(reasoning)文本进入回调处理器、SlidingWindowConversationManager的重大升级、事件循环重构、Agent.stream_async()的 OpenTelemetry Span 生命周期修复,以及 OpenAI 模型请求格式化的兼容性修复。读完本文,你将掌握如何在生产代码中按调用覆盖系统提示词、消费流式推理文本、精细调优滑窗上下文管理策略,并理解这些能力背后的源码实现与测试验证路径。
一、版本概览:v0.1.5 的定位与变更全景
python/v0.1.5是strands-agentsPython SDK 在 2025-05-26 发布的一个功能与稳定性并重的版本。根据 pyproject.toml 的配置,包名为strands-agents,版本号由 git tag 动态生成(dynamic = ["version"]),且 hatch 的tag_regex = "^python/v(?P<version>.+)$"与变更日志中的tag: python/v0.1.5一一对应——即该版本对应仓库中的python/v0.1.5标签。
本版本共包含 12 条变更记录,按类型归纳如下:
| 类型 | 数量 | 涉及范围 |
|---|---|---|
| feat(新功能) | 3 | handlers(推理文本回调)、动态 System Prompt 覆盖、SlidingWindowConversationManager 更新 |
| fix(修复) | 3 | OpenAI 模型 tool arguments、README logo 配色、stream_async()agent span 生命周期 |
| docs(文档) | 4 | README 徽章、logo、标题规范化、仓库链接 |
| other(其他) | 2 | 事件循环重构、版本发布 |
其中三项新功能(PR 108、PR 109、PR 120)分别由三位新贡献者Shubhamraut01、josephgultekin、Unshure提交,是本次版本的重点。下面按功能主题深入展开。
二、按调用覆盖 System Prompt:动态系统提示词能力(PR 108)
2.1 使用方式:从"构造时固定"到"调用时动态"
Agent在构造时通过system_prompt参数设定模型行为基线,这属于常规用法。v0.1.5 引入的"动态 System Prompt 覆盖功能"(PR 108)允许在每次调用agent(...)/agent.stream_async(...)时临时传入system_prompt,覆盖 Agent 实例的默认提示词,从而实现同一 Agent 实例在不同任务间切换角色或指令。
以测试 test_agent.py 中的验证逻辑为参照,一次典型的动态覆盖调用形如:
agent( "test message", system_prompt="Override system prompt", # 本次调用临时覆盖默认 system_prompt some_value="a_value", )测试断言的关键点在于:system_prompt会进入本次调用的invocation_state,事件循环在发起模型请求时读取的是覆盖后的值(invocation_state["system_prompt"] == override_system_prompt),而非 Agent 构造时的默认值。这意味着动态覆盖是按调用生效、不污染实例状态的——下一次不传system_prompt时,仍回落到默认提示词。
2.2 源码实现:setter 与 invocation_state 的配合
从源码结构看,Agent类对系统提示词的管理位于 agent.py:
system_prompt是只读属性,返回split_system_prompt(self._system_prompt_content)[0],保证与既有期望字符串接口的代码兼容;system_promptsetter 接受str | list[SystemContentBlock] | None,内部统一转换为_system_prompt_content内容块列表(字符串会被包装为[{"text": ...}]);system_prompt_content属性则返回内容块列表本身,供需要多模态系统块的模型适配层直接消费。
配套测试覆盖了三种 setter 场景:字符串赋值、内容块列表赋值、置None清空(见 test_agent.py)。动态覆盖正是复用这套 setter 语义,在调用路径上把kwargs/invocation_state中的system_prompt透传到事件循环,最终由_start_agent_trace_span(agent.py)连同system_prompt_content一起写入追踪 Span 属性,保证覆盖后的提示词在可观测链路中可追溯。
2.3 典型应用场景
动态覆盖最直接的落地场景包括:
- 多租户/多角色:同一个 Agent 实例服务不同业务域,按请求切换专家角色提示词;
- A/B 提示词实验:同一任务批量对比不同 System Prompt 的回复质量,无需重建实例;
- 会话级定制:结合
invocation_state透传的其他上下文(如用户画像、地区配置),在运行时拼装个性化指令。
三、推理文本进入回调处理器:Reasoning 的可观测与终端呈现(PR 109)
3.1 变更内容
PR 109("add reasoning text to callback handler and related tests")让模型输出的推理内容(reasoning text)与签名(signature)能够流入回调事件。此前推理内容只在模型流式层内部流转,外部回调处理器无法感知;v0.1.5 之后,回调事件中新增了reasoning、reasoningText、reasoning_signature字段。
3.2 源码与测试双重佐证
在 callback_handler.py 中,PrintingCallbackHandler.__call__显式读取reasoningText并在终端原样打印:
reasoningText = kwargs.get("reasoningText", False) data = kwargs.get("data", "") complete = kwargs.get("complete", False) ... if reasoningText: print(reasoningText, end="")配套测试 test_agent.py 精确验证了回调事件携带的字段组合:
unittest.mock.call( agent=agent, delta={"reasoningContent": {"text": "value"}}, ... reasoning=True, reasoningText="value", request_state={}, ) unittest.mock.call( agent=agent, delta={"reasoningContent": {"signature": "value"}}, ... reasoning=True, reasoning_signature="value", request_state={}, )同时,最终AgentResult.message.content中的推理块以{"reasoningContent": {"reasoningText": {"text": ..., "signature": ...}}}形式完整保留(test_agent.py),说明推理内容不仅在流式过程中可被回调消费,还会随结果消息持久化。
3.3 实战价值
对于部署了带推理能力模型(如 Anthropic 系 reasoning 模型)的 Agent 应用,此变更意味着:
- 终端交互:
PrintingCallbackHandler可在输出最终答案前先行呈现"思考过程",提升可解释性; - 自定义回调:自研
CompositeCallbackHandler(同文件 callback_handler.py)可将reasoningText分流到日志、审计或分析管道,实现推理链的合规留存。
四、SlidingWindowConversationManager 升级:滑窗、主动压缩与按轮管理(PR 120)
PR 120 对滑动窗口会话管理器做了系统性增强,是 v0.1.5 中与长对话场景最相关的改动。实现位于 sliding_window_conversation_manager.py。
4.1 构造参数全解
SlidingWindowConversationManager( window_size: int = 40, should_truncate_results: bool = True, *, per_turn: bool | int = False, pin_first: int | None = None, proactive_compression: bool | ProactiveCompressionConfig | None = None, )| 参数 | 类型/默认值 | 含义与取值说明 |
|---|---|---|
window_size | int,默认40 | 历史消息窗口上限。超过该值才触发缩减;设为0表示每次缩减时清除全部非固定消息。负数会抛ValueError |
should_truncate_results | bool,默认True | 是否对超大工具结果做部分截断(仅响应式溢出恢复路径生效) |
per_turn | bool \| int,默认False | 在 Agent 循环内部主动执行消息管理的时机:False仅在循环结束(finally 块)管理;True每次模型调用前管理;N(正整数)每 N 次模型调用管理一次 |
pin_first | int \| None,默认None | 固定对话开头 N 条消息,缩减时受保护不被驱逐 |
proactive_compression | bool \| ProactiveCompressionConfig \| None,默认None | 模型调用前的主动压缩:True在上下文窗口使用率达 70% 时压缩;{"compression_threshold": float}自定义阈值(0, 1];False/None关闭,仅保留响应式溢出恢复 |
4.2 工具结果的智能截断
当上下文溢出(响应式路径,e非空)时,管理器优先从最旧的、含工具结果的消息开始截断(_find_oldest_message_with_tool_results),以最大化保留近期相关上下文。截断策略(_truncate_tool_results)细节:
- 文本块保留首尾各 200 字符(
_PRESERVE_CHARS = 200),中间替换为... [truncated: N chars removed] ...说明性占位; - 工具结果中嵌套的图片块被替换为文本占位符,格式如
[image: <media_type>, <bytes> bytes],避免图片持续占据上下文预算; - 已截断过的文本带
... [truncated:标记,不会二次截断。
4.3 合法的裁剪边界:trim point 逻辑
缩减不是简单"砍掉最旧 N 条",而是通过find_valid_trim_point寻找合法边界,保证裁剪后消息序列对模型提供商仍合法(sliding_window_conversation_manager.py):
- 边界必须以user 消息开头(大多数模型提供商的要求);
- 不能以孤立的
toolResult开头; - 不能以
toolUse开头,除非其toolResult紧随其后。
值得注意的 Python 特有增强:_find_tool_pair_trim_point提供了兜底路径——当找不到纯 user 消息边界时,回退到assistant(toolUse) + user(toolResult)完整配对边界,因为提供商将完整 toolUse/toolResult 配对视为合法的对话延续。这使得工具密集型对话(如浏览器自动化、多轮检索)也能被正常裁剪,而不会被"无合法边界"卡死。当确实无法缩减时:响应式路径抛ContextWindowOverflowException,主动/例行路径仅记录 warning 并返回。
4.4 per_turn:循环内的主动上下文管理
per_turn是本次升级针对"长循环 Agent"场景的关键能力。其钩子注册在register_hooks(sliding_window_conversation_manager.py),通过监听BeforeModelCallEvent实现;回调内部(_on_before_model_call)维护_model_call_count并按配置决定是否立即执行apply_management。
测试 test_conversation_manager.py 系统验证了该行为:
per_turn=False:6 次模型调用期间不触发管理,仅在 finally 块执行一次;per_turn=True:每次模型调用前都管理;per_turn=2:第 2、4、6 次模型调用前各管理一次,另加循环结束一次;per_turn=0或负数抛ValueError。
官方建议(源码 docstring):若 Agent 在循环中执行大量工具操作(如带频繁截图的网页浏览),应启用per_turn=True主动管理历史,防止循环变慢;若性能仍有压力,可调整为per_turn=5之类的频率。
4.5 会话状态持久化
管理器状态支持跨会话恢复:get_state()将model_call_count纳入状态字典(sliding_window_conversation_manager.py),restore_from_session()在恢复时还原计数(同文件 L137-L148),保证per_turn的调度节奏在会话续接后不中断。
五、事件循环重构(PR 106)与 stream_async 的 Span 修复(PR 119)
5.1 "Rise of the Phoenix":事件循环重构
PR 106("🔥🕊️ Rise of the Phoenix: Event Loop Refactor")对 SDK 的核心执行引擎做了重构。当前事件循环实现位于 event_loop.py,职责被清晰划分为多个函数:
event_loop_cycle/recurse_event_loop:单轮循环与递归式循环入口;_handle_model_execution:模型调用及流式事件处理;_handle_tool_execution:工具调用与结果回填;_stop_for_interrupts:中断(interrupt)收集与终止决策;_check_limits:按轮次/输出 token/总 token 的预算检查。
从模块结构看,重构后的事件循环将模型执行、工具执行、中断处理解耦为独立阶段,并通过BeforeModelCallEvent/AfterModelCallEvent/BeforeToolsEvent/AfterToolsEvent等钩子对外暴露插桩点,为上文提到的per_turn主动管理、动态 System Prompt 覆盖等能力提供了统一的执行期介入机制。
5.2 agent span 生命周期修复
PR 119 修复了Agent.stream_async()场景下 agent span 的起止问题。在 agent.py 的stream_async实现中可以看到修复后的生命周期编排:
- 输入消息转换完成后立即
self.trace_span = self._start_agent_trace_span(messages)(L1386),并在with trace_api.use_span(self.trace_span)作用域内驱动整个事件循环; - 正常结束时
self._end_agent_trace_span(response=result)(L1419); - 异常路径
self._end_agent_trace_span(error=e)(L1424); - 取消路径通过
end_span_with_cancellation结束(agent.py)。
_start_agent_trace_span(agent.py)会携带agent_name、model_id、tools、system_prompt、system_prompt_content、trace_attributes与完整工具配置,形成包含系统提示词与工具清单的 agent 根 Span;底层实现在 tracer.py(start_agent_span/end_agent_span)。修复后,流式调用全程(含流式结束后的AgentResultEvent回调)都落在正确的 agent span 内,OTLP/console 导出的追踪数据不再出现"有结果无 span"或"span 提前闭合"的错位。
5.3 对可观测性的影响
这一组合(事件循环重构 + span 修复)意味着:使用Agent.stream_async()构建流式应用的团队,可以在 Jaeger、Grafana 等 OTel 后端获得完整的 agent → 模型调用 → 工具调用 span 树,并配合MetricsClient的 usage/metrics 统计定位长会话中的上下文膨胀点。
六、OpenAI 模型适配修复:tool arguments 边界处理(PR 97)
PR 97("models - openai - argument none")属于模型适配层的兼容性修复。从当前源码 openai.py 看,OpenAI 请求格式化通过format_request_message_tool_call将toolUse的输入序列化为工具调用参数:
"arguments": json.dumps(tool_use["input"], ensure_ascii=False),该修复针对的正是arguments可能为空的边界场景——变更日志记录为argument none。可以推断,修复确保了当模型返回的 tool use 缺少 input 时,请求序列化不会产生非法结构(例如空字符串或None被错误序列化),从而维持 OpenAI API 兼容性。配套消息组装逻辑在 openai.py:仅当存在toolUse内容块时才生成tool_calls字段,且图片块会被从工具消息中拆分为独立 user 消息(_split_tool_message_images,L446-L455),满足 OpenAI 对图片必须位于 user 角色的约束。
七、元数据与文档更新(PR 100–105)
v0.1.5 还包含一组 README 层面的变更(PR 100/101/102/104/105):新增 open PRs 徽章、链接到 samples 示例仓库、将 "Docs" 统一为 "Documentation"、加入 logo,并将 logo 改为跟随用户配色偏好自动切换明暗的方案(先尝试暗色 logo,最终采用随prefers-color-scheme自动变色的实现)。这类变更虽不涉及运行时行为,但对开源项目的可发现性与 README 的可读性有实际价值,也反映了发布流程对仓库门面的一致化治理。
八、升级与验证:让 v0.1.5 落地
8.1 安装
pip install strands-agents==0.1.5包元数据见 pyproject.toml(name = "strands-agents",版本由 git tagpython/v0.1.5动态解析)。
8.2 行为验证清单
升级后建议重点回归以下路径(仓库自带测试可直接运行验证):
- 动态 System Prompt:
tests/strands/agent/test_agent.py中test_agent__call__with_invocation_state类用例,断言覆盖值进入invocation_state["system_prompt"]; - 推理回调:同文件 L812-L833 的回调事件断言,验证
reasoningText/reasoning_signature字段; - 滑窗管理:
tests/strands/agent/test_conversation_manager.py中test_per_turn_*系列与test_sliding_window_proactive_compression_skips_tool_result_truncation,覆盖参数校验、钩子注册、按轮调度与主动压缩路径。
8.3 升级注意点
per_turn参数有严格的取值约束(0与负整数抛ValueError),迁移旧配置时需确认取值合法;- 若依赖回调事件结构,需注意新增的
reasoning相关字段是增量字段,不破坏既有data/complete/tool_use语义; - 事件循环重构后,若曾自定义中间件或深度依赖内部事件顺序,建议以 event_loop.py 的公开阶段函数为准重新对齐。
结语
v0.1.5 是一次"功能增量 + 引擎加固"并行的版本:动态 System Prompt 覆盖与推理回调让 Agent 的输入与输出都更加可编程;滑动窗口管理器的per_turn、pin_first、proactive_compression三件套为长会话场景提供了可调优的上下文治理方案;事件循环重构与 span 修复则夯实了流式场景下的可观测性底座。对正在用strands-agents构建生产级 Agent 的团队而言,本文涉及的每个能力点都能在仓库源码(agent.py、sliding_window_conversation_manager.py、callback_handler.py、event_loop.py)与对应测试中找到可直接复用的实现范式。
- 人工智能
- 大模型
- 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会话管理如何通过滑动窗口与摘要技术优化AI对话
终极指南:Strands Agents会话管理如何通过滑动窗口与摘要技术优化AI对话 Strands Agents是GitHub加速计划下的sdk python
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务如何用Akagi在30天内从麻将新手晋升为战略高手?终极AI辅助指南 🀄️
如何用Akagi在30天内从麻将新手晋升为战略高手?终极AI辅助指南 🀄️ 你是否曾在雀魂对局中感到迷茫,看着手中的牌无从下手?或者明明感觉能胡牌,却总是差那
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务windows-rs 中的 Windows Window:轻量级 Win32 窗口创建与消息循环实战指南
windows rs 中的 Windows Window:轻量级 Win32 窗口创建与消息循环实战指南 导读 windows window 是 windows
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考