
Prime Agent REPL 运行时协议深度解析基于 JSON-lines 的 CPython 内核通信规范【免费下载链接】prime-agentA self-improving RLM agent for coding workflows and long-running autonomous tasks.项目地址: https://gitcode.com/GitHub_Trending/pr/prime-agent导读prime-agent-runtime是 Prime Agent 项目中为递归代理Recursive Language ModelRLM提供内核侧运行时支撑的 Python 包而prime-agent-runtime/src/rlm/repl.md则是其中 REPL 内核运行时的协议规范文档。它定义了一个以python -m rlm.repl启动的 CPython REPL 运行时如何通过标准输入输出与 TypeScript 宿主进程进行结构化通信请求走 stdin事件走 stdout全部采用「每行一个 JSON 对象」的 JSON-lines 线格式。读完本文你将掌握该协议的全部七类请求与八类事件的字段语义、输出归因与 drain 机制、顶层 await 与后台任务的执行模型、可精确到单个请求的中断投递算法以及基于dill的命名空间快照/恢复协议——这些能力正是 Prime Agent 中 IPython 内核、技能执行与长时自治任务持久化的底层基石。一、协议概览单事件循环、单一持久命名空间、JSON-lines 线格式1.1 运行时定位python -m rlm.repl启动的运行时是一个「极简 CPython REPL」所有代码单元cell都在一个持久的__main__命名空间和单个 asyncio 事件循环上执行。这意味着不同 cell 之间共享变量前一个 cell 定义的名称后一个 cell 立即可用事件循环常驻cell 中创建的 asyncio 后台任务在 cell 结束后依然存活并继续运行宿主进程可以持续地向同一个内核发送execute形成连续、有状态的会话式执行。在 repl.py 的模块 docstring 中该设计被明确表述为Cells execute with top-level await in one persistent__main__namespace on a single asyncio event loop.入口函数main()repl.py在启动时做了几件关键初始化分配协议 fd、启动 owner 看门狗、用真实的__main__模块替换sys.modules[__main__]这是为了让dill能够按值序列化用户定义的函数与类、创建事件循环并启动读线程与_serve协程最后发出ready握手事件。1.2 线格式与协议版本协议线格式固定为UTF-8 编码每行一个 JSON 对象除换行符外没有任何额外帧边界当前协议版本为3运行时通过ready事件中的protocol字段宣告事件发送使用「一次锁定的写入序列」保证帧不被交叉见_send实现repl.py在_write_lock保护下循环os.write直到整帧写完。版本号在 repl.py 定义为PROTOCOL_VERSION 3。宿主侧的 TypeScript 客户端在 repl-manager.ts 中同样声明REPL_PROTOCOL_VERSION 3并以精确版本握手为准未知事件类型被视为协议损坏而非「更新版本的新增字段」见 repl-manager.ts 的PROTOCOL_EVENT_KINDS集合。1.3 通道布局与输出归因协议在文件描述符层面做了精心的通道划分通道用途fd 0stdin接收请求fd 1stdout原始副本协议事件出口在一切运行之前通过os.dup(1)私有复制见_setup_fdsrepl.pyfd 1 / fd 2 重定向启动时被重定向进管道泵线程读取后以id: null的stdout/stderr事件发出fd 0 重绑定读线程接管 stdin 后fd 0 被重绑定到/dev/null用户代码中的input()只会读到 EOF永远不会消费协议帧Python 级写入与裸 fd 写入的归因差异是这套协议最精妙的设计之一通过sys.stdout/sys.stderr的 Python 级写入会在写入时刻被_TaggedWriterrepl.py拦截并打上当前写入上下文所属 cell 的 id标签直接走协议通道发出裸 fd 字节os.write、sys.stdout.buffer.write、C 扩展、子进程输出由管道泵线程读取事件中id恒为null永远不会被归因到某个 cellasyncio 任务会继承创建它的 cell 的 id即使该 cell 已经结束用户线程则一律为null。这一归因规则在测试 test_repl.py 中得到完整验证print(py-out)的输出带 cell id而os.write(1, bfd-out\n)的输出id为null。通道内保序、通道间不保序每个通道stdout 管道、stderr 管道、协议事件流内部顺序保持但 Python 级写入与裸 fd 写入之间不保证先后。两个通道都不会破坏协议帧边界。二、请求Requests七类请求的字段语义与执行秩序请求以 JSON 对象形式从 stdin 逐行到达。完整请求表如下RequestFieldsexecute{type:execute,id:str,code:str}interrupt{type:interrupt,id?:str}— 无回复host_reply{type:host_reply,id:str,data:{status:ok,result:{...}}}或错误信封 — 无回复snapshot{type:snapshot,id:str,path:str,manifest_path:str,max_bytes?:int,max_variable_bytes?:int,prune_oversized?:bool}restore{type:restore,id:str,path:str}list_names{type:list_names,id:str}shutdown{type:shutdown,id?:str}2.1 请求处理秩序与健壮性除interrupt与host_reply外其余请求严格按序、一次一个执行经 asyncio 队列串行见_serve循环repl.py。这两个「绕过队列」的请求类型有各自的特殊理由host_reply是宿主对运行时host_request事件的回执必须在读线程上直接路由给等待中的 cell因为该 cell 本身就是正在执行的 execute若排进 FIFO 队列会死锁在自身后面见_handle_request_linerepl.pyinterrupt必须在任何时刻都能投递因此也走读线程旁路repl.py。畸形输入防护一行无法解析或字段类型错误的 JSON 会产生{event:error,id:null,ename:ProtocolError,...}随后运行时继续服务。即使面对100000层嵌套的恶意 JSON触发RecursionError或不可哈希的请求类型读线程也能存活并继续处理后续请求——这在test_hostile_deeply_nested_json_line_does_not_kill_readertest_repl.py中有专门验证。重复 id 防护execute/snapshot/restore的 id 若与在途请求重复会返回ProtocolErrorduplicate in-flight request id因为复用 id 会破坏中断与完成簿记的一致性repl.py。stdin EOF 即 shutdown读线程在 stdin 关闭时主动向队列投入{type:shutdown}并先让所有等待中的host_request失败退出repl.py。2.2 宿主侧客户端视角TypeScript 侧的内核客户端 repl-manager.ts 将内核描述为「一个 JSON-lines 子进程python -m rlm.repl——请求写 stdin事件读 stdoutstderr 保留为诊断尾部」并直接引用本协议文档作为规范。它还对帧做了严格校验done与host_request必须携带非空字符串 id运行时以 uuid hex 铸造自己的 id否则视为无效帧被静默丢弃以免对应请求永远得不到结算repl-manager.ts。三、事件Events从握手到完成的完整事件谱系运行时共发出八类事件事件说明ready启动时发送一次的握手事件无任何 banner 前缀stdout/stderr捕获的输出id为写入者所属 cellresultcell 尾表达式非None时的repr同时值绑定到命名空间_display从emit()原样转发的一包 MIME 类型 → JSON 载荷host_request运行时代码向宿主的类型化请求宿主以同名 id 的host_reply应答error执行错误含ename/evalue/tracebackdone每个带 id 的请求恰好一个总是晚于该请求的所有其他事件3.1 握手事件ready{event:ready,protocol:3,python:3.13.11}protocol恒为3当前版本python是运行时的platform.python_version()repl.py在ready之前不会有任何 banner 或杂质输出宿主可以安全地以ready作为「内核已就绪」的确定性信号。启动性能同样被测试所约束test_ready_handshake_and_startup_timetest_repl.py要求从 spawn 到ready的耗时小于 500ms用于捕捉量级级的启动回归。3.2 输出事件stdout/stderr{event:stdout|stderr,id:str|null,text:str}id的赋值规则即前文所述的归因模型asyncio 任务继承创建者 cell 的 idcell 结束后依然保持用户线程与无主可证的裸 fd 字节一律null。测试test_asyncio_task_output_keeps_spawning_cell_idtest_repl.py验证了「cell A 创建的后台任务在 cell B 执行期间输出仍带 A 的 id」这一行为。3.3 结果事件result与尾表达式机制{event:result,id:str,text:str}_compile_cellrepl.py会把 cell 源码的最后一个表达式语句单独以eval模式编译当且仅当 body 以表达式结尾且其值不是None时发出result事件text为该值的repr()且该值同时绑定到命名空间中的_。标准行为在test_result_echotest_repl.py中验证11→result.text 2x 5赋值语句→ 无resultNone→ 无result_ 40→ 借助上一 cell 留下的_得到42。3.4 展示事件display{event:display,id:str|null,data:{mime:payload,...}}data是一包 MIME 类型 → JSON 载荷的字典由emit()原样转发。id沿用任务上下文归因cell 派生的 asyncio 任务保持该 cell 的 id用户线程为null。emit()的输入校验很严格repl.py必须是「非空、键全为字符串」的字典否则抛TypeError此外还会用allow_nanFalse做一次预序列化校验——因为NaN/Infinity会以非 JSON 文本形式撕裂宿主的协议帧边界_send本身遇到不可序列化值会在写任何字节前抛错因此NaN是唯一的污染向量。test_emit_nan_payload_errors_in_cell_and_keeps_framingtest_repl.py验证了这一点emit({application/json: float(nan)})在 cell 内抛ValueError协议帧安然无恙。测试中使用的典型 MIME 载荷包括application/vnd.prime-agent.diffjson文件编辑 diff、application/vnd.prime-agent.attachmentjson附件如 base64 图片与application/vnd.prime-agent.agent-messagejson代理间消息见 test_repl.py。3.5 错误事件error{event:error,id:str|null,ename:str,evalue:str,traceback:[str,...]}ename为异常类型名evalue为其字符串形式__str__本身崩溃时有兜底exception str() failed见_safe_strrepl.pytraceback是纯文本、无颜色无装饰的帧列表且运行时自身的帧会被剥离保留 cell 帧与库帧cell 源码经linecache注册在cell-N名下因此 traceback 中能直接显示出错源码行见_cell_stackrepl.py若连 cell 帧都没有如编译期SyntaxError则只输出异常行含文件名、源码行与 caret 指示符。test_traceback_clean_with_source_linetest_repl.py断言traceback 包含cell-与raise ValueError(nope)源码行且不包含repl.py运行时帧、不包含 ANSI 转义序列\x1b[。3.6 完成事件done每个请求的唯一收尾标记{event:done,id:str,status:ok|error}每个带 id 的请求恰好一个done且总是晚于该请求的所有其他事件snapshot的done额外携带saved、skipped、pruned、bytesrestore的done额外携带restored、failedlist_names的done携带names失败的 snapshot/restore 还会携带reasonrestore 一个不存在的文件报告status:okrestored/failed均为空列表并附reason:snapshot not found对应 repl.py 的早退分支测试见 test_repl.py。3.7 drain 机制保证done前收到全部字节在发出 cell 的done之前运行时会对两个输出通道做 drain见_drain_outputrepl.py先flush()两个带标签的 writer即使 cell 关闭或重绑定了sys.stdout/sys.stderr捕获异常后继续绝不因此跳过另一条流或杀死 serve 循环对 stdout、stderr 两条 fd 管道各调用一次drain()向管道的私有复制写端写入一个随机 marker 字节序列泵线程见到该 marker 即确认此前的所有字节都已发出_Pump.drainrepl.py。marker 走私有 dup 的写端因此 cell 关闭或回收 fd 1/2 也无法劫持 drain token。于是「cell 同步写出的每一个字节——包括直接 fd 写——都先于其done到达」且不完整的 UTF-8 序列会在 drain 时以替换字符\ufffd收尾_finish_decode测试见test_drain_finalizes_incomplete_raw_utf8_before_donetest_repl.py。注意通道间Python 级写入与裸 fd 写入的顺序依然不保证。四、执行模型顶层 await、后台任务与持久命名空间4.1 编译与运行Cell 的编译与执行分两步编译_compile_cell使用ast.PyCF_ALLOW_TOP_LEVEL_AWAIT标志编译repl.py使await可以在 cell 顶层直接书写每个 cell 的源码注册到linecache的cell-N名下。运行_run_codesrepl.py逐个执行编译产物若代码对象是协程co_flags inspect.CO_COROUTINE则await它。所有 cell 作为任务运行在持久事件循环上因此顶层await直接可用无需async def包装cell 创建的后台任务在 cell 结束后继续运行并在后续 cell 之间持续存活。test_top_level_awaittest_repl.py验证了顶层await asyncio.sleep(0)后返回oktest_background_task_persists_across_cellstest_repl.py则验证了「cell 1 启动的无限tick()任务在 cell 2 期间累计写入acccell 3 再取消它」。4.2 任务上下文归因_current_cell是一个contextvars.ContextVarrepl.pyasyncio 任务在创建时复制 cell 上下文因此分离的后台任务保留其输出归因与完成屏障而线程以全新上下文启动因此用户线程的输出恒为nullid。这正是测试test_output_after_done_carries_null_idtest_repl.py与test_background_thread_and_fd_output_during_later_cell_is_nulltest_repl.py所固化的行为跨 cell 的迟到输出绝不错误归因给当前运行的 cell。4.3 traceback 清洗Traceback 使用标准traceback模块格式化剥离运行时自身帧_cell_stack从第一个cell-帧开始截取并过滤掉运行时文件帧无颜色、无装饰便于宿主直接展示给用户或模型。五、中断Interrupt精确到单请求的 KeyboardInterrupt 投递5.1 请求语义{type:interrupt}向正在运行的 cell 抛出KeyboardInterrupt不带id作用于正在运行的请求若当前无请求运行则作用于下一个排队的请求带id仅作用于该请求请求尚未开始就到达的中断会被停车parked并在该请求变为激活的瞬间投递——因此execute与interrupt背靠背写入时中断依然生效test_interrupt_written_back_to_back_with_executetest_repl.py请求在done发出之前始终可被中断这覆盖了运行后尾表达式repr与输出 drain 阶段test_interrupt_during_slow_repr_cancels_finishing_requesttest_repl.py针对已结束或未知请求的中断被丢弃请求结束后其目标会随之失效迟到的 SIGINT 不会误伤复用同一 id 的后继请求test_stale_target_from_finished_interrupt_ignores_later_sigint_on_reused_idtest_repl.py。5.2 投递机制POSIX 与 Windows 两条路径POSIX 路径读线程通过signal.pthread_kill(main_thread, SIGINT)把信号投到主线程也是事件循环线程处理器_sigint_handlerrepl.py查询 asyncio 当前被信号打断的是哪个任务的 step据此分派激活 cell 自身处于 mid-step同步字节码如time.sleep循环或被 EINTR 唤醒的阻塞 syscall 如selectors.select()处理器直接抛出KeyboardInterrupt从 cell 任务中传播出去循环空闲在select()cell 挂起在await上或其他任务 mid-step后台任务或运行时自身此时抛异常会落在错误上下文因此处理器取消激活的 cell 任务运行时把这次取消报告为KeyboardInterruptmid-step 任务是后台任务后台任务若阻塞在同步代码里会独占唯一线程导致取消永远无法执行此时处理器也向它抛出KeyboardInterrupt让它带着异常死掉从而解除循环阻塞、让取消生效。Windows 路径无signal.pthread_kill读线程退化为在事件循环上取消激活的 cell 任务——await挂起的 cell 可以正常中断但阻塞在同步代码中的 cell 无法被打破尽力而为的等价性。这一回退缝在test_interrupt_without_pthread_kill_cancels_awaited_celltest_repl.py中通过临时删除signal.pthread_kill模拟验证。已知限制在路径 2/3 中中断以「await 点上的取消」形式落地因此用户代码在await周围捕获KeyboardInterrupt无法拦截它。两条路径都以error事件ename为KeyboardInterrupt加donestatus:error收尾运行时继续服务。当没有任何运行中或排队中的请求时SIGINT 与 interrupt 请求均被忽略。另外_serve在每个请求处理前都会重新绑定SIGINT处理器——因为某个 cell或快照恢复出的旧处理器可能重绑过信号协议处理器必须夺回所有权repl.pycell 中途的重绑只对该 cell 自身有效test_interrupt_survives_cell_rebinding_siginttest_repl.py。六、Display 桥与 Host 桥运行时与宿主的双向通道6.1 Display 桥emit()在 cell或任何用户线程中执行from rlm.repl import emit emit({text/plain: label, application/vnd.prime-agent.diffjson: { path: /tmp/file.py, old_str: a, new_str: b, start_line: 3, }})emit(data)接收一个非空、键为 MIME 类型字符串的字典并将其逐字作为display事件的data转发。校验规则见 3.4 节非字典、空字典、非字符串键抛TypeError含NaN的载荷抛ValueError。emit是线程安全的事件按调用时刻的 cell 打 id 标签。6.2 Host 桥host_request/is_activefrom rlm.repl import host_request reply await host_request({type: demo, value: 7})host_request(data)repl.py铸造一个运行时自产的 uuid hex id发出{event:host_request,id:rid,data:data}挂起等待匹配 id 的host_reply返回回复中的data字典原样。路由细节回复在读线程上通过_loop.call_soon_threadsafe直接结算等待中的 future_resolve_host_replyrepl.py绝不经过请求队列——因为等待中的 cell 本身就是那个在途的 execute排队会死锁。对未知 id 的回复、或等待 cell 已被取消的回复一律丢弃future 已被弹出。关停语义一旦 stdin EOF 或 shutdown 到达_host_closed置位之后所有含未来host_request调用直接抛RuntimeError(host connection closed; host_request cannot be answered)所有等待中的 future 被置为该异常_fail_pending_host_requestsrepl.py。测试test_stdin_eof_with_pending_host_request_exits与test_shutdown_with_pending_host_request_exitstest_repl.py验证了这两种退出路径。rlm.repl.is_active()repl.py报告当前进程是否正在服务该协议——仅仅 import 模块不算激活其实现即_protocol_fd 0。6.3 与内核 shim 的关系prime-agent-runtime/src/rlm/__init__.py在host_request基础上包装出类型化内核 APIinit.pyawait host_request(rlm.run, {...})、rlm.create_session、rlm.find_models、rlm.list_subagents、rlm.delete_subagent等由 TypeScript 宿主按类型分发。request_type放在载荷最后使载荷里的type键无法重路由请求。spawn的线协议类型保持为rlm.run以便不同版本的内核与宿主保持兼容。七、快照与恢复Snapshot / Restore基于 dill 的命名空间持久化7.1 请求字段与默认值{type:snapshot,id:str,path:str,manifest_path:str, max_bytes?:int,max_variable_bytes?:int,prune_oversized?:bool}max_bytes默认256 * 1024 * 1024256 MiBmax_variable_bytes默认16 * 1024 * 102416 MiB常量定义于 repl.py两个容量字段若出现必须是非负整数布尔值与负数是非法值——负数上限会把每个用户变量都判为超大prune_oversized必须是布尔path与manifest_path经realpath解析后必须不同防止符号链接别名静默覆盖载荷见_handle_state的校验repl.py 与测试 test_repl.py。7.2 快照算法_snapshot_staterepl.py以dill的 recurse 模式逐个序列化命名空间名称总是跳过_前缀名称以及集合{rlm, mcp, bash, asyncio, In, Out, get_ipython, exit, quit, open}_ALWAYS_SKIPrepl.py——这些是会话引导每次都会重建的名称不应当被快照跳过条件单变量 pickle 超过max_variable_bytes或累计总量会超过max_bytesprune_oversized: true仅当名称超过单变量上限时才从命名空间删除该名称并列入pruned因总量上限被跳过的名称列入skipped但保留在命名空间一个不可 pickle 的名称不会中止整个快照它被记入skipped原因截断到 200 字符其余名称继续原子写入先写临时文件再os.replace载荷与清单各用独立临时文件先暂存两者任何失败发生在第一次 replace 之前都保证旧载荷清单对完整无损若写入中途发现超限还会对载荷做二分裁剪因为前缀 pickle 大小单调把超出的名称移入skipped清单文件JSON 格式字段为version恒为 1、savedNames、skipped、pruned、bytes、pythonVersion、timestampUTC ISO 8601清单写入失败 ⇒ 整个快照失败且不执行任何 prune——绝不让坏清单路径破坏状态。test_snapshot_restore_roundtriptest_repl.py验证了完整闭环保存x、函数bump、socket模块与一个 socket 对象后saved为[bump,socket,x]、skipped为[sock]socket 对象不可 pickle目录里无临时文件残留新进程 restore 后bump(x)返回42。test_snapshot_prune_oversizedtest_repl.py验证prune_oversized会真正从命名空间删除超大变量big。7.3 恢复算法_restore_staterepl.py缺失文件返回 ok 空恢复reason:snapshot not found损坏文件以reason失败load failed: ...逐个名称独立复活单个名称反序列化失败只计入failed列表不影响其余名称永不恢复载荷中的In、Out、get_ipython_RESTORE_SKIPrepl.py——这些是 IPython 注入的名称见test_restore_skips_ipython_injected_namestest_repl.py应用阶段整体原子把 SIGINT 停车到整个命名空间应用完成保证 all-or-nothingdill惰性导入不可用时 snapshot 与 restore 都以status:error加reason失败。dill被声明在pyproject.toml的 dev 依赖组中pyproject.toml由宿主预置而非运行时硬依赖。7.4list_names{type:list_names,id:str}在done中返回names与快照相同过滤规则下非_前缀、非_ALWAYS_SKIP、字符串键的排序后的用户自定义顶层名称_list_namesrepl.py。非字符串键如globals()[1] 1不算可列出的用户名称测试见test_list_names与test_list_names_skips_non_string_keystest_repl.py。7.5 中断下的快照一致性快照/恢复以可中断任务运行_handle_state用_run_guarded包装且对「提交后 SIGINT 落在完成窗口」做了专门恢复一旦清单已提交、命名空间已 prune此时到达的协议中断会被消费并仍把该已提交的快照报告为done status:ok——否则宿主可能丢弃唯一一份已 pruned 变量的副本repl.py 中 SIGINT 停车逻辑测试见 test_repl.py 的test_sigint_in_post_run_guarded_window_reports_snapshot_ok与test_protocol_interrupt_during_restore_commit_is_consumed_and_next_request_runs。八、关停Shutdown进程组的干净收尾shutdown或 stdin EOF的收尾序列_serve中的 shutdown 分支repl.py关闭 MCP 子连接若rlm.mcp模块已加载则先await mcp_mod.close()宿主 5 秒期限内内部有界MCP 子进程必须赶在事件循环消亡前关闭杀掉存活的rlm.bash子进程组_kill_live_handles()bash.py对每个存活句柄向进程组投递SIGKILL——此处不能依赖atexit因为那时 executors 已驻留等待若请求带 id回复done停止事件循环以退出码 0 结束进程。test_bash_integrationtest_repl.py验证运行时 shutdown 后bash(sleep 600)启动的进程组必死无疑。8.1 宿主进程看门狗除协议级关停外运行时还带一个与事件循环无关的owner 看门狗_start_owner_watchdog/_owner_watchdogrepl.pyPOSIX 上通过「父进程重排检测 kill(owner, 0)探测」判断宿主是否存活PRIME_AGENT_KERNEL_OWNER_PID环境变量可指定非父进程的宿主Windows 上通过OpenProcess(SYNCHRONIZE)WaitForSingleObject阻塞等待宿主退出os.kill(pid, 0)在 Windows 上会终止目标进程因此只能用手柄等待宿主一旦死亡杀掉存活的 bash 句柄后os._exit(1)硬退出——因为同步 cell 可能独占事件循环排队中的 EOF 关停永远不会执行必须从这里硬退repl.py。九、实战用测试框架快速验证协议仓库自带一个完整的协议级测试套件 test_repl.py其ReplProcess封装类本身就是一份可复用的协议客户端参考实现send()写请求、read_event()逐行读事件、until_done(rid)收集直到某个 id 的done为止的全部事件。它演示了最核心的交互模式# 启动并握手 proc ReplProcess() # Popen([python, -m, rlm.repl], ...) ready proc.ready() # {event: ready, protocol: 3, python: 3.13.x} # 执行一个 cell events proc.execute(a, 11) # - [{event:result,id:a,text:2}, {event:done,id:a,status:ok}] # 快照与恢复 proc.send({type: snapshot, id: s2, path: /tmp/kernel-state.dill, manifest_path: /tmp/kernel-state.json}) done proc.until_done(s2) # 优雅关停 proc.shutdown() # 退出码 0运行方式在prime-agent-runtime包目录内# 安装 dev 依赖含 dill uv sync --extra dev # 运行 REPL 运行时协议测试 PYTHONPATHsrc uv run python -m unittest test.test_repl -v若要手工体验协议可在终端 A 启动python -m rlm.repl在终端 B 向它的 stdin 逐行写入 JSON 请求观察 stdout 上的事件流例如发送{type:execute,id:a,code:11}即可看到result与done事件。注意该运行时假定由宿主进程持有 stdin/stdout 通道手工调试时需保持两条管道不被污染。十、小结prime-agent-runtime/src/rlm/repl.md定义的 REPL 运行时协议以极简的「JSON-lines over stdio」为骨架承载了 Prime Agent 内核会话所需要的全部关键能力有状态单一持久__main__命名空间 单事件循环顶层 await 与跨 cell 后台任务开箱即用可信输出Python 级写入与裸 fd 写入的分通道归因配合 drain marker 保证done之前的字节完整性可控执行精确到单请求、支持停车投递与事后窗口的KeyboardInterrupt中断模型跨 POSIX/Windows 双路径双向桥接emit()展示桥与host_request宿主桥为 Python 技能与 TypeScript 宿主之间提供类型化 RPC可持久化基于dill的快照/恢复协议原子写入、容量上限、选择性 prune 与逐名恢复为长时自治任务的状态保存提供了可靠基础可治理owner 看门狗确保宿主死亡时内核随之退出shutdown 时干净回收 MCP 与 bash 子进程组。文档、实现repl.py、宿主客户端repl-manager.ts与测试test_repl.py四者互为印证构成了这套协议从规范到落地、再到行为验证的完整证据链。无论你是要扩展内核能力、调试会话持久化还是实现自己的 JSON-lines 协议客户端本文覆盖的字段语义与执行语义都能作为直接的实现依据。【免费下载链接】prime-agentA self-improving RLM agent for coding workflows and long-running autonomous tasks.项目地址: https://gitcode.com/GitHub_Trending/pr/prime-agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考