
OpenMed 隐私安全 Agent 运行摘要openmed.agent.RunSummary确定性元数据设计与边界校验实战【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed导读OpenMed 是本地优先local-first的医疗 AI 平台其 Agent 编排层在诊疗流程中会执行多次工具调用、产出临床证据与 FHIR/OMOP 资源。为了在仪表盘与审计证据包中呈现这次运行发生了什么又绝不让提示词、工具参数、证据文本、文件路径、凭据或异常信息离开数据边界openmed.agent.RunSummary提供了一套只含确定性元数据的运行摘要机制。读完本文你将掌握 RunEvent 事件契约、RunSummary.from_events()聚合、from_json()严格解析的完整细节并能结合实际源码与测试用例在自己的 Agent 工作流中落地隐私安全的运行审计。本文主体内容继承自 docs/agent/run-summaries.md并辅以 openmed/agent/run_summary.py、openmed/agent/outcomes.py 等源码实现与测试证据进行纵深展开。一、设计目标只让元数据过境绝不复制内容openmed.agent.RunSummary的核心承诺是为仪表盘和证据包生成确定性deterministic元数据但不复制任何敏感内容。在 run_summary.py 的模块 docstring 中明确写着Only bounded identifiers, closed workflow outcomes, counts, durations, and artifact digests cross this boundary. Prompts, tool payloads, evidence text, paths, credentials, and exception text are never accepted or rendered.也就是说跨越摘要边界的只有五类受限数据有界的bounded工作流标识符来自闭合词汇表的类型化WorkflowOutcome结果类别 原因码有界的非负工具调用计数与有限的运行时长可选的、小写 SHA-256 产物摘要版本化的 schema 标识符。而提示词、工具实参、工具输出、证据文本、文件系统路径、凭据、异常文本——一律不被接收、不被渲染。这让运行摘要天然可以进入审计日志、远程仪表盘或证据包而不触碰 HIPAA 合规所要求的 PHI 边界。二、事件契约RunEvent的五个字段每个运行事件RunEvent定义见 run_summary.py只承载以下字段字段类型约束workflow_idstr有界标识符禁止路径或 URL 语法由正则^A-Za-z0-9?$校验outcomeWorkflowOutcome来自闭合结果/原因码词汇表见第三节tool_call_countint非负整数上限_MAX_TOOL_CALLS 10_000_000duration_secondsfloat有限值上限_MAX_DURATION_SECONDS 31_536_000.0约一年artifact_digeststuple[str, ...]每个事件最多 128 个格式为sha256:前缀 64 位小写十六进制值得注意的校验细节标识符防注入测试 test_run_summary.py 明确验证了workflow with spaces、/tmp/workflow、https://example.test、../secret都会被拒绝并抛出invalid_identifier——这正是为了防止路径穿越、URL 语法与自由文本混入摘要。计数与时长有界tool_call_count必须是非负整数且不超过上限duration_seconds先校验类型与范围再转换为float并强制math.isfinite杜绝NaN/Infinity等非有限值。摘要去重同一事件内的artifact_digests不允许重复duplicate_item。事件构造示例from openmed.agent import OutcomeClass, RunEvent, RunSummary, WorkflowOutcome event RunEvent( workflow_idclinical-review, outcomeWorkflowOutcome(OutcomeClass.SUCCESS, completed), tool_call_count3, duration_seconds2.5, artifact_digests(sha256: a * 64,), ) summary RunSummary.from_events([event]) json_payload summary.to_json() assert RunSummary.from_json(json_payload) summary markdown_report summary.to_markdown()三、结果词汇表WorkflowOutcome的闭合枚举WorkflowOutcome见 outcomes.py是事件中唯一表达运行结果的对象其词汇表是闭合closed的——不允许自由文本状态字符串。完整词汇表继承自 docs/agent/outcome-reasons.md结果类别OutcomeClass允许的原因码reason_codesuccesscompletedabstainedinsufficient_evidence、out_of_scope、low_confidencereview_requiredconflicting_evidence、safety_review、human_gatepolicy_deniedconsent_required、purpose_mismatch、phi_policyfailedtool_error、timeout、invalid_input这张映射表在 outcomes.py 中以_REASON_CODES字典硬编码并通过allowed_reason_codes()暴露查询接口。失败的关闭原则fail closed覆盖以下场景未知结果类别 →unknown_class未知原因码 →unknown_reason类别与原因码不匹配如success配timeout→ 拒绝多余字段 →unknown_field自由文本原因 → 一律拒绝。异常信息只命名字段名或稳定错误码如outcome_class: unknown_class绝不回显被提交的值。这保证了即使校验失败也不会把可疑的临床内容泄露进异常堆栈。to_dict()按固定字段序schema_version、outcome_class、reason_code输出to_json()输出按键排序的紧凑 JSON保证相同输入序列化后逐字节一致byte-for-byte identical——这是审计与去重的基础。四、聚合RunSummary.from_events()的边界与确定性RunSummary.from_events()见 run_summary.py把一组RunEvent聚合为一条摘要。源码中的关键逻辑输入必须可迭代字符串、bytes、映射对象会被拒绝events: invalid_iterable防止误把单个对象当序列事件数上限_MAX_EVENTS 10_000超过即too_many_items工作流 ID 去重聚合后workflow_ids为排序去重的元组且最多_MAX_WORKFLOWS 1_024个结果计数outcome_counts必然覆盖全部 5 个闭合结果类别且合计不超过事件上限工具调用累计tool_call_count逐事件累加超限即total_out_of_range时长累计使用math.fsum精确求和避免浮点累加误差总和超限即拒绝摘要级去重所有事件的产物摘要合并为排序去重集合上限_MAX_SUMMARY_DIGESTS 4_096。这种设计保证了输入有界 聚合总量有界任何异常输入都在进入摘要前被拦截。直接构造的规范化强制RunSummary是frozenTrue的 dataclass但其__post_init__run_summary.py会强制规范化排序workflow_ids与artifact_digests必须是排序去重后的序列outcome_counts必须恰好覆盖 5 个类别键。也就是说绕过from_events()直接构造时若传入乱序、重复或键不完整的序列会直接以not_sorted_unique/invalid_keys失败——从构造层面杜绝了非规范化的摘要进入下游。五、信任边界解析from_dict()与from_json()文档明确指出在信任边界trust boundaries应使用RunSummary.from_dict()或RunSummary.from_json()解析摘要。两者都拒绝缺失字段missing_field与未知字段unknown_field——摘要字段是冻结集合_SUMMARY_FIELDS只有schema_version、workflow_ids、outcome_counts、tool_call_count、duration_seconds、artifact_digests六个不支持的版本unsupported_version必须精确等于openmed.agent.run_summary.v1非法计数invalid_count不安全的字符串unsafe_string——字符串要么匹配有界标识符正则要么匹配sha256:摘要格式否则拒绝。from_json()在其之上还有四道额外防线run_summary.py大小上限MAX_RUN_SUMMARY_JSON_BYTES 1_048_5761 MiB对字符串先按 UTF-8 编码后测长度超限即json_too_large重复键拒绝通过object_pairs_hook_strict_json_object在解析时检测重复字段并抛duplicate_field非标准非有限数拒绝parse_constant_reject_json_constant拦截NaN/Infinity/-Infinity字面量non_finite_number畸形 JSON 兜底解析失败统一转为summary: invalid_json且不保留底层源码异常——调用方永远不会看到来自解析器的内部 traceback。此外严格解析还会拒绝序列字段中出现映射对象invalid_sequence字符串/bytes 也不行并在转换为 float 之前完成时长边界检查避免类型混淆带来的精度与安全问题。六、确定性序列化to_dict()/to_json()/to_markdown()摘要的序列化输出是稳定、可复现的to_dict()输出前先经过_assert_safe_payload递归校验run_summary.py任何非有限浮点数non_finite_number、超出白名单的字符串unsafe_string、非法类型forbidden_type都会触发RunSummaryPrivacyError——这是序列化方向的最后一道隐私闸门to_json()json.dumps(..., sort_keysTrue, separators(,, :))按键排序的紧凑 JSON保证相同摘要序列化结果逐字节一致to_markdown()生成确定性 Markdown 报告固定包含# Agent Run Summary、## Workflows、## Outcomes、## Execution工具调用数 时长、## ArtifactsSHA-256 列表五个小节。JSON 键、结果行、工作流标识符、产物摘要的顺序全部稳定可直接进入审计比对或证据包生成流水线。同时摘要层从不读取产物内容或工作流内容——它只搬运元数据不触碰数据本体。七、配套生态内容无关的 Agent 元数据体系RunSummary不是孤立组件它与openmed.agent包中的其他隐私安全组件共同构成一套完整的内容无关元数据体系统一导出见 openmed/agent/init.pyArtifactReference让一次运行指向一个产物而无需把报告、临床内容、文件名、本地路径或远程 URL 复制进 trace。每个引用只含art_ 32 位小写十六进制的透明 ID、闭合类别evidence/preview/fhir/omop/evaluation、版本化 schema ID、64 位小写 SHA-256 摘要和不超过有符号 64 位整数上限的正字节数。实现见 artifact_reference.py批量挂载多个引用时用validate_artifact_references()拒绝重复 IDduplicate_artifact_id并保持顺序。重要边界引用记录的是调用方提供的摘要与大小并不自行验证创建、解析、序列化引用永不打开本地文件、不拉取远程资源、不校验临床内容。Event Correlationrun_/act_前缀 32 位小写十六进制的 128 位随机关联 IDRunId/ActionId/ActionCorrelation运行时用secrets.token_bytes生成禁止通过对提示词、临床文本、文件名、用户 ID 等做哈希或编码来派生。Timing Metadata调用方提供的单调纳秒边界RunTiming/ActionTiming计算精确整数时长永不读取墙钟序列化后不含墙钟时间戳、路径或 PHI父链接必须构成无环图。Governance IdentifiersCapabilityId/PurposeId/PolicyId/WorkflowId/ToolId五种开发者手写名称遵循kind:reverse-domain/local-name[version]语法GovernanceIdError的code提供invalid_identifier、wrong_kind、namespace_too_long等稳定诊断。这些组件的共性设计语言与RunSummary完全一致闭合词汇、有界长度、规范化解析、错误信息不回显被拒绝的值。整个openmed.agent包在 openmed/agent 目录下均有独立源码模块与对应测试tests/unit/agent 下的test_run_summary.py、test_outcomes.py、test_artifact_reference.py、test_correlation.py、test_timing.py、test_identifiers.py可以作为元数据安全模式的完整参考实现。八、测试验证与离线回归运行摘要的所有边界行为都有离线测试覆盖。以 tests/unit/agent/test_run_summary.py 为例test_run_event_accepts_safe_metadata验证合法元数据被接受且字段保持原值test_run_event_accepts_closed_outcome_vocabulary参数化遍历全部 5 个OutcomeClass验证闭合词汇表test_run_event_rejects_paths_urls_and_free_text验证带空格、路径、URL、../的工作流 ID 全部以invalid_identifier拒绝test_run_event_requires_typed_outcome字符串或字典形式的 outcome 一律invalid_type拒绝。全文件共 442 行覆盖计数越界、时长越界、重复摘要、乱序 ID、未知字段、重复 JSON 键、超大文档、非有限数等负面路径。类似地治理标识符的语法测试可用如下命令聚焦运行uv run --frozen --extra dev pytest tests/unit/agent/test_identifiers.py -q九、落地建议何时、在何处使用RunSummary结合源码设计与测试覆盖以下实践路径可以直接复用在 Agent 工作流出口生成摘要每次工作流结束后用RunEvent记录工作流 ID、WorkflowOutcome、工具调用数、时长与产物摘要再通过RunSummary.from_events()聚合。注意workflow_id使用有界标识符字母数字 _/./-不要塞入路径或 URL。在信任边界用from_json()解析任何来自外部系统、网络请求或持久化存储的摘要一律走from_json()其 1 MiB 上限、重复键检测、非有限数拦截与字段白名单可防御畸形或恶意载荷不要直接用RunSummary(...)构造去解析不可信数据。摘要只进证据包内容留在原地产物本体通过 ArtifactReference 以art_透明 ID SHA-256 引用运行摘要只携带摘要层元数据两侧都永不读取产物内容。错误处理只看错误码RunSummaryError/RunSummaryPrivacyError/OutcomeError的code与field_name是稳定诊断接口异常消息不回显提交值可直接用于监控告警而无需担心 PHI 泄露。这套机制把Agent 可观测性与医疗数据隐私解耦仪表盘获得的是确定、有界、无内容的运行事实审计证据包获得的是可复现、可比对的元数据轨迹而 PHI 始终停留在本地数据边界之内。参考与深入阅读主文档docs/agent/run-summaries.md结果词汇表docs/agent/outcome-reasons.md产物引用docs/agent/artifact-references.md关联标识docs/agent/event-correlation.md、docs/agent/timing-metadata.md、docs/agent/governance-identifiers.md源码实现openmed/agent/run_summary.py、openmed/agent/outcomes.py、openmed/agent/artifact_reference.py测试用例tests/unit/agent/test_run_summary.py 及 tests/unit/agent 目录下其余组件测试【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考