本页为译文。以英文版为准: English

面向工程师和科学家

给你的智能体一份它们无法讨好的记录。

一个 Python 包,零依赖。由你决定谁来审查、哪些运行算作已记录、工作花费多少;HypGraph 负责执行,在写入时核查每条主张,并推导出真正被证明的内容。

安装

pip install hypgraph            # engine, CLI, JSON API, UI — standard library only
pip install "hypgraph[mcp]"     # + the MCP server (FastMCP)

Python 3.10+。每份记录一个 SQLite 文件(Graph("research.hypgraph")),或用于测试和 notebook 的内存版 Graph()。

模型

有类型的节点 — 问题、假设、实验、运行、结果、主张、来源、审查、决策 — 由端点受约束的有类型链接相连(supports、challenges、requires、tests、produced、replicates、based_on …)。所有表都只追加;每次写入都是 SHA-256 链中的一个事件。不存储任何现状。每次读取都会推导:

  • 审查 — 已核查 / 未核查 / 有争议 / 过时,依据审查者对当前版本的裁定;
  • 风险 — 上游已倒下的前提(AT RISK)、依据已变动的决策(REVISIT)、全部支撑已倒下(UNSUPPORTED);
  • 独立证据线 — 不共享运行、数据工件或来源的支撑;
  • 证据 — 最强的一条线:智能体报告 → 仪器记录 → 已复现 → 独立实现 → 新数据 → 外部来源。

完整规则见记录格式;hypgraph schema --json 会打印词汇表。

策略与角色

from hypgraph import Graph, Policy

POLICY = Policy(
    reviewers={"critic", "stats-reviewer"},   # whose verdicts count (an investigation can add its own)
    instrument="runner",                      # the only author whose kind=lab runs are "recorded" evidence
    operator="operator",                      # revises anything, settles disputes
    importer="importer",                      # brings legacy records in, with their original dates
)
g = Graph("research.hypgraph", policy=POLICY)
身份认证由你负责。HypGraph 按字面接受 author=。凡是智能体能接触到图的地方,都在你这一侧固定它的作者并拒绝 POLICY.reserved — 内置的 MCP 服务器和 HTTP API 就是这么做的。

一种适用于智能体团队的模式:

在你系统中的角色在 HypGraph 中
工作智能体(研究员、分析员)各自使用自己的作者名;它们的主张会被核查;它们的审查是评论
批评者 / 审查者智能体reviewers;它们的裁定决定现状;从不针对它们自己的节点
执行代码的作业执行器 / 沙箱instrument:用哈希记录运行,使结果算作已记录
你,或代表你行事的编排器operator

接入智能体

MCP

每个智能体身份一个服务器进程 — 作者在启动时固定:

hypgraph --db research.hypgraph --as critic mcp                                # stdio
hypgraph --db research.hypgraph --as worker-1 mcp --transport http --port 8766 # streamable HTTP

或者在进程内构建(自定义策略、你自己的认证):hypgraph.mcp.build(graph, author="worker-1") 返回 FastMCP 服务器。

可运行的示例,同一个故事以六种方式集成(LangChain、LangGraph、PydanticAI、CrewAI、OpenAI Agents SDK、Claude Agent SDK):examples/frameworks。每个都可以用脚本化模型离线运行,或用 --real 在真实模型上运行。

Agent Skill

hypgraph skill --install 会写出 .claude/skills/hypgraph/SKILL.md:方法、各类拒绝及其修正方式,通过 CLI 使用。

你自己的工具

任何接受 Python 函数作为工具的框架(Claude Agent SDK、LangChain、LangGraph、OpenAI Agents …)— 返回拒绝文本,让模型能据此行动:

from hypgraph import GraphError

def add_claim(statement: str, scope: str, result: str, measurements: list[dict], why: str) -> str:
    """Add a claim supported by a result; every number in the statement must be bound in measurements."""
    try:
        n = g.create(author=AGENT_NAME, type="claim", inv=INV,
                     fields={"statement": statement, "scope": scope, "measurements": measurements},
                     links=[{"rel": "supports", "from": result, "why": why}])
        return f"Added {n['code']}: {n['state']['sentence']}"
    except GraphError as e:
        return f"Refused — fix this and retry:\n{e}"

在任务开始时把 g.report(inv)["markdown"] 或 MCP 文本 overview 放进智能体的上下文,让它先读到已确立的内容,而不是重新推导。

记录运行

from hypgraph import file_sha256

data, code = file_sha256("evals/heldout.jsonl"), file_sha256("eval.py")
a_data = g.create(author="runner", type="artifact", inv=INV, fields={**data, "format": "jsonl"})["id"]
a_code = g.create(author="runner", type="artifact", inv=INV, fields={**code, "format": "py"})["id"]
run = g.create(author="runner", type="run", inv=INV, fields={"kind": "lab", "state": "succeeded", "seed": 7},
               links=[{"rel": "uses", "to": a_data, "data": {"role": "data"}},
                      {"rel": "uses", "to": a_code, "data": {"role": "code"}}])["id"]
res = g.create(author="runner", type="result", inv=INV, links=[{"rel": "produced", "from": run}],
               fields={"summary": "Held-out accuracy, fine-tune vs baseline.",
                       "values": {"finetune": {"k": 1624, "n": 2000}, "baseline": {"k": 1568, "n": 2000}}})["id"]

工件按内容寻址(相同字节,一个节点),因此用同样数据算出的两个结果会自动合并为一条证据线。重新运行会把 replicates 链接到 data.differs(new_seed、new_impl、new_data …),并提升证据等级。

配置与工作流

在调查上设置一个配置,记录就会执行该学科的规则 — 对于 @2 配置,还会执行它的工作流:带关卡的阶段、什么会使证据失效、diff、实例、来源或仓位必须具备的有类型形式。阶段和现状一样,在每次读取时推导。

inv = g.create(author="operator", type="investigation",
               fields={"title": "Issue 412", "objective": "Fix the importer and prove it.", "profile": "software@2"})["id"]
q = g.create(author="operator", type="question", inv=inv, fields={"text": "Does the importer keep quoted commas?"})["id"]

g.stage(q)        # {"stage": "implemented", "index": 2, "of": 6, "complete": False,
                  #  "next": "no live artifact kind=diff (meta: base_sha, head_sha, files) part_of Q1", "gates": [...]}
g.stages(inv)     # one row per live question;  GET /api/graph/stages?inv=…  ·  MCP tool: stage
g.completion(inv) # the profile's criteria for the whole investigation
  • 关卡是谓词。hypothesis_stated、preregistered、diff_registered、tests_pass_current、backtested、positioned、still_valid、solved、result_reviewed … — 也可用作工单的 done_when。
  • 什么会使之失效。除前提外,工作流还把 uses(修正后的数据文件、被取代的 diff 或实例)或 cites(被撤回的来源)加入到使依赖项有风险的条件中 — 按配置区分,因此 @1 下的记录保持原有的现状不变。
  • 时效。如果某个结果的运行使用了现已被取代的工件,或其 valid_until 已过,它就是过时的;当支撑一条主张的所有结果都过时,主张也过时。基于过时证据的核查不满足 reviewed。
  • 有类型的形式。artifact.kind + meta(diff 需要 base_sha、head_sha、files)、source.kind、带 size、stop、review_date、paper 的 decision.kind=position — 不完整则被拒绝。重新记录相同字节会给无类型的工件加上类型,并添加所指定的链接。
  • 诚实的结局。一个已核查的 inconclusive 回答、一项 no_position 决策、一次已验证的失败(仪器记录的阴性结果,已核查)都能完成一个仅靠关卡永远无法完成的问题。

每种工作流所依据的方法,以及每个关卡背后的决策,在 docs/workflows 中各有一页。HypSwarm 的调度器正是据此为每个问题下达阶段工单。

做法:站得住的评估报告

  1. 预注册。在运行前建立一个实验,用 tests 链接到每个假设(“微调更好”、“没有差异”),每个都带 data.expected。
  2. 记录运行,方法如上;把计数以 {k, n} 的形式写进结果的值中,而不只是百分比。
  3. 用测量来主张。“2,000 中 1,624,对比 1,568”是绑定的;没有结果字段对应 5 的“好 5 个点”会被拒绝。
  4. “没有差异”需要检验力。预埋一个已知效应(在预测的副本中注入 2 个点的差异),证明在这个样本量下比较能检测到它,并把该结果标记为 power: "demonstrated"。没有这一步,就把主张记录为 inconclusive — 记录会坚持这一点。
  5. 审查。一个批评者智能体在保存的预测上重新运行评估器;它的 pass 或 fail 被固定到这条主张的这个版本。
  6. 报告。g.report(inv)["markdown"] 是报告开头的事实表;它不能重述已撤回的主张。

成本

def spend(inv, tasks, since=None):            # your meter: model calls per task id
    rows = ledger.calls(task_ids=tasks, since=since)
    return {"usd": sum(r.usd for r in rows), "calls": len(rows), "input_tokens": ..., "cached_tokens": ...,
            "output_tokens": ..., "by_task": [{"task_id": t, "usd": ...} for t in tasks]}

g = Graph("research.hypgraph", policy=POLICY, spend=spend)
with g.writing_for(task_id):                    # events carry the task
    g.create(...)
g.cost(inv)        # $ for the investigation, per node, per verdict, and since the record last moved

HTTP 与界面

hypgraph serve --db research.hypgraph            # HypGraph UI + JSON API on 127.0.0.1:8765, read-only
hypgraph serve --db research.hypgraph --writable # + POST /api/graph/write

在你自己的应用中(示例为 FastAPI;任何框架都可以):

from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from hypgraph.server import dispatch
from hypgraph.ui import static_dir

app = FastAPI()
app.mount("/hypgraph", StaticFiles(directory=static_dir(), html=True))

@app.get("/api/graph/{path:path}")
def graph_api(path: str, request: Request):
    status, body = dispatch(g, "GET", "/" + path, dict(request.query_params))
    return body          # (set the status code too)

界面不需要框架,也没有构建步骤:HypGraph.mount(el, {source: HypGraph.HttpSource('/api/graph')}),或完全不用服务器的 HypGraph.BundleSource(bundle)。它实时跟随 GET /api/graph/stream,而 HypSwarm 运行的遥测(<record>.telemetry.jsonl)会加入每次模型和工具调用。hypgraph export --telemetry 会把它放进记录包以便回放,位于哈希链之外;{play: true} 以回放模式打开。用 CSS 变量 --hg-* 设置主题。在在线示例中查看。

CI 中的记录包

hypgraph export -o record.bundle.json     # every event as the exact string that was hashed
hypgraph verify record.bundle.json        # exit 1 if anything was edited

发布结果时,把记录包的 head 哈希公布在你无法控制的地方(标签、论文、工单):之后经过该哈希的记录不可能改写任何更早的内容。审查者无需安装任何东西即可在 /verify 上检查记录包。

审查报告

大多数炒作存在于最终报告中,而不是记录里。hypgraph check 对照记录读取 markdown,出错时以 1 退出,因此智能体交付的摘要不能与真正被证明的内容相矛盾:

hypgraph check summary.md              # errors fail
hypgraph check --strict summary.md     # warnings (unsourced numbers …) fail too
错误能发现
REPORT_OVERSTATES_STANDING对记录中未核查、有争议或有风险的主张使用“已确立”/“已确认”
REPORT_CITES_WITHDRAWN把已撤回的主张当作仍然成立来引用
REPORT_UNKNOWN_CODE引用不存在的主张或结果
REPORT_ABSOLUTE_UNBACKED · REPORT_ABSENCE_UNBACKED · REPORT_SIGNIFICANCE_UNBACKED背后没有任何引用的从不 / 无效应 / 显著

警告:没有任何结果包含或蕴含的数字、被省略的争议、被取代的引用、没有引用的因果表述。代码块、行内代码、URL、引用的段落、否定(“无法证明”)和指令(“绝不要使用评估集”)不被视为主张 — 已在二十多份真实报告上校准,这些报告都对照其所报告的活跃记录进行了检查。在 Python 中:g.check_text(text, inv);通过 HTTP:POST /api/graph/check;面向智能体:MCP 工具 check_report。

拒绝日志

每条被拒绝的主张都会被记录 — 作者、陈述、代码 — 当同一作者以诚实版本回来时标记为已修正。这是别人无法给你的数字:你的智能体多常试图过度主张、哪些规则拦住了它们、哪些它们悄悄放弃了。

hypgraph refusals                      # per author and rule, fixed vs open
hypgraph refusals --author analyst     # one agent's refusals in full

只追加,有自己的哈希链(g.verify_refusals()),与记录的链分开。在 Python 中:g.refusal_report(inv);HTTP GET /api/graph/refusals;MCP refusal_log;以及 HypGraph 概览中被拒绝过度主张的计数。

性能

节点推导全部现状读取一个节点写入验证链
1,0010.047 s0.1 ms5.7 ms0.028 s
3,3010.095 s0.07 ms6.0 ms0.07 s
10,0010.37 s0.07 ms11.4 ms0.21 s

纯 Python,在一台 Windows 笔记本上用 python dev/bench.py --nodes N 测量(Python 3.13,hypgraph 0.6)。其记录是一项调查,包含问题、绑定到值的结果、由此推导的主张,以及对其中一部分的审查;推导与记录以相同速度增长。一次写入的开销取决于它触及的内容:快照共享未触及的数据,写入无法触及的每个节点的缓存现状都会保留(已用随机化测试套件对照完整重建进行检查)。写入的大部分时间是 SQLite 提交到磁盘。在你的机器上、用你的规模运行基准测试。