人工审批与断点续跑¶
Rein 的恢复机制建立在一条地基上:暂停 = 把会话存盘,恢复 = 把会话喂回去。同一套机制撑起人工审批(HITL)、长任务续跑、错误重试。
人工审批(HITL)¶
把权限设成 ask,工具执行前会暂停,产出一个中断态:
from rein import Agent, LoopConfig
agent = Agent("anthropic/claude-opus-4-8", config=LoopConfig(permission="ask"))
@agent.tool
def delete_db(name: str) -> str:
"删除数据库(危险)"
return f"已删除 {name}"
result = agent.run("清理生产库")
if result.status == "interrupted":
print(result.interrupt.message) # "待批准执行工具:delete_db ..."
# 你来决定:
result = agent.resume(result.session, approve=False) # 拒绝
print(result.output) # 模型读到拒绝,改走安全做法(自愈)
approve=True→ 执行工具,继续跑。approve=False→ 把「被拒绝」回填给模型,模型自己换个安全方式。
CLI 里的交互式审批¶
它和服务端「产出中断态交给上层」用的是同一套机制,不是两套。
恢复的本质:喂回 session,不靠挂起的协程¶
resume 不是「继续一个卡住的协程」,而是「拿一份 session 数据,从它的阶段接着推进」。所以中断态可以存盘、关机、换台机器、明天再 resume:
from rein import FileSessionStore
store = FileSessionStore("./sessions")
result = agent.run("危险任务")
if result.status == "interrupted":
store.save("task-42", result.session) # 存盘,可以关机了
# ……改天,另一个进程……
session = store.load("task-42") # 读盘
result = agent.resume(session, approve=True) # 续跑到完成
持久化:SessionStore¶
from rein import MemorySessionStore, FileSessionStore
MemorySessionStore() # 进程内(测试/单进程)
FileSessionStore("./dir") # 存成 {id}.json
接口只有 save(id, session) / load(id)。redis / 数据库是你的事 —— 实现这俩方法即可(鸭子类型,无需继承)。"持久化不绑后端"。
错误也能恢复重试¶
模型调用遇到可重试错误(限流 / 超时 / 5xx)时,会建模成 error 中断态,你可以 resume 重试:
result = agent.run("...")
if result.status == "interrupted" and result.interrupt.type == "error":
result = agent.resume(result.session) # 重跑这一步
致命错误(鉴权 / 参数错)则直接抛 —— 重试也没用,抛出来最清晰。