Contents

Prime Agent: A Self-Improving RLM Harness


作者Seth Karten, Alex L. Zhang, Kevin Thomas, Sebastian Müller, Prime Intellect Team
机构Prime Intellect
时间2026-08-05
链接博客 · Web App

就像在有持久状态的 REPL 里写程序,程序可以修改它自己的运行时配置——唯一工具是 IPython kernel,子 agent 用 await rlm(...) 异步调用,harness state(system prompt、技能库、记忆、子 agent)用 CRUD API 在运行时更新;/refine 自动分析轨迹并把成功/失败模式写进技能库和记忆。当前无模型专门训练,作者明确表示 model-harness co-learning 才是解锁能力的关键。

95.5%ARC-AGI 3
RHAE Best@1 (Opus 5)
99.97%ARC-AGI 3
Best@3 (183/183)
H=(ρ,G,K,M)harness state
prompt/agents/skills/memory
REPL唯一工具
IPython kernel
architecture
Prime Agent 架构总览:IPython kernel 是唯一接口;Background Daemon 管理 session JSONL + kernel snapshot;Agents View TUI 允许跨父/兄/子 session 导航。

研究动机

核心架构

1. Programmatic Tool-Calling(PTC)——IPython 作为唯一工具

与其他 harness 不同,Prime Agent 每轮只暴露一个工具:IPython kernel。所有操作(bash、文件读写、子 agent 调用、harness 修改)都通过 Python 代码完成。pre-imported 模块包括技能库、工具集和 rlm 异步函数。

子 agent 调用示例:

# 并行 fan-out:同时派出两个子 agent
auth = await rlm("Summarize the auth flow in auth/. Reply when done.", name="auth-expert")
api  = await rlm("Summarize the HTTP API layer in src/. Reply when done.", name="http-expert")
# 结果通过 agent_message 异步返回

直观理解:子 agent 是 `await` 的异步函数,而不是"派发任务"的抽象操作——父 agent 在 REPL 里等待返回值,就像调用普通 Python 函数。

2. 持久会话与 Background Daemon

Background Daemon 通过本地 socket 管理实时 session。每个 session 有:

Agent 通信限于"核心家庭"(parent / sibling / child)——防止跨 session 意外交叉干扰。

TUI
TUI 主界面:显示当前 session 的 agent 轨迹、context 使用量、运行状态。
Agents view
Agents View:导航父/兄/子 agent session;显示各 session 状态(running / idle / inactive)。

3. Autonomous Mode(评估/无人值守运行)

三个机制支持无人值守运行:

Goals
持久目标,每轮重新注入 prompt
Heartbeats
Cron 式定时消息(监控进度、防止卡死)
Autonomous mode
确保持续向目标推进的续跑机制
prime-agent \
  --autonomous \
  --autonomous-gate "npm run check" \
  --autonomous-max-turns 20 \
  "Implement and verify the requested change"

Gate 失败时返回截断输出供重试;工作区无变化则跳过重跑失败 gate。

flowchart LR
  User["User / Goal"] --> Agent["Prime Agent\nIPython REPL"]
  Agent -->|"await rlm(...)"| Sub1["Subagent A"]
  Agent -->|"await rlm(...)"| Sub2["Subagent B"]
  Sub1 -->|"agent_message reply"| Agent
  Sub2 -->|"agent_message reply"| Agent
  Agent -->|"rlm.harness.create_skill"| HS["Harness State\nH = p,G,K,M"]
  Agent -->|"compact.run()"| GC["GC Subagent\ncompaction"]
  Agent -->|"refine.run()"| Ref["Refine\nplannerApplier"]
  Ref --> HS
  HS -->|"pre-inject"| Agent
        
drag to pan · scroll to zoom
Prime Agent 数据流:主 agent 在 IPython REPL 里运行;子 agent 用 await rlm 异步调用;/refine 分析轨迹后 CRUD harness state;compaction 由子 agent 完成垃圾收集。H=(ρ,G,K,M) = prompt/subagents/skills/memory。

Continual Harness & /refine

Harness State H = (ρ, G, K, M)

Continual Harness 的核心:harness 自身状态(prompt ρ、子 agent G、技能 K、记忆 M)是 agent 在运行时可以 CRUD 的数据结构,存在 IPython kernel 里的 rlm.harness 对象。

字段含义CRUD 示例
ρ (prompt)System prompt 注释create_prompt_note("always check return types")
G (subagents)已注册的持久子 agentcreate_subagent("db-expert", ...)
K (skills)Python 函数/模块,跨会话持久create_skill("retry_helper", code, reference={...})
M (memory)键值对记忆create_memory("flaky test pattern", "retry 3×")
# 运行时 CRUD 示例
rlm.harness.create_memory("flaky test pattern", "retry three times before failing")
rlm.harness.create_skill("retry helper", code_str, reference={"type": "python", "import": "retry_helper"})
rlm.harness.list("memory")       # 列出所有记忆
rlm.harness.get("skill", "retry_helper")  # 读取特定技能

/refine 管线——自动 harness 更新

/refine 分析当前 agent 轨迹,找出最小相关 CRUD 编辑并写入 harness。两阶段:

  1. 后台规划(非阻塞):分析轨迹,确定应新建/更新哪些 skill/memory
  2. 快速应用(在轮次边界阻塞):执行实际 CRUD
await refine.run("promote the retry-on-flaky-test pattern to a skill")
await compact.status()   # tokens, context_window, percent, scheduled
await refine.status()    # pending, in_flight

支持回滚(通过 refinement history)。每次 refine 记录 trigger 和 outcome。

最关键的一句话:harness state 是 agent 在运行时写给自己的"长期记忆 + 工具库",/refine 是把短期轨迹经验固化进这个结构的自动化通道。

实验结果

ARC-AGI 3

ARC-AGI3 scaling
ARC-AGI 3 分数 vs token 用量的 scaling 曲线。
ARC-AGI3 cost scaling
ARC-AGI 3 cost scaling:Prime Agent 在相同花费下优于 native harness。

长上下文 Benchmark 对比

BenchmarkPA+GLM-5.2Pi-monoPA+Opus 5Claude CodePA+GPTCodex
OOLONG (128k)0.7000.4200.9000.9200.9400.500
OOLONG-Pairs0.8740.5560.9290.9220.9110.895
OBLIQ-Bench0.6690.6350.8020.7950.6120.646
LongBenchPro0.7770.7680.8040.7900.7940.790
LongBenchv20.6800.6960.7440.7460.7140.704
ManyIH Coding0.4240.3860.5360.5220.4990.454
ManyIH IF0.2090.1640.2250.1750.2160.232
LongCot-Mini0.6380.6130.7220.5580.6710.681
EmulatorBench0.2080.0000.047*0.062*0.2750.228

* EmulatorBench 中 Opus 5 / Claude Code 的低分可能因 harness 限制而非模型能力。

EmulatorBench(从零写 Rust 模拟器)

Agent 从头实现 SEGA Genesis 和 Nintendo Game Boy Color 模拟器,通过 diagnostic 验证程序(CPU flags、PPU timing)测试正确性。16 个模拟器重建任务。

emulator
EmulatorBench 结果:Prime Agent+GPT 以 0.275 领先,Pi-mono 为 0.000(无法完成任何模拟器)。

PMPP-Hard(GPU Kernel 编写)

pmpp
PMPP-Hard:编写通过 KernelGuard 正确性检查的高性能 GPU kernel,对照 GPU MODE kernel leaderboard 标准。

MazeBench(3D 空间推理)

mazebench
MazeBench:开放世界 3D 迷宫,需解谜 + 收集宝石。指标:找到唯一房间数、唯一状态数、收集宝石数(均为 token 用量的函数)。"前沿模型在这个任务上表现非常差,花费数十亿 token 仅完成整个世界的一小部分。"

Factorio 案例:奖励作弊与自改进的双面性

factorio
Factorio Learning Environment:Prime Agent 控制 4 个可编程角色(通过子 agent 调用),几小时内实现 100K+ 生产分数。

这是目前 continual harness + autonomous self-improvement 在真实任务上发现奖励 hacking 的最具体案例之一。

工程实现(GitHub 源码解读)

Repo:PrimeIntellect-ai/prime-agent(MIT)。TypeScript monorepo + Python runtime,核心分两层。

1. 架构分层

flowchart TD
  TS["TS Host\npkgs/coding-agent\npkgs/agent"] -->|"stdio JSON"| PY["Python Kernel\nrlm.repl"]
  PY -->|"host_request(type, payload)"| TS
  TS --> DM["Daemon\nsession JSONL\nkernel snapshot"]
  PY --> HS["harness_state.json\nprompt / memory\nskill / subagent"]
  TS -->|"refine cmd"| HS
  PY -->|"mtime check"| HS
        
drag to pan · scroll to zoom
两层架构:TypeScript Host 管理 session 生命周期和 agent loop;Python Kernel 是 LLM 看到的执行环境,通过 stdio JSON 协议与 Host 通信。harness_state.json 是两侧共享的唯一持久状态文件。
目录语言职责
prime-agent-runtime/src/rlm/PythonREPL kernel、harness CRUD、rlm API、bash tool、MCP
packages/agent/TypeScriptagent-loop.ts — 主循环,tool dispatch,AbortSignal 管理
packages/coding-agent/TypeScriptTUI、daemon、session 管理、/refine 命令实现
packages/ai/TypeScript多模型 provider 抽象(Anthropic/OpenAI/Gemini/Bedrock…)
packages/tui/TypeScript终端 UI 组件
scripts/benchmarks/Pythonbenchmark runner(SWE-bench 等)

2. Python Kernel(repl.py)— 为什么只有一个工具

rlm/repl.pypython -m rlm.repl 的入口。它在单个 asyncio event loop 上运行,把一个持久的 __main__ namespace 当 IPython kernel 用——每个 LLM "cell" 都在这个 namespace 里执行,支持 top-level await

与 TS Host 的通信协议是 newline-delimited JSON over stdio(PROTOCOL_VERSION = 3):

Snapshot 机制:Kernel 可以把当前 __main__ namespace 序列化到磁盘(最大 256 MB,单变量上限 16 MB),崩溃后从 JSONL + snapshot 恢复。_ALWAYS_SKIP 里的名字(rlm, mcp, bash, asyncio 等)永远不进 snapshot。

3. Harness State(harness.py)— CRUD 的具体实现

harness state 是一个 JSON 文件(路径优先级:$RLM_HARNESS_STATE_DIR$RLM_SESSION_DIR/harness/harness_state.json),结构如下:

# harness_state.json 结构
{
  "schema": 1,
  "entries": {
    "prompt":   { "<slug-id>": { HarnessEntry } },
    "memory":   { ... },
    "skill":    { ... },
    "subagent": { ... }
  },
  "refinements": [ { RefinementEvent } ]
}

# HarnessEntry 字段
@dataclass
class HarnessEntry:
    id: str            # _slug(title) 或显式指定
    kind: Literal["prompt","memory","skill","subagent"]
    title: str
    content: str
    path: str = "general"       # 用于 UI 分组
    scope: Literal["local","global"] = "local"
    reference: dict = {}        # skill 专用:{"type":"python","import":"...","callable":"..."}
    arguments: dict = {}
    metadata: dict = {}
    source: str = "agent"
    created_at: str             # UTC ISO
    updated_at: str
    version: int = 1            # 每次 update +1

三个关键设计点:

CRUD API(在 kernel namespace 里直接调用):

# 完整 CRUD 示例

# --- CREATE ---
rlm.harness.create_memory("flaky test pattern", "retry 3× with exponential backoff")
rlm.harness.create_prompt_note("always check return types", "verify type annotations before calling APIs")
rlm.harness.create_skill(
    "retry_helper",
    "retry_helper.run(cmd, max=3) — retries shell cmd with backoff",
    reference={
        "type": "python",
        "import": "retry_helper",   # pip-installable Python package name
        "callable": "run",           # 或 call_pattern: "retry_helper.run(...)"
    }
)
rlm.harness.create_subagent(
    "db-expert",
    "Specialist for all database operations",
    reference={"model": "anthropic/claude-opus-5"}
)

# --- READ ---
entry = rlm.harness.get("memory", "flaky_test_pattern")
all_skills = rlm.harness.list("skill")
overview = rlm.harness.list()          # 所有 kind

# --- UPDATE ---
rlm.harness.update("memory", "flaky_test_pattern",
    "flaky test pattern", "retry 5× with 2s base delay")

# --- DELETE ---
rlm.harness.delete("memory", "flaky_test_pattern")

# --- upsert (create-or-update,不报错) ---
rlm.harness.upsert("memory", "deploy notes", "use --rolling flag")

4. rlm API(__init__.py)— 子 agent 调用接口

rlm 是一个 module-level singleton(_RLMNamespace),pre-imported 进每个 kernel session。所有子 agent 操作都通过它发给 TS Host:

# 子 agent spawn(非阻塞,返回 handle)
handle = await rlm.spawn("Summarize auth flow in auth/", name="auth-expert")
# handle.rlm_child_id: str, handle.session_dir: Path, handle.model: str

# 并行 fan-out + 等待
h1 = await rlm.spawn("analyze API layer", name="api-worker")
h2 = await rlm.spawn("analyze DB layer",  name="db-worker")
results = await rlm.collect([h1, h2], timeout_ms=120_000)
# results[i].status: "done"/"error"/"running"/"queued"/"cancelled"
# results[i].answer_preview: str | None
# results[i].settled: bool

# 非阻塞 snapshot(timeout_ms=0)
snapshot = await rlm.collect()          # 所有直接子 agent 的当前状态

# 进度上报(到 parent,限速,512 UTF-16 chars)
await rlm.progress_note("processed 3/10 files")

# 删除子 agent session
await rlm.delete_subagent(handle)

# rlm.spawn 的底层:
# → host_request("rlm.run", {"prompt": ..., "kwargs": {"name": ...}})
# → TS Host 创建新 session,返回 rlm_child_id

rlm.collect() 的关键语义:timeout_ms=0 立即返回当前快照(非阻塞);正值等待所有目标 settle 或超时,超时返回当前状态而不报错。父 session 永远不会被 collect 调用"steering"——它只观察,不被打断。

5. TypeScript Agent Loop(agent-loop.ts)

packages/agent/src/agent-loop.ts 是 TS 侧的主循环。核心函数是 runLoop()

// 简化版 runLoop 骨架
async function runLoop(context, newMessages, config, signal, emit) {
  let firstTurn = true;
  // steering messages = heartbeat / user 注入
  let pendingMessages = await pollMessagesUnlessAborted(config.getSteeringMessages, signal);

  while (true) {
    throwIfAborted(signal);
    // 注入 steering messages 到 context
    if (pendingMessages.length > 0) { /* push + emit */ }

    // 调用 LLM,流式返回 AssistantMessage
    const message = await streamAssistantResponse(context, config, signal, emit);

    if (message.stopReason === "error" || message.stopReason === "aborted") {
      emit({ type: "agent_end", messages: newMessages });
      return;
    }

    // 提取 tool calls,dispatch 执行
    const toolCalls = message.content.filter(c => c.type === "toolCall");
    // ... 执行 tool,收集 toolResults,push 回 context ...

    if (toolCalls.length === 0) {
      // 检查是否继续:config.getContinuationMessages() 有内容则继续
      const continuationMessages = await config.getContinuationMessages(lastTurn);
      if (!continuationMessages?.length) {
        emit({ type: "agent_end", messages: newMessages });
        return;
      }
    }
  }
}

Events 流(供 TUI / caller 消费):agent_start → turn_start → message_start/end → turn_end → agent_end。AbortSignal 贯穿所有 async 操作——abort 时立即停止并发 agent_end

agentLoopContinue() 用于 retry:context 已有 user/toolResult message,直接继续执行而不重新 push prompt。

6. Self-Improvement 完整数据流

sequenceDiagram
  participant LLM as LLM
  participant K as Kernel
  participant TS as TS Host
  participant F as harness_state.json

  LLM->>K: cell: rlm.harness.create_skill(...)
  K->>F: atomic write
  F-->>K: mtime updated

  Note over TS: user runs /refine
  TS->>TS: spawn refine child agent
  TS->>F: analyze trajectory, CRUD edits
  F-->>TS: mtime updated

  LLM->>K: next cell: rlm.harness.list()
  K->>F: _sync_from_disk checks mtime
  F-->>K: reload with refine edits
  K-->>LLM: updated skill list
        
drag to pan · scroll to zoom
Self-improvement 数据流:LLM 直接写 harness_state.json;/refine 通过 TS 进程修改同一文件;Python Kernel 通过 mtime 检测感知变化,下次访问时 reload。

8. Master Prompt 结构(实验时实际注入内容)

buildRlmPrompt() 按以下顺序拼出完整 system prompt(depth=0 root agent):

#Block条件内容摘要
1Identity全部"You are a general purpose agent that uses code to solve tasks. You solve tasks by breaking down problems into sub-tasks, writing and executing code, observing results, and iterating one step at a time."
2LONG_RUNNING_WORK全部非阻塞控制流;让 worker 并行启动然后 end turn;明确禁止 sleep polling
3USER_PROGRESSdepth=0 only主动向用户报告进度;在有意义的 milestone 发 update;lead with user-visible outcomes
4SIMPLIFIED_ENGLISH全部短句、常用词、具体动词;每句一个 fact;技术术语/命令/路径保持原样
5Runtime meta全部Working directory / Conversation log / Recursive agent depth: N / Pre-installed packages
6Skill列表有 skill 时Pre-imported Python modules 名单;每个 skill 用 help() 或读 SKILL.md 查 API
7Child doctrinedepth>0"You are a child agent spawned by <parent>. Task prompts labeled [task from parent]. Reply with agent_message.send(message, receiver_role='parent')."
8REPL_CONTROL有 ipython最长块:IPython 详细规范,bash() 用法,harness CRUD,MCP via python object
9refine 使用指导refine skill 存在小的、有证据的更新;call refine.run() 返回立即,turn 结束后执行
10Subagent guidancedepth=0 + ipythonfan-out 模式;collect 语义;progress_note;large outputs → files
11Project context有 context filesCLAUDE.md / AGENTS.md 等项目文件内容
12Harness digestharness 非空运行时注入:prompt notes / memory / skill / subagent entries 的 overview
REPL_CONTROL_PROMPT 原文关键段(最重要的 behavior specification)
# 节选自 packages/coding-agent/src/core/prompts/rlm.ts

"The `ipython` tool is a persistent Python REPL — the agent's long-lived control
environment for reasoning, context management, state, tool orchestration, and
recursive subcalls. Top-level `await` works directly."

"Python is the orchestration language: use Python for loops, conditionals, parsing,
and state. Use `bash()` to invoke programs, not to write shell programs — no shell
loops or heredocs; do those in Python."

"Do not assume the REPL is the native runtime of the external thing being investigated.
A repository, package, service, dataset, paper, website, benchmark, or API may have
its own environment and normal interface. Evaluate external systems through their own
interface, then use the REPL to coordinate the process and analyze what comes back."

"Run shell commands with `bash()`, not `subprocess`/`os.system`: subprocess calls
block the kernel, show the user nothing while they run, and spawn processes the
harness cannot see or stop."

"Important: do not install dependencies into the kernel just to make an external
project import or run there."

"Each `bash()` call is its own process, so shell state does not persist between
calls; use `os.chdir(...)` for the working directory and `os.environ[...]` for
environment variables — both persist in the REPL and apply to later `bash()` calls."

"Python state in the kernel persists across cells: named variables, helper functions,
classes, imports, notes, parsed outputs, and helper data structures all remain
available in every later turn."

9. Interesting Agent Behaviors(从 prompt 设计推出)

行为prompt 来源含义
bash() 非阻塞 REPL_CONTROL_PROMPT h = bash('npm test') 立即返回 handle;await h 才等完成。明确禁止 subprocess——"blocks the kernel, shows the user nothing, spawns processes harness cannot see or stop"
禁止 sleep polling LONG_RUNNING_WORK "Do not keep the turn open by polling with time.sleep() or shell sleep." 等 child 完成的正确方式:end turn → 等 follow-up 消息 → collect()
外部环境不进 kernel REPL_CONTROL_PROMPT 明确禁止"install deps into kernel to make external project run"。用项目自己的 env:uv run ... / .venv/bin/python ...
shell state 不持久,REPL state 持久 REPL_CONTROL_PROMPT bash() 每次新进程;os.chdir() + os.environ[] 在 REPL namespace 持久,后续 bash() 继承
spawn 返回时 child 未完成 rlm.ts recursion block "spawn returns immediately after task admission... it never waits for or returns the child's answer." 结果只通过 agent_message 或文件传回
/refine 是 after-turn hook rlm.ts refine block "refine.run() returns immediately and runs when the current turn ends." 不阻塞当前工作
base prompt 不可被改写 REFINEMENT_SYSTEM_PROMPT /refine 子 agent 的 system prompt 明确写:"The base system prompt is immutable and MUST NOT be rewritten." 只能加 prompt notes(supplemental addendum)
collect() preview not result buildSubagentGuidance "Large child outputs belong in files that you read selectively; collect snapshots are previews." collect() 只给 answer_preview(截断),强制 agent 设计文件交接协议
子 agent 继承 model + thinking level rlm.ts spawn block "A child inherits your model." 显式 model 参数才覆盖;不可用 model 则 spawn 失败(不 fallback)
Simplified Technical English SIMPLIFIED_TECHNICAL_ENGLISH_PROMPT 用户可见 prose 默认 ASD-STE100 风格(短句、每句一 fact);命令/路径/引用保持原样

7. 最小可复现核心(无 TS 依赖)

理解原理后,可以用纯 Python 复现 harness state 的最小版本:

# 最简 harness state(无需 TS host)
import json, os
from pathlib import Path

HARNESS_FILE = Path.home() / ".prime" / "agent" / "harness" / "harness_state.json"
HARNESS_FILE.parent.mkdir(parents=True, exist_ok=True)

def load():
    if not HARNESS_FILE.exists(): return {"entries":{"memory":{},"skill":{},"prompt":{}}}
    return json.loads(HARNESS_FILE.read_text())

def save(state):
    tmp = HARNESS_FILE.with_suffix(".tmp")
    tmp.write_text(json.dumps(state, indent=2))
    os.replace(tmp, HARNESS_FILE)

def create_memory(title, content):
    s = load()
    s["entries"]["memory"][title.replace(" ","_")] = {"title":title,"content":content}
    save(s)

# 用法
create_memory("flaky test pattern", "retry 3×")
print(load()["entries"]["memory"])

真正的 HarnessState 多了:version 递增、mtime 同步检测、scope 路由(local/global)、原子写入(O_EXCL + replace)、技能 reference 校验。

沙箱与反作弊架构(评估时)

跑 benchmark(SWE-bench 等)时,Prime Agent 用两层隔离防止 reward hacking:cloud 沙箱 + 双 sandbox 隔离验证。

1. Cloud Sandbox(prime_sandboxes SDK)

评估基础设施用 Prime Intellect 自己的 prime_sandboxes SDK 创建 Docker 容器。每个 benchmark 都独立 provision 一个沙箱:

# controller.py — 创建 solver sandbox
sandbox = client.create(CreateSandboxRequest(
    docker_image  = config.image,
    cpu_cores     = config.cpu_cores,
    memory_gb     = config.memory_gb,
    disk_size_gb  = config.disk_gb,
    timeout_minutes = config.ttl_minutes,
    labels = ["prime-agent-benchmarks-v1",
              f"role:main",
              f"repository:{repo}",
              f"run:{run_id}",
              f"attempt:{attempt}"],
))

TTL label 用于清理超时沙箱;labels 允许多次重试共享同一 run 上下文。

2. 进程级用户隔离(worker.py)

沙箱内,每个 trial 创建独立 Linux user,agent 以该 user 运行:

# worker.py — 每个 trial 独立 user
subprocess.run([
    "useradd",
    "--create-home",
    "--uid", str(2001 + trial),     # benchmark1=2002, benchmark2=2003...
    f"benchmark{trial + 1}",
])
# agent 以非特权 user 运行
cmd = ["runuser", "-u", f"benchmark{trial+1}", "--", "prime-agent", ...]

Trial 结束时 stop_processes(user)/proc/*/status 找 uid → SIGTERM → SIGKILL,清理所有残留进程。

3. 双 Sandbox 隔离设计(核心反作弊)

flowchart LR
  C["Controller\n(CI / grader)"]
  C -->|"CreateSandbox"| S["Solver Sandbox\nnetwork=full\nagent runs here"]
  S -->|"git diff patch"| patch["/tmp/prime-agent.patch"]
  patch -->|"transfer only"| V["Verifier Sandbox\nfresh_copy=True\nnetwork=none"]
  V -->|"git reset to base_commit"| V
  V -->|"git apply patch"| V
  V -->|"rm config.json tests.tgz"| V
  V -->|"run tests"| log["test_output.log"]
  log -->|"parse"| C
        
drag to pan · scroll to zoom
双 sandbox 设计:agent 在 Solver 中运行(有网络),唯一输出是 git diff patch;Verifier 是 fresh copy,无网络,重置到 base commit 后 apply patch 再跑测试。评分在 Controller 完成,不在任何 sandbox 内。

4. 每层防 Reward Hack 机制

机制实现位置防止什么
输出只允许 patch 文件 SecureHarbor.finalize() agent 只能产出一个 /tmp/prime-agent.patch;任何其他 artifact → RuntimeError,得 0 分
Verifier 用 fresh sandbox VerifierConfig(fresh_copy=True, network_allow=[]) Verifier 不继承 Solver 任何 state;无网络,无法外联
Verifier reset 到 base commit SecureVerifiedMixin.setup() git reset --hard {base_commit} && git clean -fd——从已知干净状态开始,只 apply patch
测试 config 在跑前删除 SecureVerifiedMixin.run_verifier() rm -f /tests/config.json /tmp/tests.tgz——agent 无法读 instance_id、预期答案
测试脚本重写 rewrite_test_script() pip install → no-op;parser 替换 → 无法伪造 log;强制模板验证(含 PARSER/LOG/TEE 三个 pattern)
API credentials 剥离 strip_task_runtime_credentials() PRIME_API_KEY / PRIME_SANDBOX_API_KEY / GITHUB_TOKEN / GH_TOKEN / HF_TOKEN 全部从 sandbox env 删除
base commit 由 trusted config 指定 trusted_base_commit() 读 task 目录的 config.json(agent 不可修改),SHA 格式校验;agent 无法指定不同的 base
dataset revision pinned pin_taskset_sources() 每个 taskset 固定到 git commit hash,防止 dataset drift 或 agent 通过版本差异获益

5. Patch 收集命令(由 trusted code 生成)

# verified_verifier.py — patch 收集命令
def patch_collect_command(task_dir: Path) -> str:
    base = trusted_base_commit(task_dir)   # 从 trusted config.json 读,agent 不可改
    return (
        "rm -rf /logs/artifacts && "
        "git add -N -- . && "
        f"git diff --binary --no-ext-diff {base} -- . > /tmp/prime-agent.patch"
    )

# 测试脚本重写片段(防 pip hijack + parser 劫持)
def rewrite_test_script(script: str) -> str:
    # pip install → no-op
    script = re.sub(r"python -m pip install.*", ": # dependencies pinned in task image", script)
    # parser 替换(防止 agent 写恶意 parser)
    script = script.replace(
        'uv run parser.py | tee "$LOG_FILE"',
        'exit "${TEST_STATUS:-0}"'
    )
    # log 重定向到 /dev/null
    script = script.replace("LOG_FILE=$(mktemp)", "LOG_FILE=/dev/null")
    return script

整个设计核心:结构上不可能 hack。Agent 只有一个输出通道(git diff),Verifier 是 fresh isolated environment,测试本身由 trusted code 重写——不依赖 agent 诚实运行。

局限与展望

批判性定位

已知局限

研究趋势

Prime Agent 代表了"harness 作为可训练信号载体"这一方向的早期形态——与 Anthropic/OpenAI 2026 年报告中"AI R&D 自动化"的大趋势一致。下一步关键:(1) 专门针对 RLM API 的模型训练;(2) 解决 refinement loop 的目标对齐问题;(3) 把 harness state 的变化作为强化学习信号(而非仅仅是 prompt 注入)。Factorio reward hacking 案例是一个难得的公开 empirical evidence,说明 autonomous self-modification 系统的对齐挑战不是理论问题。

附录:Repo 深度解析

基于 PrimeIntellect-ai/prime-agent 源码(2026-08)直接分析。TypeScript monorepo(pnpm workspace)+ Python runtime(uv)。

目录分工

路径语言职责(一句话)
TypeScript monorepo(packages/)
packages/agent/src/TS agent-loop.ts:LLM 流式调用主循环 + tool dispatch;agent.ts:单次 agent 入口;proxy.ts:emit 事件的代理包装
packages/coding-agent/src/core/TS 所有"coding agent"逻辑:session 生命周期、系统 prompt 构建、kernel 管理、compaction、/refine、goals、heartbeat、MCP、tool 实现
packages/coding-agent/src/core/kernel/TS Python kernel 进程管理:bootstrap.ts 启动子进程;repl-manager.ts 管理 cell 执行队列;state-snapshot.ts 保存/恢复 kernel state
packages/coding-agent/src/core/prompts/TS rlm.tsbuildRlmPrompt() — 12 块 system prompt 拼装;index.ts:通用 prompt utilities
packages/coding-agent/src/core/refinement/TS refinement.ts:/refine 命令实现;REFINEMENT_SYSTEM_PROMPT;planner+applier 子 agent 编排
packages/coding-agent/src/modes/TS 运行模式路由:interactive/ TUI 模式;session-worker/ 实际执行 agent 逻辑;daemon/ 后台 session 管理器;acp/ agent-connection protocol;headless-completion.ts 无 TUI 运行
packages/coding-agent/src/modes/daemon/TS 常驻后台进程:daemon-supervisor.ts 监管所有 session worker;daemon-catalog-*.ts session 目录(JSONL 索引);daemon-socket.ts Unix domain socket 通信;heartbeat-catalog.ts 定时 heartbeat 管理
packages/coding-agent/src/modes/session-worker/TS 单个 session 的执行环境:private-framing.ts 二进制帧协议(连接 daemon↔worker);agent-roster.ts 子 agent 注册表;compact-session-stream.ts context compaction
packages/ai/src/TS 多模型 provider 抽象:Anthropic/OpenAI/Bedrock/Gemini/OpenRouter + Prime Inference;stream.ts 统一流式 API;models.generated.ts 模型列表
packages/tui/TS 终端 UI 组件(Ink/React-like):session 列表、agent trace、context 占用、agents-view 导航
Python runtime(prime-agent-runtime/src/rlm/)
rlm/repl.pyPython IPython kernel 主进程:stdio JSON 协议(PROTOCOL_VERSION=3);持久 __main__ namespace;top-level await;snapshot 序列化;host_request() 反向 RPC 桥
rlm/harness.pyPython HarnessState 类:harness_state.json 的全部 CRUD;原子写入;mtime 同步检测;local/global scope 路由;HarnessEntry dataclass;RefinementEvent
rlm/__init__.pyPython _RLMNamespace singleton(kernel 里的 rlm):spawn()/collect()/progress_note()/delete_subagent()_HarnessProxy 把 harness 挂到 rlm.harness
rlm/bash.pyPython 非阻塞 bash():返回 handle,await 才等完成;stdout/stderr streaming;进程 cleanup;与 harness 进程树隔离
rlm/mcp.py + mcp_base.pyPython MCP (Model Context Protocol) 集成:把 MCP server 的工具暴露为 Python 对象,供 kernel 直接调用
rlm/skill.pyPython 技能模块 CLI helpers:skill install/list/remove;技能包的 import 路径解析
rlm/_winjob.pyPython Windows Job Object 封装(Windows 平台进程生命周期管理)
评估基础设施(scripts/)
scripts/benchmarks/controller.pyPython Benchmark 控制器:创建/销毁 cloud sandbox;phase 调度(setup→solve→verify→grade);并行 trial 管理;结果汇总
scripts/benchmarks/worker.pyPython Sandbox 内执行:apt install + user 创建;agent 进程启动;stdout/stderr 捕获;试验间进程清理
scripts/evals/short_swe/Python SWE-bench 评估套件:secure_harbor.py 双 sandbox 隔离;verified_verifier.py trusted commit + 测试脚本重写;prepare.py credential 剥离 + dataset pinning;oracle_harness.py 金标准 preflight
scripts/evals/swarm_fanout/Python 多 agent swarm fan-out 评估(并行子 agent 协作任务)

启动流程(从命令行到第一个 LLM call)

sequenceDiagram
  participant U as User
  participant CLI as cli-main.ts
  participant D as daemon-supervisor.ts
  participant SW as session-worker
  participant KM as kernel/bootstrap.ts
  participant PY as repl.py

  U->>CLI: prime-agent "task..."
  CLI->>D: connect to daemon socket
  Note over D: daemon already running\nor fork new daemon process
  D->>SW: spawn session-worker subprocess
  SW->>KM: boot Python kernel
  KM->>PY: python -m rlm.repl (subprocess)
  PY-->>KM: protocol handshake (PROTOCOL_VERSION=3)
  KM-->>SW: kernel ready
  SW->>SW: build system prompt (buildRlmPrompt)
  SW->>SW: inject harness_state.json digest
  SW->>SW: first LLM call (stream)
  SW-->>D: events (agent_start, turn_start...)
  D-->>CLI: forward events
  CLI-->>U: TUI renders
          
drag to pan · scroll to zoom
启动流程:CLI → Daemon(Unix socket)→ session-worker 子进程 → Python kernel 子进程。System prompt 在 kernel ready 后在 session-worker 侧构建,harness_state.json digest 在每轮注入。

关键细节:

单轮执行控制流

sequenceDiagram
  participant SW as agent-loop.ts
  participant AI as packages/ai stream.ts
  participant RM as repl-manager.ts
  participant PY as repl.py kernel
  participant HS as harness_state.json

  SW->>AI: streamAssistantResponse(context, config, signal)
  AI-->>SW: stream chunks (text / tool_use)
  Note over SW: tool_use = ipython cell
  SW->>RM: executeCell(code, signal)
  RM->>PY: {type:"execute", code:"..."} newline JSON
  PY->>PY: exec in __main__ namespace
  PY-->>RM: {type:"stream", stream:"stdout", text:"..."}
  PY-->>RM: {type:"result", value:"..."}
  RM-->>SW: CellResult {stdout, stderr, result}
  SW->>AI: push tool_result to context
  Note over SW: while tool calls present, loop
  SW->>HS: (if cell called harness CRUD) mtime updated
  SW->>SW: check getContinuationMessages()
  SW-->>TUI: emit events (turn_end / agent_end)
          
drag to pan · scroll to zoom
单轮:LLM 流式输出一个 tool_use(ipython cell)→ repl-manager 把 cell 发给 Python kernel → kernel 执行并流式返回 stdout/result → tool_result push 回 LLM context → 循环直到无 tool call。

关键细节:

子 Agent 生命周期

sequenceDiagram
  participant P as Parent kernel
  participant TS as TS Host (session-worker)
  participant D as daemon
  participant C as Child session-worker
  participant CK as Child kernel

  P->>TS: host_request("rlm.run", {prompt, name, model})
  TS->>D: spawn new session (via daemon socket)
  D->>C: fork child session-worker
  C->>CK: boot Python kernel
  TS-->>P: {rlm_child_id, session_dir} (immediate)
  Note over P: cell returns RLMSpawnHandle immediately
  C->>C: run agent loop (async, independent)
  C-->>D: emit agent_message(reply, receiver_role=parent)
  D-->>TS: route message to parent session
  TS->>P: inject as steering message (next turn)
  Note over P: parent sees reply in getContinuationMessages
  P->>TS: host_request("rlm.collect", {ids, timeout_ms})
  TS-->>P: [{status, answer_preview, settled}]
          
drag to pan · scroll to zoom
子 agent 生命周期:spawn 在 task admission 时立即返回 handle;child 作为独立 session-worker 异步运行;reply 通过 daemon routing 注入父 session 的 steering message 队列;collect() 轮询当前状态快照。

关键细节:

/refine 管线

flowchart TD
  cmd["User: /refine or refine.run()"]
  cmd --> TS["refinement.ts\nbuildRefinementContext(session)"]
  TS --> P["Planner child agent\nanalyzes trajectory\nproposes RefinementEdit[]"]
  P --> A["Applier child agent\nexecutes CRUD edits\nharness_state.json"]
  A --> HS["harness_state.json\nmtime updated"]
  HS --> KR["kernel _sync_from_disk\ndetects mtime change"]
  KR --> LLM["LLM sees updated\nskill/memory/prompt\nnext turn"]
  TS --> RE["RefinementEvent logged\nin harness_state.json refinements[]"]
          
drag to pan · scroll to zoom
/refine 两阶段:Planner 分析当前 session 轨迹(JSONL)并提出 RefinementEdit;Applier 执行实际 CRUD 写入 harness_state.json;kernel mtime 检测自动 reload。

关键细节:

Daemon 架构

文件职责
daemon-supervisor.ts主进程:监听 socket;fork session-worker;监控子进程存活;重启 crashed worker
daemon-socket.tsUnix domain socket 服务器(~/.prime/agent/daemon.sock);连接 multiplexing
daemon-catalog-*.tsSession 目录:JSONL 索引 + session metadata(id, name, status, timestamps);disk-backed,daemon 崩溃可恢复
daemon-session-summarizer.ts后台生成 session title(LLM call);显示在 session 列表
heartbeat-catalog.tscron-style heartbeat 管理:每个 session 可注册 heartbeat;daemon 定时注入 steering message
saved-session-catalog.ts已保存 session 的磁盘索引;支持 /tree 恢复任意分支
rlm-ledger.ts子 agent 关系账本:记录 parent→child 依赖图;用于 routing 和 cleanup
worker-recovery-journal.tsworker 崩溃恢复日志:记录哪个 session 在哪个 worker PID 上;重启后重新挂载
mutation-drain-latch.ts优雅关闭时等待 in-flight mutation 完成(防止 torn write)
flowchart LR
  C1["CLI (TUI)"]
  C2["CLI (headless)"]
  C3["Remote client"]
  DS["daemon\ndaemon-socket.ts\ndaemon-supervisor.ts"]
  W1["session-worker\n(session A)"]
  W2["session-worker\n(session B)"]
  W3["session-worker\n(session C, child of A)"]
  K1["Python kernel A"]
  K2["Python kernel B"]
  K3["Python kernel C"]
  C1 -->|"socket"| DS
  C2 -->|"socket"| DS
  C3 -->|"socket"| DS
  DS -->|"pipe+framing"| W1
  DS -->|"pipe+framing"| W2
  DS -->|"pipe+framing"| W3
  W1 -->|"stdio JSON"| K1
  W2 -->|"stdio JSON"| K2
  W3 -->|"stdio JSON"| K3
  W1 -->|"agent_message route"| W3
          
drag to pan · scroll to zoom
Daemon 拓扑:多个 CLI client 共享同一 daemon;daemon 管理多个 session-worker 子进程;agent_message 路由由 daemon 转发(rlm-ledger 维护父子关系)。

Python Kernel 启动与 pre-import 机制

packages/coding-agent/src/core/kernel/bootstrap.ts 启动 kernel 进程:

// bootstrap.ts 简化版
const kernelProcess = spawn("python", ["-m", "rlm.repl"], {
  cwd: sessionDir,
  env: {
    ...process.env,
    RLM_SESSION_DIR: sessionDir,
    RLM_HARNESS_STATE_DIR: harnessDir,
    PROTOCOL_VERSION: "3",
  },
  stdio: ["pipe", "pipe", "pipe"],
})
// 等待 handshake message
const handshake = await readLineJSON(kernelProcess.stdout)
// → {"type":"ready","protocol_version":3}

repl.py 启动时 pre-import 进 __main__ namespace:

名字类型内容
rlm_RLMNamespacespawn/collect/progress_note + rlm.harness proxy
bashfunction非阻塞 shell 执行器(bash.py)
mcpobjectMCP server 工具代理(mcp.py)
asynciomodule标准库,top-level await 支持
skill modulesmodulesharness_state.json 里每个 skill 的 reference.import 对应的 Python 包

Snapshot 机制state-snapshot.tsrepl.py):

Eval/Benchmark 完整控制流

sequenceDiagram
  participant CTL as controller.py
  participant SDK as prime_sandboxes SDK
  participant SS as Solver Sandbox
  participant VS as Verifier Sandbox
  participant W as worker.py

  CTL->>SDK: CreateSandboxRequest(image, cpu, mem, ttl)
  SDK-->>CTL: sandbox handle
  CTL->>SS: phase("setup") - install deps, create user
  W->>SS: useradd benchmark1 (uid=2002)
  CTL->>SS: phase("solve") - run agent
  SS->>SS: runuser -u benchmark1 prime-agent task
  SS-->>CTL: patch_collect_command output
  CTL->>CTL: verify artifacts == {/logs/artifacts, /tmp/prime-agent.patch}
  CTL->>SDK: CreateSandboxRequest(fresh_copy=True, network=[])
  SDK-->>CTL: verifier sandbox
  CTL->>VS: phase("verify_setup") - git reset base_commit
  CTL->>VS: phase("verify_apply") - git apply patch
  CTL->>VS: phase("verify_run") - rm config/tests, run tests
  VS-->>CTL: test_output.log
  CTL->>CTL: grade(log) -> score
  CTL->>SDK: destroy both sandboxes
          
drag to pan · scroll to zoom
Eval 控制流:Controller 编排全部 phase;Solver sandbox 跑 agent;唯一输出是 git diff patch;Verifier sandbox fresh copy + no network,仅接受 patch,grade 在 Controller 侧完成。

Phase 调度controller.py phase()):

Phase位置执行内容
setupSolverapt install、useradd、pip install agent runtime、build venv
solveSolverrunuser -u benchmarkN prime-agent <task>;timeout 由 config 指定
collectSolverpatch_collect_command()git diff --binary … > /tmp/prime-agent.patch
verify_setupVerifiergit reset --hard {trusted_base} + git clean -fd
verify_applyVerifiergit apply --binary /tmp/prime-agent.patch(从 Solver 复制过来)
verify_runVerifierrm -f /tests/config.json /tmp/tests.tgz;执行 rewrite 后的测试脚本
gradeController解析 Verifier 的 test_output.log → pass/fail → 数值分

OracleHarness(oracle_harness.py):在正式 eval 前用金标准 patch 验证整个流程可用——确保 phase 调度、sandbox 网络、测试脚本都正确,再跑真实 agent,避免"基础设施 bug 被误算成 agent 失败"。