跳到文档内容
Anygent.ai文档

Agent for Science 入门:用 Codex / Claude Code 接续科研分析任务

用公开 Iris 数据走一遍可复核的科研分析:固定输入、命令和产物,再用 Anygent 在手机上接续同一会话。附 Python 示例、复核清单和失败恢复。

先确定分析边界

  1. 把 agentic science workflow 拆成可验收的小任务

    “Agent for Science”在这里指:人定问题和数据,Agent 协助读代码、跑分析、解释输出,人复核方法和结论。示例只算 Iris 的分组描述统计,不训练模型、不检验新假设,不能据此声称自主科学发现或超级智能。分析在你接入的电脑或服务器上执行,Anygent 提供会话、文件、终端和跨设备入口。

  2. 准备独立项目目录

    需要 Python 3.10 或更新版本,只用标准库,不必装数据科学依赖。在执行设备上新建并进入 iris-workflow 目录,准备好 Codex 或 Claude Code 实例和凭据;只想复核计算可直接运行脚本,不必接入平台。Windows 没有 python3 时,下文命令都改用 py -3。

    mkdir iris-workflow
    cd iris-workflow
    python3 --version
  3. 下载固定版本的数据

    从文末 UCI 官方数据包链接下载 iris.zip,把其中的 iris.data 放进当前目录;不要用 bezdekIris.data、网页复制的表格或 Agent 生成的数据。UCI 记录了版本间个别数据点的差异,本例固定 iris.data 的字节版本,SHA256 应为 6f608b71a7317216319b4d27b4d9bc84e6abd734eda7872b71a458569e2656c0。数据 150 行,含 4 个以厘米计的测量值和一个类别标签;引用 Fisher, R. (1936). Iris [Dataset]. UCI Machine Learning Repository,DOI 10.24432/C56C76,许可 CC BY 4.0。

把项目放进科研工作台

  1. 先选执行设备,再安排面板

    工作台保存的是面板布局,工作区才对应执行设备上的项目目录:给工作台起名 iris-workflow 不会创建目录、复制数据或安装 Python。目录和输入在目标设备上备好后,打开“工作台”,选已有的或新建一个。

  2. 把 Chat、File、Terminal 放一起

    从左侧栏把分析会话拖进工作台,或在空白面板选 Chat 再选设备、工作区和会话;点标签栏的“+”添加 File 和 Terminal,都选同一执行设备和 iris-workflow 工作区。桌面上右键面板标签,选“水平分割”或“垂直分割”排布。Chat 管任务和审批,File 看数据和结果,Terminal 查环境和输出。同名目录可能在不同设备上,逐个核对面板的设备和完整路径。

  3. 运行前核对目录和 Python

    在 Terminal 运行下面的只读命令:cwd 应是项目目录,input 指向其中的 iris.data,exists 为 True,并记下 Python 路径和版本。它不跑分析、不改文件、不校验哈希(交给后面的脚本)。设备或工作区列表为空,先查执行设备和 Agent 是否在线。终端里切目录或虚拟环境不会改变 Agent 会话的执行环境,批准 Agent 运行前也让它报告目录和 Python 版本。

    python3 -c "import sys; from pathlib import Path; print('cwd:', Path.cwd()); print('python:', sys.executable); print('version:', sys.version.split()[0]); print('input:', Path('iris.data').resolve()); print('exists:', Path('iris.data').is_file())"

运行一次可核对的分析

  1. 保存完整脚本

    把下面代码存为 UTF-8 文件 iris_summary.py,与 iris.data 同目录。它先核验输入哈希、行列数、类别计数和数值,再写出 summary.csv 和 provenance.json(记录数据来源、输入与脚本哈希、Python 版本和运行时间)。输出目录必须是新目录,免得重跑悄悄覆盖上次结果。

    """Reproduce a small descriptive analysis of UCI's iris.data (Python 3.10+)."""
    import argparse
    import csv
    import hashlib
    import io
    import json
    import math
    import platform
    from collections import Counter
    from datetime import datetime, timezone
    from pathlib import Path
    from statistics import mean
    
    SOURCE = "https://archive.ics.uci.edu/dataset/53/iris"
    EXPECTED_SHA256 = "6f608b71a7317216319b4d27b4d9bc84e6abd734eda7872b71a458569e2656c0"
    SPECIES = ("Iris-setosa", "Iris-versicolor", "Iris-virginica")
    COLUMNS = ("sepal_length_cm", "sepal_width_cm", "petal_length_cm", "petal_width_cm")
    
    
    def main():
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument("input", type=Path, help="Unmodified iris.data from UCI iris.zip")
        parser.add_argument("output", type=Path, help="A NEW result directory, e.g. results-01")
        args = parser.parse_args()
        raw = args.input.read_bytes()
        digest = hashlib.sha256(raw).hexdigest()
        if digest != EXPECTED_SHA256:
            raise ValueError("Input SHA256 differs; check the file/version before proceeding")
        rows = [row for row in csv.reader(io.StringIO(raw.decode("ascii"))) if row]
        if len(rows) != 150 or any(len(row) != 5 for row in rows):
            raise ValueError("Expected 150 rows, four measurements and one species label")
        if Counter(row[4] for row in rows) != Counter({s: 50 for s in SPECIES}):
            raise ValueError("Expected three species with 50 rows each")
        groups = {s: [] for s in SPECIES}
        for row in rows:
            values = [float(value) for value in row[:4]]
            if not all(math.isfinite(value) and value > 0 for value in values):
                raise ValueError("Measurements must be finite and positive")
            groups[row[4]].append(values)
        summary = []
        for species, values in groups.items():
            summary.append([species, len(values)] + [
                round(mean(row[column] for row in values), 3) for column in range(4)
            ])
        # A completed result is never silently overwritten. Use a new output name.
        args.output.mkdir(parents=True, exist_ok=False)
        with (args.output / "summary.csv").open("x", encoding="utf-8", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(["species", "n"] + ["mean_" + name for name in COLUMNS])
            writer.writerows(summary)
        manifest = {
            "source": SOURCE,
            "citation": "Fisher, R. (1936). Iris [Dataset]. UCI ML Repository. doi:10.24432/C56C76",
            "license": "CC BY 4.0",
            "input": str(args.input.resolve()),
            "input_sha256": digest,
            "script_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
            "python": platform.python_version(),
            "rows": len(rows),
            "columns": [*COLUMNS, "species"],
            "created_at_utc": datetime.now(timezone.utc).isoformat(),
        }
        (args.output / "provenance.json").write_text(
            json.dumps(manifest, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
        )
        print(json.dumps({"rows": len(rows), "output": str(args.output), "summary": summary}))
    
    
    if __name__ == "__main__":
        main()
  2. 先让 Agent 说明要做什么

    在 Codex 或 Claude Code 会话里选中这台设备和 iris-workflow 目录,发下面的提示,核对它说的目录、文件和命令后再批准。两种 Agent 都能围绕这套文件协作,模型输出、可用工具和审批策略取决于实例配置。这是给你用的提示示例,不是已替你执行的账号内任务。

    请只读检查当前工作目录中的 iris.data 和 iris_summary.py,说明脚本的输入校验、输出文件和运行命令。先不要修改文件、下载数据、安装依赖或运行分析。确认目录与脚本无误后,等待我批准再执行;不要更改预期哈希来跳过错误。
  3. 运行并保留输出

    确认后在终端或经批准的 Agent 操作中运行下面的命令。进程应正常退出,并生成 results-01/summary.csv 和 results-01/provenance.json;只看到“开始执行”不算成功,要核对退出状态和这两个产物。

    python3 iris_summary.py iris.data results-01
  4. 按数据和单位复核

    本示例发布前用上述 UCI iris.data 实际跑过:summary.csv 每类 n 应为 50,mean_sepal_length_cm 依次为 5.006、5.936、6.588。这是该固定样本的萼片长度均值(cm),不是分类准确率或总体推断。打开 CSV 核对列名和顺序(别只看 Agent 的总结),再查 provenance.json 的输入哈希和 Python 版本;结果不符先查版本、字段和运行记录,别改参考答案。

    species,n,mean_sepal_length_cm
    Iris-setosa,50,5.006
    Iris-versicolor,50,5.936
    Iris-virginica,50,6.588
  5. 写交接记录

    在项目目录写 HANDOFF.md,记下工作目录、执行命令、已完成产物和下一步,不写账号密钥;数据和代码按项目的版本管理方式保存。接续时以实际产物和运行记录为准,聊天记录只帮助解释过程。

    # Iris 分析交接
    输入:iris.data(版本以 results-01/provenance.json 的 SHA256 为准)
    脚本:iris_summary.py
    命令:python3 iris_summary.py iris.data results-01
    已完成:summary.csv、provenance.json;请填写实际退出状态和复核结果
    下一步:先复核列名、单位、每组数量,再决定是否增加离散程度统计
    限制:没有训练模型,没有进行显著性检验,没有验证新科学结论

离开电脑后继续同一个任务

  1. 手机打开原会话,先只读核对

    手机登录同一 Anygent 账号,找到刚才的 Codex 或 Claude Code 对话,核对执行设备和项目目录;电脑或服务器及其 Agent 必须在线。先让 Agent 只读检查交接记录和结果文件,再决定下一步计算。

    请只读查看 HANDOFF.md、results-01/provenance.json 和 results-01/summary.csv。报告当前目录、输入哈希、三个类别的样本数与萼片长度均值,并指出交接记录有没有未核实事项。不要修改文件或重新运行分析。
  2. 本机 Codex 历史先导入

    分析只在电脑本机的 Codex 里做过、平台会话列表里没有时,按 Codex 会话教程从“对话主机管理”导入历史,核对执行目录后再决定是否启动(导入默认不启动)。新建空白实例不等于接续原分析;其他 Provider 的导入方式不一定与 Codex 相同。

让接手者独立复核产物

  1. 手机查看:分清消息、进程和结果

    历史聊天或“开始执行”消息只说明有记录,锁屏重连后的页面也不代表进程已结束。回原会话核对设备和目录,再看实际退出状态、summary.csv 和 provenance.json;结果目录也可能是中断后的部分输出。等执行者写完并保留原脚本再复核。

  2. 保存只读核验脚本

    把下面代码存为 verify_iris.py。它不导入或执行 iris_summary.py、不重跑分析、不写结果文件,而是核对当前输入 / 脚本与运行记录的哈希,并从固定输入独立重算三类各四列均值。拿到完整结果副本也能跑,provenance.json 里原设备的绝对路径只作来源记录。它不证明科学方法正确、数据真实或记录没被一起恶意改写,人工复核仍要保留。

    """Read-only check of this tutorial's completed Iris run (Python 3.10+)."""
    import argparse
    import csv
    import hashlib
    import io
    import json
    from decimal import Decimal, ROUND_HALF_EVEN
    from pathlib import Path
    
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('input', type=Path)
    parser.add_argument('script', type=Path)
    parser.add_argument('results', type=Path)
    args = parser.parse_args()
    
    def require(ok, message):
        if not ok:
            raise SystemExit('CHECK FAILED: ' + message)
    
    raw = args.input.read_bytes()
    digest = hashlib.sha256(raw).hexdigest()
    require(digest == '6f608b71a7317216319b4d27b4d9bc84e6abd734eda7872b71a458569e2656c0',
            'input is not the reference iris.data')
    record = json.loads((args.results / 'provenance.json').read_text('utf-8'))
    require(record['input_sha256'] == digest, 'input and provenance disagree')
    require(record['script_sha256'] == hashlib.sha256(args.script.read_bytes()).hexdigest(),
            'script changed since this run; preserve the original script for review')
    require(record['rows'] == 150, 'provenance row count differs')
    # Recalculate from the raw data without importing or executing the analysis script.
    source = [r for r in csv.reader(io.StringIO(raw.decode('ascii'))) if r]
    columns = ['sepal_length_cm', 'sepal_width_cm', 'petal_length_cm', 'petal_width_cm']
    with (args.results / 'summary.csv').open(newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        require(reader.fieldnames == ['species', 'n'] + ['mean_' + c for c in columns],
                'CSV column names/order differ')
        output = list(reader)
    species = sorted({r[4] for r in source})
    require(sorted(r['species'] for r in output) == species, 'missing/duplicate species')
    for row in output:
        group = [r for r in source if r[4] == row['species']]
        require(int(row['n']) == len(group), 'group size differs')
        for i, column in enumerate(columns):
            expected = (sum(Decimal(r[i]) for r in group) / len(group)).quantize(
                Decimal('0.001'), rounding=ROUND_HALF_EVEN)
            actual = Decimal(row['mean_' + column])
            require(actual.is_finite() and actual == expected,
                    row['species'] + ': ' + column + ' mean differs')
    print('CHECK OK: input/script provenance and 3 groups x 4 means match; no files written')
  3. 在原设备或完整副本上核验

    运行后退出码为 0 且输出 CHECK OK,才表示本例所列检查通过;缺文件或哈希、列名、样本数、均值不符时应非零退出,先保留原产物查原因,别让 Agent 改参考值让检查变绿。本文验证过正常结果和五条失败路径(错误输入、脚本变更、错误均值、错误样本数、缺失运行记录),但这不证明账号内手机或多 Agent 运行已完成。

    python3 verify_iris.py iris.data iris_summary.py results-01
  4. 多 Agent 科研协作:分清执行与复核

    执行者负责一个新结果目录,复核者只读检查已完成的输入、原脚本、产物和运行记录,由人审阅差异后决定下一轮。不同设备上的同名路径不是同一份文件,要讲清交接哪些文件、谁能访问。别让两个 Agent 同时改同一结果目录,重新分析就用新目录并记下脚本版本。项目和 Issue 可记录分工与验收,不代替文件传递或科学验证。

    请作为只读复核者,先核对设备、目录和 HANDOFF.md;确认执行者已完成写入,再运行 python3 verify_iris.py iris.data iris_summary.py results-01。报告命令、实际退出码、输出与未核实事项。不要修改脚本/数据/产物,不重新运行分析;缺文件或检查失败就停止并说明。

失败恢复与下一项真实分析

  1. 输入、环境或输出目录报错

    找不到 Python:查执行设备上的安装和版本。找不到文件:查终端和 Agent 的工作目录。哈希不符:核对下载来源、是否错用 bezdekIris.data、是否改过换行或内容,别让 Agent 改校验常量掩盖差异。results-01 已存在:先检查原产物,改用 results-02。中途退出的不完整目录留着排查,换新目录重跑;本例没有自动断点续算。

    python3 iris_summary.py iris.data results-02
  2. 设备离线与分析失败分开处理

    能看到历史不代表电脑在线。设备休眠、断网或 Agent 停止时,先恢复设备和连接,再核对原进程是否还在跑、结果是否完整,别重复启动长任务。刷新手机唤不醒离线设备,接续会话也不会自动恢复任意 Python 程序的内存状态。

  3. 换成自己的课题:保留验收标准

    这个小样例只验证流程,不能证明某个 Agent 的科研能力。换数据前写清研究问题、许可与敏感数据边界、字段和缺失值规则、环境版本、计算预算、输出文件和人工复核责任;加入模型或假设检验时,还要查数据泄漏、验证集划分、随机种子、统计假设和不确定性。先用能独立核对的小任务验证,再扩大规模。

注意事项

  • 实测过的只有公开数据上的脚本和统计输出;手机接续部分是操作步骤和提示示例,不代表已替你完成设备接入、账号内 Agent 执行或科学实验。
  • 真实科研项目的源数据、代码、环境和结果按项目要求归档;输入哈希只证明字节相同,不证明数据真实、方法正确或结论可靠。

参考资料