返回博客

AI Agent 实例启动/停止/重启 API 实战:不想用的时候关掉,改完配置一键重启

2026年7月30日阅读约 15 分钟

AI Agent 实例跑起来之后,怎么暂停、恢复、重启?到期了是直接停用还是自动删除?改了模型配置之后要不要重建容器?本文用怡途Claw 的实例生命周期 API 把这些操作拆开讲清楚。

AI Agent 实例创建完成之后,不是说就扔在那里不管了。实际用起来会遇到几个很现实的问题:

  • 买了个实例,改了大模型配置,怎么让它生效?
  • 套餐到期了忘记续费,实例会被怎么处理?
  • 续费之后,需不需要重新创建一个实例?
  • 不想用的时候能不能先暂停,下次再恢复?

怡途Claw 的实例生命周期 API 就是处理这些事情的。本文不讲概念,直接从 API 接口和代码逻辑来看这几个操作各自做了什么。

先看实例当前状态:GET /api/app/instances

调用 GET /api/app/instances 返回当前用户的所有实例列表,每个实例带上 status 字段,值可能是 running、stopped、error、creating、pending 等。

返回的实例数据里,env 和 token 字段会被过滤掉,不会暴露给调用方。customLLMConfig 里的 apiKey 也会被替换成 [REDACTED]。

如果想看汇总数据,可以调 GET /api/app/instances/stats,返回 total、running、stopped 三个数字,外加按 type 分组的统计。这个接口还会额外返回 subscriptionStatus、packageStatus 和 suspendedInstances。suspendedInstances 是那些因为套餐过期被系统自动暂停的实例数量。

暂停实例:POST /api/app/instances/:id/stop

调用 stop 接口,系统会去 Docker 层面 stop 容器。

代码里有一个细节:如果 Docker 返回的 error message 包含 "304" 或 "already stopped" 或 "not running",系统不会报错,而是直接返回成功。也就是说 stop 是幂等的——你对着一个已经停掉的实例再调一次 stop,不会报 400。

停掉之后,instance.status 变成 stopped,lastStoppedAt 记录下时间。

注意:停掉实例不会删除数据。容器还在,只是进程停了。

恢复实例:POST /api/app/instances/:id/start

start 接口做的事情比 stop 多一些。

第一步,检查实例是否已经在 running 状态,如果是就直接报错。

第二步,检查 expiresAt。如果实例已经过期,直接返回 "实例已过期,请先续费后再启动"。

第三步,如果实例之前因为订阅过期被暂停(isSuspendedDueToSubscription 返回 true),start 会清除暂停状态——把 suspendReason、suspendedAt、scheduledDeleteAt 都置空。也就是说,续费之后只要调一次 start,实例就恢复正常了,不需要重新创建。

第四步,看有没有容器。如果 containerId 为空,说明之前没创建过容器,会调用 createContainer 重新创建。如果 instance.needsRecreate 为 true(说明 LLM 配置更新过),会先删掉旧容器,释放旧端口,再重新创建新容器。

第五步,正常启动容器。如果 Docker 返回 "container already started",系统照样不会报错,直接返回成功。

重启实例:POST /api/app/instances/:id/restart

restart 和 start 有区别:start 是从停止状态恢复,restart 是让正在运行的容器重新启动。

代码里 restart 的流程是:

  1. 检查 expiresAt,过期了直接拒绝。
  2. 检查 containerId 是否存在。
  3. 调用 Docker 的 restartContainer。
  4. 等待 5 秒,确保容器完全重启。
  5. 特殊处理 runtime 类型:如果实例是 claude-code runtime,重启后重新跑 preconfigureClaudeCodeContainer(重建 tmux 会话);如果是 codex runtime,重启后重新写 ~/.codex/config.toml(因为容器可能基于新镜像替换过,配置需要重新落盘)。

这里的 5 秒等待不是随便写的——容器 restart 之后需要时间让内部进程启动,如果不等就直接返回,前端可能拿到的还是旧状态。

改完模型配置,要不要重启?

PUT /api/app/instances/:id/llm-config 更新大模型配置后,实例并不会自动重启。代码里会把 instance.needsRecreate 标记为 true。

下次调用 start 或 restart 的时候,系统检测到 needsRecreate 为 true,会先删掉旧容器,释放旧端口,创建新容器,再启动。这样新的 LLM 配置才会生效。

也就是说,改完配置之后,需要手动调一次 start 或 restart 来激活新的配置。

关于订阅和暂停的联动

接到过几次用户反馈:"我续费了,为什么实例还是用不了?"

原因在于:续费只是更新了套餐的到期时间,但实例本身还处于暂停状态。需要调一次 start 接口,代码里才会把 suspendReason 和 suspendedAt 清掉。

所以续费之后的完整操作流程是:

  1. 续费套餐
  2. GET /api/app/instances/stats 确认 subscriptionStatus 已恢复正常
  3. POST /api/app/instances/:id/start 恢复实例

总结

接口做什么注意点
GET /api/app/instances查实例列表敏感字段已脱敏
GET /api/app/instances/stats查汇总数据含订阅状态和暂停数量
POST /api/app/instances/:id/stop暂停实例幂等,不会删数据
POST /api/app/instances/:id/start恢复实例自动清除暂停状态,过期检查
POST /api/app/instances/:id/restart重启实例5 秒等待,runtime 特殊处理

上面这些接口都是跟 Docker 容器直接打交道的。实例的本质就是一个容器,启动、停止、重启都对应 Docker 的同名操作。理解了这一点,API 的行为就很好理解了。

本文基于怡途Claw 后端 app-instances.controller.ts 与 instances.service.ts 的源码分析。