Skip to main content

Ennew Harness Python SDK

适用于 Python 3.9 及以上版本,安装包名为 ennew-harness-sdk,导入名称为 ennew_harness。

从 0.1.1 起,导入名称由 harness 改为 ennew_harness,避免与 Worker 自身的同名包冲突。升级后请同步修改业务脚本中的导入语句;不保留旧名称别名。

python3 -m pip install --upgrade ennew-harness-sdk

本 SDK 依赖 Ennew Harness 运行环境,并非独立运行的公共网关客户端。普通脚本读取上下文或发送前端消息时,运行时必须提供 CODEX_THREAD_ID;MCP 读取上下文或发送前端消息可改为传入请求 ctx。读取上下文还需设置 ENV 或 HARNESS_ENV,并能访问对应业务网关。发送前端消息需要本机 Worker 服务。

读取上下文时,Worker 还需通过环境变量 HARNESS_GATEWAY_CONTEXT_TOKEN 注入对应环境的服务凭据。SDK 将其放入 X-OpenClaw-Mcp-Gateway-Token 请求头;未配置或为空时,在发送请求前报错。不要将真实凭据写入源码、镜像或发布包。

安装到运行业务脚本的 Python 环境后,可直接使用:

from ennew_harness import context, gui

current = context.get_current_context()
gui.send("file_changed", {"file": "report.md"})

上述未传入 ctx 的调用都从运行时的 CODEX_THREAD_ID 获取当前线程身份。gui.send 要求传入非空的 type 和字典 payload,把 type 同时写入 params.type 与 params.message 中的业务 JSON,经 Worker 本机 127.0.0.1:18080/internal/events 发到当前线程的前端连接。只有线程正在执行且前端连接仍在时才能发送;接口返回成功表示消息已写入 WebSocket,不保证前端已处理。

MCP 回调中传入宿主提供的本次请求 ctx,SDK 从 ctx.meta["threadId"] 获取线程身份,不读取或修改 CODEX_THREAD_ID。元数据缺失或线程 ID 不是非空字符串时,在发送请求前报错,不回退环境变量。线程身份不要从模型填写的工具参数中获取。此方式不要求 SDK 安装 MCP 依赖,也不支持在尚无请求上下文的 MCP 启动阶段获取线程身份。

在异步 MCP 回调中,使用以下方式避免同步网关请求阻塞事件循环:

import asyncio
from ennew_harness import context, gui

current = await asyncio.to_thread(context.get_current_context, ctx)
await asyncio.to_thread(gui.send, "file_changed", {"file": "report.md"}, ctx=ctx)

context.get_current_context() 优先读取系统环境变量 ENV 并转为大写;ENV 未设置或为空字符串时,再读取 HARNESS_ENV(保持原有大小写要求)。取到的值必须是 FAT、UAT 或 PROD;非空但无效的 ENV 会直接报错,不会回退。SDK 根据该值选择网关配置,并完整返回网关响应中的 data,包括 authTokens、businessContext 及后续新增字段。返回值可能包含敏感凭据,业务脚本不得记录、展示或转发完整上下文。三套网关 URL 定义在 ennew_harness/context.py,请求不内置 Token。安装 SDK 不会自动授予业务网关访问权限。

源码仓库中可运行上下文示例脚本:python3 fat_context.py。该脚本不随安装包提供。

文件写入后通知(0.1.6 起)

模型生成文本、JSON 时,推荐用标准输入一次同步提交完整内容,不先创建 Agent 临时输入文件。脚本的 read() 等待 EOF,之后才校验、写入和通知。下例为可执行格式示例,真实产物按业务契约填写:

python3 -m ennew_harness.write_notify --file artifacts/report.json --content-file - --json <<'ARTIFACT_EOF'
{"title":"本次报告","ready":true}
ARTIFACT_EOF

用单引号包住 heredoc 标记,避免正文中的 shell 变量和命令被展开;标记不能出现在正文独立行中,结尾独占一行。先准备完整内容再发起一次调用,不后台执行、不交互式分段输入。生成程序管道的 EOF 不代表生成成功,不建议将未检查退出码的生成程序直接管道接入。

执行顺序:读取到 EOF → 输入校验 → 目标同目录临时文件写入、flush/fsync、关闭 → os.replace 原子替换 → 回读比对 → gui.send。默认外层 type=file.changed,消息 JSON 内 type=file_changed,data.files 为项目相对路径数组,与原通知协议一致。gui.py 保持不变;脚本内部通知适配器处理外层与内层 type 不同的情况,通过现有 Worker HTTP 接口发送。默认入口不产生 Agent 输入临时文件;SDK 内部临时文件成功替换后消失,失败时清理。

批量标准输入

python3 -m ennew_harness.write_notify --batch-stdin <<'ARTIFACT_BATCH_EOF'
{"files":[{"file":"artifacts/report.json","content":"{\"ready\":true}","json":true},{"file":"artifacts/report.md","content":"# 本次报告\n"}]}
ARTIFACT_BATCH_EOF

信封只含非空 files 数组,每项 file 是目标路径、content 是完整文本字符串,可选 json=true 校验该文件 JSON。批量信封完整读取 EOF 后,解析和校验全部内容,再写入文件;全部文件回读成功后发送一次去重通知。同路径同内容去重,不同内容拒绝。--json 校验所有项;混合 Markdown 与 JSON 时用逐项 json 标志。--batch-stdin 不与 --file、--content-file、--payload-from-content 或 --cleanup-input 混用。

项目状态通知

python3 -m ennew_harness.write_notify --file project-state.json --content-file - --json --type sop.update --payload-from-content <<'STATE_EOF'
{"revision":1,"currentStep":"step-01","steps":[{"stepId":"step-01","stepName":"需供能力匹配","viewType":"system-page","viewUrl":"/demandSupply","status":"not_started"}]}
STATE_EOF

此处展示一项的格式示例,实际状态按平台步骤配置提供完整列表。通知携带状态 JSON 并附加 type=sop.update,状态文件不增加 type。--payload-from-content 仅支持单文件;自定义消息可用 --payload-file 传入 JSON 对象,与前者互斥。

失败处理与文件模式

退出码 0:文件已保存且 Worker 接受通知,不表示前端已处理;1:输入、写入或回读失败,未发送通知,实际文件可能部分写入,应检查后修复;2:已保存但通知失败;3:保存和通知成功,但临时输入清理失败。

退出码 2 时使用原命令加 --notify-only,并重新提供完全一致的标准输入正文或批量信封,重试一次。该模式只回读对比、不重写文件、不递增 revision;内容改变拒绝通知。退出码 3 仅清理残留,不重新通知。标准输入不落输入临时文件,重试内容须由调用方保留;SDK 不持久化重试正文。

大文件或外部程序输出保留原文件输入模式:

python3 -m ennew_harness.write_notify --file artifacts/report.pdf --content-file drafts/report.tmp.pdf --cleanup-input

只有外部生成程序同步成功退出、文件关闭后才执行。--cleanup-input 通知成功后删除可丢弃的输入文件,失败保留供重试;不删除目标产物、payload-file 或需长期保留的原始材料。重复输入路径去重,输入与任一目标产物相同则预先拒绝。标准输入无需清理。文件模式仍支持重复 --file 与 --content-file 按出现顺序配对,全部输入先读取再写入。

环境与保证范围

目标相对路径基于 --root(默认 cwd);真实绝对路径及符号链接解析后的目标必须在 root 内。消息路径以 / 开头代表相对于项目根目录,不是服务器绝对路径。父目录自动创建。前端文件服务需访问同一存储视图,同目标写入须串行执行。

脚本校验 JSON 语法和读写一致性,不判断业务完整性;EOF 仅代表本次传输结束,不能识别内容本身遗漏或上游异常导致的完整合法短内容。批量写入不提供多文件事务回滚。当前无通知持久化、离线补发或前端处理回执。

运行环境需要更新后的 ennew-harness-sdk、CODEX_THREAD_ID 与本机 Worker。SDK 通知不产生 Codex JSONL 中 send_hidden_message 的调用记录,依赖此记录的后台记忆 Skill 归属需另行适配,不重复发送通知补记录。

Metadata

Release files for ennew-harness-sdk 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ennew-harness-sdk 0.1.7
File Size Uploaded Provenance
ennew_harness_sdk-0.1.7.tar.gz 18.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ennew-harness-sdk 0.1.7
File Interpreter ABI Platform
ennew_harness_sdk-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 28.9 kB

Release files / ennew_harness_sdk-0.1.7.tar.gz

Download URL ennew_harness_sdk-0.1.7.tar.gz
Size 18.0 kB
Tags Source
SHA-256 checksum
How to use checksums
6a06b1571c7ad650070c71bc38c05cb2d7b09eb1bbafe322eff7b83dce91b40f
BLAKE2b-256 checksum
How to use checksums
2410d596d82b732a447257f70aac9d187443252f5271af0cbda9be3aa1bf6a2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.12

Release files / ennew_harness_sdk-0.1.7-py3-none-any.whl

Download URL ennew_harness_sdk-0.1.7-py3-none-any.whl
Size 10.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2353c635dadfd5b537e718e1030acac13db2bf40851b7a56b22cebd6d828392
BLAKE2b-256 checksum
How to use checksums
fe2f0984c1eaf99713973af84ddd95636a5663ed1bbd2fbf1873e5f79ca68f3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.12

Security for ennew-harness-sdk 0.1.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page