news 2026/9/10 21:39:20

Composio Examples Harness 实战指南:基于实时后端与调用轨迹的客户端一致性校验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Composio Examples Harness 实战指南:基于实时后端与调用轨迹的客户端一致性校验

Composio Examples Harness 实战指南:基于实时后端与调用轨迹的客户端一致性校验

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

导读

harness/是 Composio 仓库中一套面向"示例(examples)"的回归校验工具链:它把examples-manifest.json中登记的全部可运行入口(entrypoint)跑在一个实时 Composio 后端上,逐条记录每个入口发出的每一次后端调用,然后对同一组入口的两轮运行做逐调用(call-for-call)比对,从而在升级客户端(TypeScript / Python SDK)前后量化验证"行为没有发生变化"。本文以 harness/README.md 为主线,结合 harness/run.mjs、harness/parity.mjs、harness/backend-url.mjs、harness/trace/register.mjs、harness/trace-py/sitecustomize.py 与 scripts/examples-provision.mjs 的源码实现,带你完整掌握:如何选择后端、如何做一次客户端升级的前后一致性(parity)比对、如何安全地准备测试数据,以及如何用自检命令验证 harness 本身是可信的。

一、整体架构:一次"可复现"的示例回归

harness 的核心理念是把示例跑成可比较的"信号源"。整个体系由四个角色协作:

组件文件职责
运行器 Runnerharness/run.mjs遍历examples-manifest.json中登记的入口,逐个运行,产出results.jsonl与每个入口独立的 trace 文件
比较器 Comparatorharness/parity.mjs对两个运行目录做逐入口、逐调用比对,输出 parity 报告
追踪器 Tracerharness/trace/register.mjs(TS/Node fetch)、harness/trace-py/sitecustomize.py(Python httpx)由运行器注入进程,记录每个后端请求的(method, path-template)与状态分组
数据准备 Provisionerscripts/examples-provision.mjs为 tier-2/3 入口准备 auth configs 与 connected accounts,并以COMPOSIO_EXAMPLES_*环境变量形式输出

1.1 入口清单(manifest)

所有可运行入口登记在根目录的 examples-manifest.json 中,目前共 92 个入口,按 tier 分级:

  • tier 1(36 个):无人值守,只要进程以 0 退出即视为通过;
  • tier 2(34 个):依赖 provisioner 预先准备好的认证状态(auth configs / connected accounts);
  • tier 3(13 个):有界运行——输出命中 manifest 里登记的 readiness 正则即判通过并终止进程;
  • tier X(9 个):排除项,不参与运行。

每个入口声明了idlangts/py)、pkg(TS 包名)、file(入口文件)、tier、运行所需的环境变量与ids(来自 provisioner 的COMPOSIO_EXAMPLES_*导出)、timeoutSec等字段。运行器在 loadManifest 中会先做字段完整性校验(例如 tier-3 入口必须有readiness正则),防止坏数据流入运行。

1.2 运行产物

一次 sweep 的全部产物落在.artifacts/examples-parity/<run-id>/目录下,run-id 形如20260910-013000-xxxxxx-baseline

  • results.jsonl:逐行记录每个入口的运行结果(idtierstatus(green/red/skipped)、exittimedOutreadinessMatcheddurationMstraceFile相对路径等);
  • traces/<entry-id>.jsonl:每个入口一份调用轨迹,其中 entry-id 中的/会被替换为__(见 runEntry/buildEnv 与 parity.mjs 的 tracePairs);
  • summary.json:本轮总览(runId、client、llm 模式、baseUrl、green/red/skipped 计数)。

二、后端选择:COMPOSIO_BASE_URL的严格约束

COMPOSIO_BASE_URL决定示例跑在哪个后端,默认是 staging(https://staging-backend.composio.dev)。关键约束是:只接受"裸 https 根"——携带路径、查询串、fragment 或内嵌凭据的 URL 一律拒绝。原因有二:追踪器要把后端 host 钉死用于过滤记录;provisioner 会在根上追加自己的 API 路径。校验逻辑见 harness/backend-url.mjs:

const isBareHttpsRoot = url.protocol === 'https:' && url.pathname === '/' && !url.search && !url.hash && !url.username && !url.password; if (!isBareHttpsRoot) { throw new Error(`refusing malformed COMPOSIO_BASE_URL: ${value}`); } return url.origin;

Python 侧在 sitecustomize.py 中用urlsplit做了完全一致的结构检查,不满足条件时直接os._exit(78)拒绝启动。.github/workflows/examples-live.yml中 CI 显式设置 staging,因此默认值的变化不会影响 CI 行为。

2.1 安全前提:只跑在"可丢弃"的项目上

COMPOSIO_BASE_URL指向一个你愿意让示例触碰数据的项目。尤其注意scripts/examples-provision.mjs --gc会跨整个项目删除示例遗留的、超过 24 小时的资源——永远不要对一个你在意的项目运行它(下文 §4.3 详解删除边界)。此外,出站邮件 denylist 由追踪器强制实施且不可按运行覆盖run.mjs在 buildEnv 中显式删除COMPOSIO_TOOL_DENYLIST环境变量),而--llm mock会把模型流量拉到本地aimock服务器上,保证没有任何 agent 能"决定去写点什么"。

三、追踪器:如何把"行为"变成可比较的信号

parity 比较的对象是追踪器记录的(method, path-template)对。两条追踪器都由运行器注入,示例代码本身从不引用COMPOSIO_TRACE_FILE(lint 强制):

3.1 Node/TS 侧:fetch 包装

harness/trace/register.mjs 通过NODE_OPTIONS=--import注入(见 buildEnv),替换全局fetch

  • ID 归一化:路径段若匹配ID_SEG(如ca_ac_ti_tr_sess_前缀、UUID、纯数字等)会被模板化为{id},使两次运行中不同的资源 ID 不影响比对;
  • 状态分组:响应状态码折叠为2xx/3xx/4xx/5xx,网络异常记为ERR
  • 出站邮件防护:命中默认 denylist(GMAIL_SEND|GMAIL_REPLY|SEND_EMAIL|SEND_DRAFT|OUTLOOK[A-Z_]*SEND)的后端工具执行在传输层直接抛错并记录"s":"BLOCKED",绝不转发给后端;
  • LLM 流量:对 openai/anthropic/generativelanguage 三个 host 只记{llm: hostname}标记,不记路径。

3.2 Python 侧:httpx 钩子

harness/trace-py/sitecustomize.py 通过PYTHONPATHsitecustomize钩子加载(见 buildEnv),猴子补丁httpx.Client.sendhttpx.AsyncClient.send,同步实现模板化、状态分组、denylist 防护与 LLM 标记。整个追踪逻辑包在try/except里——追踪绝不允许拖垮示例本身

3.3 trace 的判定意义

追踪记录被 parity.mjs 直接消费,也在 sweep 中用来判定"出站邮件防护是否被触发":只要 trace 中出现"s":"BLOCKED",该入口无论退出码如何都判红(runPool 中的 blocked 检查)——因为"捕获到拒绝然后继续执行"不能被算作有效覆盖。

四、一次完整的客户端升级比对(parity run)

parity run = 对同一组 entry id 做两轮 sweep(变更前后各一轮),再按 trace 中的(method, path-template)对逐调用比较。

4.1 标准流程

# 1. 为你要 sweep 的项目准备 id(capture 之后立即 eval—— # 一次失败的 provision 运行绝不能被静默吞掉) out=$(node scripts/examples-provision.mjs) && eval "$out" # 2. 基线:使用基线分支 checkout 上的钉死客户端 node harness/run.mjs sweep --client baseline --lang py --llm mock --ids "$IDS" # 3. 候选:换入候选客户端后跑同一组入口 COMPOSIO_CLIENT_WHEEL=/abs/path/composio_client-<version>-py3-none-any.whl \ node harness/run.mjs sweep --client candidate --lang py --llm mock --ids "$IDS" # 4. 比对两个运行目录 node harness/parity.mjs <baseline-run-dir> <candidate-run-dir>

务必显式传--ids,而不要依赖默认选择:这样即使两个 checkout 对 manifest 的认知不一致,两边也跑完全相同的集合。

4.2 候选客户端来自本地产物,而非版本声明

COMPOSIO_CLIENT_TARBALL(TypeScript)与COMPOSIO_CLIENT_WHEEL(Python)指向本地构建产物。Python wheel 用如下命令获取:

pip download composio-client==<version> --no-deps

两个 swap 都有保护性设计(见 run.mjs 的 candidate 逻辑):

  • 守卫:如果项目实际解析到的客户端版本没变,sweep 直接中止(TS 侧校验解析出的@composio/client版本,Python 侧通过importlib.metadata.version("composio-client")校验);
  • 自动恢复:sweep 结束后,被改动的文件(pnpm-workspace.yamlpnpm-lock.yamlpython/pyproject.tomluv.lock)都会恢复为运行前的快照(snapshotTsBaseline/snapshotPyBaseline+restore*)。

Python 侧还有一个细节:候选 sweep 期间运行器会临时去掉python/pyproject.toml里精确的composio-client==钉版(relaxPyClientPin)。原因是多个入口通过pyWith安装本地./python项目,而 uv 无法同时满足"钉版 + 候选 wheel"——不去掉钉版,这些入口会因打包解析失败而静默变红,悄悄缩小比较范围。

4.3 数据准备与清理(provisioner)

scripts/examples-provision.mjs 是一个幂等的预置检查:

  • 为 tier-2/3 入口验证/创建examples-<slug>命名的 auth configs(OAuth 类用use_composio_managed_auth,serpapi 这类 API-key 工具用use_custom_auth,其存储值是刻意伪造的占位符而非真实密钥);
  • COMPOSIO_EXAMPLES_*导出(stdout 设计为可被eval,所有值做了 shell 单引号转义),缺失的 OAuth 连接可用--initiate-missing生成浏览器授权 URL;
  • --gc(可加--dry-run预览)是破坏性命令:只删除示例自己创建的资源——从未变 ACTIVE 的 connected accounts、超额的 serpapi demo 账户、以及匹配examples-<label>-<unix-seconds>命名的 MCP configs。删除以"auth config 名为examples-<slug>"作为所有权标记(isExampleOwned),且只处理创建超过 24h 的资源,保证并发运行安全;项目里用户自己的配置永远不会被误删。
  • 值得注意的安全细节:provisioner 的所有 API 调用带redirect: 'error'(api 函数),防止 3xx 重定向把x-api-key转发给其他 host。

4.4 读懂 parity 报告

parity.mjs 的判定规则是:只比较两边都 green 的入口;任一侧 red、skipped 或缺失,该入口记parity: false并附原因,而不会让比较器直接失败。对两边都 green 的入口,比较(method, path-template)集合是否相等(忽略 parity-variance.json 中登记的允许差异对,当前该文件为空列表{"entries": []})。

因此阅读报告时:

  • 同时看comparedparityGreencompared是参与比较的入口数,parityGreen是真正一致的数量;
  • 检查 trace 是否非空:两轮空 trace 的 parity 是空洞地成立的(vacuous truth),必须结合compared一起判断;
  • 退出码语义:report.length > 0 && report.every(r => r.parity)时退出 0,否则退出 1(见 parity.mjs 末尾)。

五、验证 harness 自身:selftest 与 neg

5.1selftest:验证 harness 本身的正确性

node harness/run.mjs selftest

cmdSelftest 覆盖的检查点包括:

  • 后端 URL 处理:staging 是默认值、裸 https 根被采纳、携带 path/query/凭据/明文 http 的 URL 被拒绝;
  • 候选 swap 守卫:TS/Python 的候选替换保护逻辑(含"已解除钉版的工程再解除会报错"的负例);
  • 已知好/坏 fixturests/anthropic/index这类已知好入口(实际 selftest 用 error-handling-demo 入口)必须退出 0,harness/fixtures/always-fails.ts 与harness/fixtures/always_fails.py必须退出非 0;
  • 两个追踪器:harness/fixtures/trace-check.ts 与 harness/fixtures/trace_check.py 各发一个未认证请求,验证 fetch/httpx shim 都记录了非 2xx 的 composio 行(如GET /api/v3/toolkits);
  • 比较器自身的接受/拒绝行为:两个相同运行目录应通过,候选侧缺失入口时比较器应拒绝。

5.2neg:对示例的互补检查

node harness/run.mjs neg

neg用垃圾凭据(nc-invalid前缀的假 key)重跑示例,期望每个入口都变红。任何在垃圾凭据下仍 green 的入口都被视为"吞掉了错误"(error swallowing),会以NEGATIVE-CONTROL FAILURES列出并使进程退出 1(见 cmdNeg)——这样的入口不能算作有效覆盖。可用--sample N --seed S做确定性抽样(使用 mulberry32 伪随机数发生器,种子可复现)。

六、运行模式与常用参数速查

node harness/run.mjs <sweep|neg|selftest> [options],退出码语义:0全部通过,1存在发现(红项/失败预期),2用法或环境错误。

参数适用命令说明
--client baseline\|candidatesweep本轮身份,默认baseline
--lang ts\|pysweep / neg只跑某语言入口
--ids a,bsweep / neg显式指定入口集合(parity run 强烈建议)
--tiers 1,2,3sweep按 tier 过滤,默认1,2,3
--llm live\|mocksweep默认livemock时模型流量走本地 aimock(默认127.0.0.1:4010,可用AIMOCK_PORT覆盖),provider key 被强制改写,保证 mock sweep 不消耗 token
--concurrency Nsweep / neg并行度,默认 4(neg 默认 6)
--sample N --seed Sneg确定性抽样
COMPOSIO_BASE_URL全部后端根,默认 staging,只接受裸 https 根
COMPOSIO_CLIENT_TARBALL/COMPOSIO_CLIENT_WHEELsweep(candidate)本地候选客户端产物
COMPOSIO_TRACE_FILE(内部)追踪输出文件,由运行器注入,示例不得引用

两个运行器细节值得注意:

  • 并发与串行:manifest 中标记serial的入口(如触发器等有状态示例)会排到并行池之后单独执行(runPool);
  • LLM mock 兼容性:manifest 中llmMock: false的入口在 mock 模式下会被跳过(记llm-mock-unsupported),它们是仅限 live 的 canary。

七、与 CI 的衔接

.github/workflows/examples-live.yml把上述能力接入了 CI:工作流支持client/lang输入(对应 baseline/candidate 与 ts/py),显式设置 staging 后端,校验COMPOSIO_API_KEY存在,产物.artifacts/examples-parity/作为examples-live-resultsartifact 保留 14 天。也就是说,一次客户端发版可以完全自动化地完成"基线 sweep → 候选 sweep → parity 比对",任何未预期的调用集变化都会在合并前暴露。

八、实践要点与边界提醒

  1. 永远用专用项目跑:sweep 会让示例真实调用后端、创建连接与 MCP 配置;--gc会删项目里超过 24h 的示例资源。请只对"可丢弃"的项目运行。
  2. parity 不等于全绿:两个 trace 都为空时 parity 空洞成立。阅读报告务必同时核对comparedparityGreen与 trace 非空。
  3. 不要吞 provision 失败out=$(node scripts/examples-provision.mjs) && eval "$out"eval报告的是被求值文本的退出状态,必须用&&链式保证 provision 失败即终止。
  4. 候选产物守卫是特性:如果客户端解析版本没有实际变化,sweep 会拒绝启动——这正是"比较必须真实发生"的保障。
  5. 负例控制不可省neg是判定"示例真的在调用后端"的最低成本手段,与selftest互为表里,共同保证 harness 自身与示例两端的信号都可信。

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 21:38:41

Zabbix-in-Telegram源码解析:深入理解Telegram Bot与Zabbix的通信机制

Zabbix-in-Telegram源码解析&#xff1a;深入理解Telegram Bot与Zabbix的通信机制 Zabbix-in-Telegram是一款强大的开源工具&#xff0c;它实现了Telegram Bot与Zabbix监控系统的无缝集成&#xff0c;支持通过Telegram接收带有图表的Zabbix告警通知。本文将深入剖析其核心通信机…

作者头像 李华
网站建设 2026/9/10 21:38:23

CANN/GE数据流构图接口

&#xfeff;# 构图接口 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Te…

作者头像 李华
网站建设 2026/9/10 21:34:33

MCGS 7.7仿真在鼓风机气压检测系统中的应用实践

白天工厂里鼓风机房热浪加噪声&#xff0c;晚上想改程序又怕现场设备配合不了。做鼓风机气压检测系统这些年&#xff0c;我最大的体会是——真正费时间的从来不是接线和组态&#xff0c;而是没完没了的反复调试。所以我现在养成一个习惯&#xff1a;所有鼓风机气压检测的画面、…

作者头像 李华
网站建设 2026/9/10 21:34:08

CANN/ge离线图编译执行示例

Sample Usage Guide 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Tensor…

作者头像 李华
网站建设 2026/9/10 21:34:04

Java大数据技术在智能医疗中的应用与实践

1. 智能医疗时代的数据革命电子病历数据正以每年40%的速度增长&#xff0c;三甲医院平均每天产生超过5TB的临床记录。这些数据如果只是静态存储&#xff0c;就如同埋在地下的石油&#xff0c;无法发挥其真正的价值。我在参与某省级医疗大数据平台建设时&#xff0c;亲眼见证过这…

作者头像 李华