
人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务【免费下载链接】harness-sdkBuild an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python TypeScript - any model, any cloud.项目地址https://gitcode.com/GitHub_Trending/sdkpython13/harness-sdk点击查看免费下载本文基于 strands-py/docs/PORTING.md 整理Strands 以 TypeScript SDKstrands-ts为规范canonical实现Python SDKstrands-py以复刻 TypeScript 行为、用地道 Python 表达为移植原则。文章逐条展开该文档定义的构造级映射规则construct-to-construct mappings并辅以strands-py源码与测试中的实际实现佐证帮助你在为 strands-py 贡献功能时准确完成跨语言移植。移植总则TypeScript 是规范Python 是复刻移植的核心立场只有一句话TypeScript SDK 是规范canonical一个移植port就是复现 TypeScript 的行为并以地道的 Python 表达出来。strands-py与strands-ts属于同一仓库下的双实现 SDK见 strands-py 与 strands-ts两者的对外能力、事件模型、工具系统与模型接口必须保持行为一致这正是 PORTING.md 存在的原因。PORTING.md 只收录构造到构造construct-to-construct的映射规则即一个 TypeScript 语法结构应该翻译成哪种 Python 结构至于通用语言惯用法例如循环、异常处理、命名习惯默认读者已经掌握文档不赘述。此外凡是因为 Python或当前代码库限制而不得不做的让步统一收敛在 Workarounds 一节中——这类映射并非自由选择而是受既有代码约束的结果。下面按文档顺序逐条展开。一个 TypeScriptinterface按角色映射为三种 Python 形态之一TypeScript 的interface一个结构往往身兼数职而 Python 用不同的构造表达不同角色。因此映射规则取决于该 interface是拿来干什么的1. 行为契约含方法成员→Protocol如果 interface 只声明了方法、描述一段行为契约就映射为 Python 的Protocol隐式实现不需要显式继承# interface Extractor { extract() } - class Extractor(Protocol): def extract(self) - ...: ...strands-py中大量使用此模式。例如 agent/base.py 中的AgentBase(Protocol)定义了所有 Agent 实现必须满足的最小契约invoke_async、stream_async等types.py 中的ContextStrategy(Protocol)声明了name属性与async def apply(context) - bool方法任何实现了这两个成员的对象都能作为上下文削减策略传入管线无需继承任何基类。2. 任意数据形态纯字段、构造后传递→dataclass如果 interface 只是承载数据字段被构造出来、传来传去映射为dataclass其中readonly字段对应dataclass(frozenTrue)# interface ExtractionResult { readonly text: string; ... } - dataclass(frozenTrue) class ExtractionResult: text: str3. 纯构造配置解构一次用于建对象、不作为整体保留→ 显式__init__参数如果 interface 只是构造参数被解构一次用来创建别的对象之后不再整体保留则不引入任何类型直接写成__init__的显式参数字段变成实例属性。必填字段尤其是必填回调用位置参数可选字段放在裸*,之后强制 keyword-only# interface ContextInjectorConfig { render_content: ...; name?: ...; trigger?: ... } - class ContextInjector: def __init__(self, render_content, *, nameNone, triggerNone): self.render_content render_content self.name name self.trigger trigger这样既避免了为一次性配置创建冗余数据类又通过*,让可选参数无法被位置误传语义与 TypeScript 的 destructuring 可选属性完全对齐。带字符串标签的对象字面量联合成员 → frozen dataclass当一个联合union成员是带字符串标签的 TypeScript 对象字面量时映射为 frozen dataclass标签用非 init 默认字段表示# type Deny { type: deny; reason: string } - dataclass(frozenTrue) class Deny: type: str field(defaultdeny, initFalse) reason: str 关键映射点readonly→frozenTrue字面量type:标签 →field(default..., initFalse)运行时存在该字段但不是构造参数工厂函数function deny(reason): Deny坍缩进构造函数deny(x)变成Deny(reasonx)联合别名直接照搬type X A | B→X A | B下游按标签分发switch (action.type)→isinstance判断isinstance(action, Deny)。这个模式在strands-py的干预intervention系统中得到完整落地。interventions/actions.py 中定义了Proceed、Deny、Guide、Confirm、Transform五个 frozen dataclass每个都带有type: str field(default..., initFalse)标签字段并在文件末尾聚合为联合别名InterventionAction Proceed | Deny | Guide | Confirm | Transformactions.py#L117。分发端同样印证了isinstance取代switch的规则interventions/registry.py 中_apply_before_invocation用一连串if isinstance(action, Deny) / elif isinstance(action, Guide) / elif isinstance(action, Transform) / elif isinstance(action, Proceed)完成事件处置Deny 直接设置event.cancel fDENIED: {action.reason}并短路后续 handler与 actions.py 文档字符串中给出的兼容性矩阵一一对应。tool({...})对象字面量 →tool装饰的函数TypeScript SDK 用tool({...})对象字面量声明工具Python 端则用tool装饰一个函数。对象字面量的每个字段都落到函数的一个特定位置TypeScripttool({...})字段Pythontool函数name: summarize_context函数名def summarize_contextdescription: ...函数 docstringinputSchema: z.object({ keepRecent: z.number().int().optional() })类型化参数keep_recent: int \| None None每个字段的.describe(...)docstring 中对应的Args:条目callback: (input, context) {...}函数体context第二个回调参数tool(contextTrue)加上tool_context: ToolContext参数也就是说声明式 schema 及其描述全部坍缩进函数签名 Google 风格 docstring不再有单独 schema 对象。源码实现印证了这一设计的全部细节。tools/decorator.py 是整个映射的落地处docstring 解析FunctionToolMetadata在构造时用docstring_parser.parse(inspect.getdoc(func))解析 docstringdecorator.py#L109-L114Args:条目被提取为param_descriptions字典描述即 description_extract_description_from_docstring会剔除Args:段、保留Returns:/Raises:/Examples:等段作为工具描述decorator.py#L235-L261签名即 inputSchema_create_input_model遍历函数签名把类型注解含Annotated元数据、处理 PEP 563 字符串注解与默认值合成为 Pydantic 模型作为输入校验 schemadecorator.py#L192-L233context 注入tool(contextTrue)默认把tool_context作为注入参数名tool(contextmy_name)可改名decorator.py#L822-L829。_validate_signature会在函数签名中出现ToolContext却未声明context时抛出ValueError(tool(context) must be set if passing in ToolContext param)decorator.py#L177-L190_is_special_parameter则把self、cls、agent与配置的 context 参数排除出输入校验模型decorator.py#L434-L454。一个同时演示签名映射与 context 映射的官方示例decorator.py#L813-L819tool(namecustom_tool, descriptionA tool with a custom name and description, contextTrue) def my_tool(name: str, count: int 1, tool_context: ToolContext) - str: tool_id tool_context[tool_use][toolUseId] return fProcessed {name} {count} times with tool ID {tool_id}ToolContext与ToolSpec类型定义位于 types/tools.pyToolSpec含name、description、inputSchema、可选outputSchema与 MCPannotations这些键与 TypeScript 侧一致。相应的校验测试可见 tests/strands/tools/test_decorator.py例如tool(context)缺失即报错的用例在 test_decorator.py#L1839。外部协议线键wire keys原样保留不做大小写转换凡是属于外部 API 或协议、不属于 SDK 自有表面的键必须逐字符复制不能重新改大小写re-case。max_tokens、input_tokens、tool_use、stop_reason都是第三方拼写照抄即可。这条规则同样延伸到在 docstring 与注释中提及这些键的文本——注释里写键名时也要保持第三方拼写便于按协议文档检索与对照。这一点在源码中有直接体现strands-py的工具类型定义文件开头明确写着These types are modeled after the Bedrock APItypes/tools.py#L1-L6因此toolUseId、inputTokens等 Bedrock 拼写保留原样模型层返回的流式事件与停止原因也使用stop_reason这类第三方拼写。Workarounds兼容性让步与桥接方案以下两条是受 Python或现有代码库限制而做出的让步——与前面的规则不同如果是从头移植你不会这样设计但既然要复用既有代码与生态就只能这样桥接。Python 表面是异步的用工作线程桥接仅同步客户端strands-py对外暴露的方法始终是异步生成器async def stream(...) - AsyncGenerator[...]。底层客户端具体怎么驱动取决于它提供什么能力有异步客户端可用例如 Anthropic 的AsyncAnthropic直接使用配合async with/async for。当 TypeScript API 同时暴露同步与异步两种形态时Python 移植取异步形态。源码证据models/anthropic.py 用anthropic.AsyncAnthropic(**client_args)构造客户端stream()内部async with self.client.messages.stream(**request) as stream:加async for event in stream:消费事件anthropic.py#L936-L944。仅有同步客户端boto3 没有异步客户端保持异步生成器的表面但把阻塞调用放进asyncio.to_thread通过asyncio.Queue加一个回调把事件回传给事件循环并用哨兵值None表示结束。阻塞工作绝不能跑在事件循环线程上。这条规则在 Bedrock 模型中有完整实现。models/bedrock.py 中工作线程侧_stream在独立线程中调用 boto3 的converse_stream/converse注释明确说明This method operates in a separate thread to avoid blocking the async event loop见 bedrock.py#L1419-L1422桥接侧stream()中定义callback(event)用loop.call_soon_threadsafe(queue.put_nowait, event)把事件从工作线程安全投递到事件循环bedrock.py#L1362-L1368asyncio.Queue[StreamEvent | None]承载事件None即结束哨兵消费侧_next_stream_event负责取下一个事件若取消先到则放弃等待并用asyncio.wait(..., return_whenFIRST_COMPLETED)在queue.get()与取消轮询 Future 之间竞争bedrock.py#L99-L133主循环读到None即退出bedrock.py#L1387-L1401。同一桥接手法也用在其他同步后端上例如 storage/s3_storage.py 中put_object/get_object/delete_object全部经asyncio.to_thread包装。共享类型按目标侧既有名称查找绝不改名异常类、内容块类型、流事件类型在两侧各自集中在中央 types 模块里。当源码引用其中一个时使用目标侧已有的名称不要转换标识符。没有统一的后缀规则ProviderTokenCountError在两种语言中保持这个精确名称而ContextWindowOverflowError在 Python 侧叫ContextWindowOverflowException——因为各侧本来就各自这样拼写。逐个对照实际情况解析而不是机械地套用Error一律改名Exception的规则。这与仓库现状完全吻合TypeScript 侧中央错误模块是 strands-ts/src/errors.ts其中export class ProviderTokenCountErrorerrors.ts#L181与export class ContextWindowOverflowErrorerrors.ts#L39并存Python 侧中央错误模块是 strands-py/src/strands/types/exceptions.pyProviderTokenCountError同名保留exceptions.py#L89而上下文溢出异常拼写为ContextWindowOverflowExceptionexceptions.py#L41。即便同名的异常其语义也保持对齐ProviderTokenCountError在两侧都作为模型提供方原生 token 计数 API 失败的内部控制流使用捕获后回退到启发式估算。Python 侧 Bedrock 实现中raise ProviderTokenCountError(Bedrock count_tokens returned None for inputTokens)后由except Exception兜底并return await super().count_tokens(...)回退估算bedrock.py#L1287-L1324与 errors.ts#L175-L186 的文档注释所述机制一一对应。移植对照速查表与落地清单TypeScript 结构Python 目标结构strands-py 落地位置示例interface行为契约Protocol隐式实现agent/base.py、_context_manager/types.pyinterface数据形态dataclassfrozenTrue对应readonlyinterventions/actions.pyinterface纯构造配置显式__init__参数可选参数置于*,后—带标签对象字面量联合成员frozen dataclass field(initFalse)标签字段interventions/actions.pyDenyswitch (x.type)分发isinstance(x, ...)判断interventions/registry.pytool({...})对象字面量tool装饰函数docstring 即 schematools/decorator.py外部协议 wire keys逐字符照抄不改大小写types/tools.py仅同步客户端asyncio.to_threadasyncio.Queue 回调 None哨兵models/bedrock.py共享类型名按目标侧既有名称解析不统一改名types/exceptions.py 对照 strands-ts/src/errors.ts移植一份功能时可以按此清单逐项核对先判定每个 interface 的角色选对 Python 形态再处理联合成员与工具对象随后把 wire keys 原样保真最后检查是否命中两条 Workarounds同步客户端桥接、共享类型名称解析。除此之外参考 STYLE_GUIDE.md 与 TESTING.md 保持代码风格与测试规范与现有strands-py模块一致即可让移植结果既行为等价、又读起来像原生 Python。赞分享人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务【免费下载链接】harness-sdkBuild an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python TypeScript - any model, any cloud.项目地址https://gitcode.com/GitHub_Trending/sdkpython13/harness-sdk点击查看免费下载相关推荐Strands TypeScript SDK 依赖治理指南peerDependencies 边界规则与 package-lock 可复现构建Strands TypeScript SDK 依赖治理指南peerDependencies 边界规则与 package lock 可复现构建 导读 本文基于人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务Strands TypeScript SDK 开发指南从编码规范到模型 Provider 的完整实践Strands TypeScript SDK 开发指南从编码规范到模型 Provider 的完整实践 本文是面向在 Strands Agents 仓库中开发人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务Strands SDK 模型路由Model Routing设计解析从设计文档到 Python SDK 落地实现Strands SDK 模型路由Model Routing设计解析从设计文档到 Python SDK 落地实现 模型路由Model Routing是人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务上一篇如何永久备份微信聊天记录免费开源工具WeChatMsg终极使用指南下一篇CANN/catlass INT8转FP16反量化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考