用 OpenClaw + Vercel + Supabase 搭建 AI 公司——两周后它们自己运营了

6 个 AI 智能体,1 台 VPS,1 个 Supabase 数据库——从"智能体能对话"到"智能体自主运营网站",我花了两周时间。这篇文章讲的就是中间缺失的部分、如何修复,以及一套你可以直接拿去用的架构。

起点:你有了 OpenClaw,然后呢?

如果你最近在玩 AI 智能体,大概率已经装好了 OpenClaw。

它解决了一个大问题:让 Claude 能用工具、浏览网页、操作文件、运行定时任务。你可以给智能体分配 cron 任务——每日发推、每小时情报扫描、定期研究报告。

我也是从这里开始的。

我的项目叫 VoxYZ Agent World——6 个 AI 智能体在一个像素风办公室里自主运营一个网站。技术栈很简单:

  • OpenClaw(VPS 上):智能体的"大脑"——负责圆桌讨论、cron 任务、深度研究
  • Next.js + Vercel:网站前端 + API 层
  • Supabase:所有状态的唯一数据源(提案、任务、事件、记忆)

六个角色各司其职:Minion 做决策,Sage 分析策略,Scout 收集情报,Quill 写内容,Xalt 管社交媒体,Observer 做质量检查。

OpenClaw 的 cron 任务让它们每天"来上班"。圆桌功能让它们讨论、投票、达成共识。

但这只是"能对话",还不是"能运营"。

智能体产出的所有内容——推文草稿、分析报告、内容文章——都停留在 OpenClaw 的输出层。没有东西把它变成实际执行,也没有东西在执行完后告诉系统"搞定了"。

从"智能体能产出内容"到"智能体能端到端运行",中间缺了一个完整的 执行 → 反馈 → 重新触发 的闭环。这就是这篇文章要讲的。

闭环长什么样

先定义"闭环",免得搞错方向。

一个真正无人值守的智能体系统需要这个循环不断运行:

智能体提出想法(提案)
     ↓
自动审批检查
     ↓
创建任务 + 步骤
     ↓
Worker 认领并执行
     ↓
发出事件
     ↓
触发新的反应
     ↓
回到第一步

听起来简单?实际操作中我踩了三个坑——每一个都让系统"看起来在跑,实际在空转"。

坑 1:两个地方争抢工作

我的 VPS 上 OpenClaw worker 在认领并执行任务。同时 Vercel 上有一个心跳 cron 在跑 mission-worker,也在试图认领同样的任务。

两边查同一张表,抢同一个步骤,各自独立执行。没有协调,纯粹的竞态条件。偶尔一个步骤会被两边打上冲突的状态。

修复:砍掉一边。VPS 是唯一的执行者。Vercel 只跑轻量的控制平面(评估触发器、处理反应队列、清理卡住的任务)。

改动很小——从心跳路由中移除 runMissionWorker 调用:

// 心跳现在只做 4 件事
const triggerResult = await evaluateTriggers(sb, 4_000);
const reactionResult = await processReactionQueue(sb, 3_000);
const learningResult = await promoteInsights(sb);
const staleResult = await recoverStaleSteps(sb);

额外好处:省了 Vercel Pro 的费用。心跳不再需要 Vercel 的 cron——VPS 上一行 crontab 搞定:

*/5 * * * * curl -s -H "Authorization: Bearer $KEY" https://yoursite.com/api/ops/heartbeat

坑 2:触发了但没人接

我写了 4 个触发器:推文爆了自动分析、任务失败自动诊断、内容发布后自动审查、洞察获得多个点赞后自动提升。

测试时发现:触发器正确检测到了条件并创建了提案。但提案永远停在 pending——从没变成任务,也从没生成可执行的步骤。

原因:触发器直接插入 ops_mission_proposals 表,但正常的审批流程是:插入提案 → 评估自动审批 → 如果通过,创建任务 + 步骤。触发器跳过了后面两步。

修复:提取一个共享函数 createProposalAndMaybeAutoApprove。所有创建提案的路径——API、触发器、反应——都必须调用这一个函数。

// proposal-service.ts — 所有提案创建的唯一入口
export async function createProposalAndMaybeAutoApprove(
  sb: SupabaseClient,
  input: ProposalServiceInput,
): Promise<ProposalServiceResult> {
  // 1. 检查每日限额
  // 2. 检查 Cap Gates
  // 3. 插入提案
  // 4. 发出事件
  // 5. 评估自动审批
  // 6. 如果通过 → 创建任务 + 步骤
  // 7. 返回结果
}

改完后触发器只返回提案模板,由评估器调用服务:

// trigger-evaluator.ts
if (outcome.fired && outcome.proposal) {
  await createProposalAndMaybeAutoApprove(sb, {
    ...outcome.proposal,
    source: 'trigger',
  });
}

一个函数统治一切。未来任何检查逻辑(限流、黑名单、新的上限)——改一个文件就行。

坑 3:配额满了但队列还在增长

最隐蔽的 bug——表面上一切正常,日志没报错,但数据库里排队的步骤越来越多。

原因:推文配额满了,但提案仍在被批准,生成任务,生成排队步骤。VPS worker 看到配额满了就直接跳过——没认领,也没标记失败。第二天又来一批。

修复:Cap Gates——在提案入口就拒绝。根本不让它生成排队步骤。

const STEP_KIND_GATES: Record<string, StepKindGate> = {
  write_content: checkWriteContentGate,  // 检查每日内容上限
  post_tweet:    checkPostTweetGate,     // 检查推文配额
  deploy:        checkDeployGate,        // 检查部署策略
};

每种步骤有自己的门禁。推文配额满了?提案直接被拒,原因清楚写明,警告事件发出。没有排队步骤 = 没有堆积。

示例——推文门禁:

async function checkPostTweetGate(sb: SupabaseClient) {
  const autopost = await getOpsPolicyJson(sb, 'x_autopost', {});
  if (autopost.enabled === false) return { ok: false, reason: 'x_autopost disabled' };

  const quota = await getOpsPolicyJson(sb, 'x_daily_quota', {});
  const limit = Number(quota.limit ?? 10);
  const { count } = await sb
    .from('ops_tweet_drafts')
    .select('id', { count: 'exact', head: true })
    .eq('status', 'posted')
    .gte('posted_at', startOfTodayUtcIso());

  if ((count ?? 0) >= limit) return { ok: false, reason: `Daily tweet quota reached (${count}/${limit})` };
  return { ok: true };
}

核心原则:在门口拒绝,不要在队列里堆积。 被拒的提案会被记录(用于审计),而不是默默丢弃。

让它活起来:触发器 + 反应矩阵

三个坑修完,闭环能跑了。但系统只是一条"无错误的流水线",还不是一个"有响应能力的团队"。

触发器

4 条内置规则——每条检测一个条件并返回提案模板:

条件动作冷却时间
推文互动率 > 5%Growth 分析为什么爆了2 小时
任务失败Sage 诊断根因1 小时
新内容发布Observer 审查质量2 小时
洞察获得多个点赞自动提升为永久记忆4 小时

触发器只负责检测——不直接操作数据库,而是把提案模板交给提案服务。所有 Cap Gates 和自动审批逻辑自动生效。

冷却时间很重要。没有它,一条爆了的推文会在每个心跳周期(每 5 分钟)都触发一次分析。

反应矩阵

最有意思的部分——自发的智能体间交互。

存储在 ops_policy 表中的 reaction_matrix

{
  "patterns": [
    { "source": "twitter-alt", "tags": ["tweet","posted"], "target": "growth",
      "type": "analyze", "probability": 0.3, "cooldown": 120 },
    { "source": "*", "tags": ["mission:failed"], "target": "brain",
      "type": "diagnose", "probability": 1.0, "cooldown": 60 }
  ]
}

Xalt 发了一条推 → 30% 概率 Growth 会分析其表现。任何任务失败 → 100% 概率 Sage 会诊断。

probability 不是 bug,是特性。100% 确定性 = 机器人。加入随机性 = 更像一个真实团队——“有时候有人回应,有时候没有”。

自愈:系统必然会卡住

VPS 重启、网络抖动、API 超时——步骤会卡在 running 状态,但实际上没人在处理。

心跳中包含 recoverStaleSteps

// 30 分钟没进展 → 标记失败 → 检查任务是否应该结束
const STALE_THRESHOLD_MS = 30 * 60 * 1000;

const { data: stale } = await sb
  .from('ops_mission_steps')
  .select('id, mission_id')
  .eq('status', 'running')
  .lt('reserved_at', staleThreshold);

for (const step of stale) {
  await sb.from('ops_mission_steps').update({
    status: 'failed',
    last_error: 'Stale: no progress for 30 minutes',
  }).eq('id', step.id);
  await maybeFinalizeMissionIfDone(sb, step.mission_id);
}

maybeFinalizeMissionIfDone 检查任务中的所有步骤——有任何失败意味着整个任务失败,全部完成才算成功。不再出现"一个步骤成功了整个任务就被标记为成功"的情况。

完整架构

三层架构,职责清晰:

  • OpenClaw(VPS):思考 + 执行(大脑 + 双手)
  • Vercel:审批 + 监控(控制平面)
  • Supabase:所有状态(共享皮层)

你可以带走的东西

如果你有 OpenClaw + Vercel + Supabase,这是最小可行闭环清单:

1. 数据库表(Supabase)

至少需要:

用途
ops_mission_proposals存储提案(pending/accepted/rejected)
ops_missions存储任务(approved/running/succeeded/failed)
ops_mission_steps存储执行步骤(queued/running/succeeded/failed)
ops_agent_events存储事件流(所有智能体动作)
ops_policy存储策略(auto_approve、x_daily_quota 等,JSON 格式)
ops_trigger_rules存储触发规则
ops_agent_reactions存储反应队列
ops_action_runs存储执行日志

2. 提案服务(一个文件)

把提案创建 + Cap Gates + 自动审批 + 任务创建放在 一个函数 里。所有来源(API、触发器、反应)都调用它。这是整个闭环的枢纽。

3. 策略驱动的配置(ops_policy 表)

不要硬编码限制。所有行为开关都在 ops_policy 表中:

// auto_approve: 哪些步骤类型允许自动通过
{ "enabled": true, "allowed_step_kinds": ["draft_tweet","crawl","analyze","write_content"] }

// x_daily_quota: 每日推文上限
{ "limit": 8 }

// worker_policy: Vercel 是否执行步骤(设为 false = 仅 VPS)
{ "enabled": false }

随时调整策略,无需重新部署代码。

4. 心跳(一个 API 路由 + 一行 crontab)

Vercel 上的 /api/ops/heartbeat 路由。VPS 上一行 crontab 每 5 分钟调用它。内部运行:触发器评估、反应队列处理、洞察提升、过期任务清理。

5. VPS Worker 契约

每种步骤对应一个 worker。完成步骤后调用 maybeFinalizeMissionIfDone永远不要因为一个步骤完成就把整个任务标记为成功。

两周时间线

阶段时间完成内容
基础设施已有OpenClaw VPS + Vercel + Supabase
提案 + 审批3 天Proposals API + 自动审批 + 策略表
执行引擎2 天mission-worker + 8 个步骤执行器
触发器 + 反应2 天4 种触发类型 + 反应矩阵
闭环统一1 天proposal-service + Cap Gates + 修复三个坑
情感系统 + 视觉2 天情感重写 + 空闲行为 + 像素办公室集成
初始化 + 上线半天迁移 + 种子策略 + crontab

不算已有基础设施,核心闭环(提案 → 执行 → 反馈 → 重新触发)大约需要一周时间搭建。

最后的想法

这 6 个智能体现在每天自主运营 voxyz.space。我仍在每天优化系统——调整策略、扩展触发规则、改进智能体之间的协作方式。

还远未完美——智能体间协作仍然很基础,“自由意志"主要是通过基于概率的非确定性来模拟的。但系统确实在运行,确实不需要有人盯着。

下篇文章我会讲智能体如何"争论"和"说服"彼此——圆桌投票和 Sage 的记忆整合如何把 6 个独立的 Claude 实例变成类似团队认知的东西。

如果你也在用 OpenClaw 搭建智能体系统,我很乐意交流。作为独立开发者做这个,每一次对话都能帮你避免又一个坑。