结论先行:OpenAI 的 dots、Meta 的 Muse 把「智能体」从「你召唤一次它干一次」变成了「7×24 在后台替你盯目标」。这种常驻 Agent 到底凭什么算范式跃迁?核心不是模型多强,而是三件事,状态要持久、循环要可控、工具要可恢复。本文用一个 FastAPI + Redis 的最小骨架,把这套思路本地跑通。
一、原理:常驻 Agent 到底和普通脚本差在哪普通 Agent 是「请求,响应」:你发一句话,它答一句,进程结束,记忆清零。常驻 Agent(always-on agent)多了一层:它有自己的目标,会在后台持续轮询、执行、记录反馈,并在崩溃后从断点恢复 。OpenAI dots 的设计要点是「跑在自己的云电脑上、从反馈里学习、接 4000+ 应用」;Meta Muse 则是「在独立安全 VM 里后台管理目标,敏感动作要你批准」。抽象出来就三件套:状态存储(记住目标和进度)、执行循环(定时或事件驱动地干活)、工具接口(调 API / 发消息 / 读写文件) 。比如 一个「盯竞品价格」的常驻 Agent,状态里存着「上一次看到的最低价」,循环每 30 分钟抓一次页面,工具负责发钉钉通知。例如 一个「每日周报」Agent,状态里记着「已收集的素材列表」,循环在每天 18:00 触发汇总并写文档。差别就在「它替你记得,且会自己动」。## 二、环境准备bashpip install fastapi uvicorn redis openaidocker run -d --name agent-redis -p 6379:6379 redis:7Redis 承担三件事:目标队列(pending tasks)、状态快照(agent state)、反馈日志(feedback log)。用 Redis 而不是内存,是为了进程重启后不丢上下文。## 三、最小化常驻 Agent 骨架下面这个 FastAPI 应用实现了「提交目标 → 后台循环执行 → 记录反馈 → 可恢复」的完整闭环:```pythonimport asyncio, json, time, openaiimport redis.asyncio as aioredisfrom fastapi import FastAPI, BackgroundTasksapp = FastAPI()r = aioredis.Redis(host="localhost", port=6379, decode_responses=True)MODEL = "gpt-6-sol" # 按你自己的可用模型替换client = openai.AsyncOpenAI()async def exec_step(goal_id: str, step: str) -> str: # 1) 读当前状态 state = json.loads(await r.get(f"agent:{goal_id}:state") or "{}") # 2) 调模型推进一步 resp = await client.chat.completions.create( model=MODEL,
messages=[ {"role": "system", "content": f"你是常驻执行体,目标={state.get('goal')}"}, {"role": "user", "content": f"下一步执行:{step}。当前进度:{state}"}, ], max_tokens=400, ) result = resp.choices[0].message.content # 3) 写回状态 + 追加反馈日志 state["last_result"] = result state["updated_at"] = int(time.time()) await r.set(f"agent:{goal_id}:state", json.dumps(state)) await r.rpush(f"agent:{goal_id}:feedback", json.dumps({"step": step, "result": result})) return resultasync def loop_until_done(goal_id: str): while True: state = json.loads(await r.get(f"agent:{goal_id}:state") or "{}") if state.get("done"): break plan = state.get("plan", []) idx = state.get("cursor", 0) if idx >= len(plan): break await exec_step(goal_id, plan[idx]) await r.hset(f"agent:{goal_id}:state", "cursor", idx + 1) # 断点可恢复 await asyncio.sleep(2) # 控制节奏,避免打爆 API@app.post("/goal")async def submit_goal(goal: str, plan: list[str], bg: BackgroundTasks): goal_id = f"g_{int(time.time())}" await r.set(f"agent:{goal_id}:state", json.dumps( {"goal": goal, "plan": plan, "cursor": 0, "done": False})) bg.add_task(loop_until_done, goal_id) return {"goal_id": goal_id, "status": "running"}```提交一个目标:`curl -XPOST /goal?goal=每日汇总竞品价格&plan=["抓页面","比价","写周报"]`,后台就会按步执行,每一步结果都落 Redis。进程挂了重启,从 `cursor` 接着跑,不会重复第一步。