melech-buy-vs-build

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Buy vs Build

外购 vs 自研

An agent asked to "add background jobs" will happily write a
tasks
table, a polling worker, a retry column, and a dead-letter flag. It works. It is also BullMQ, or Trigger.dev, or Cloud Tasks, or the queue library already sitting in
package.json
— rebuilt badly, and now owned forever.
Nobody makes the call deliberately. Repo-level review only ever asks "does this already exist in our code?", and model memory answers external questions with confident, stale, sometimes invented package names. The expensive, hard-to-reverse decision — own the implementation, or hand the capability to a third party — gets made by default instead of on evidence.
melech-buy-vs-build
owns that decision. It looks outward — finding what the rest of the world already shipped for the capability, verified against live sources — and it runs one inward check first: adopt-vs-rebuild, is this already covered by a dependency or vendor you already have? Then it brings back a shortlist and a verdict: adopt, or keep building.
Think "is there an AI for that?" — but for the build-vs-buy call, and grounded in evidence instead of vibes.

当让一个Agent实现“添加后台任务”功能时,它会欣然创建一个
tasks
表、轮询工作器、重试列以及死信标记。这确实能运行,但其实这就是BullMQ、Trigger.dev、Cloud Tasks,或者已经存在于
package.json
中的队列库——只是被糟糕地重写了一遍,而且从此要由你方永久维护。
没人会刻意做出这种选择。代码库层面的评审只会问“我们代码里已经有这个功能了吗?”,而模型的记忆会用自信但过时甚至虚构的包名来回答外部问题。这个代价高昂、难以逆转的决策——是自行实现能力,还是将其交给第三方——就这样默认做出,而非基于证据。
melech-buy-vs-build
负责这个决策。它会向外调研——寻找全球范围内已实现该能力的现有方案,并通过实时来源验证——同时首先执行一项向内检查复用vs重造,你现有的依赖或供应商是否已经覆盖了该能力?之后它会返回一份候选清单和结论:采用现有方案,或继续自研。
可以把它理解为“有没有AI能做这件事?”——但针对的是外购vs自研的决策,并且完全基于证据而非主观感觉。

Two Intents

两种意图

Both intents are outward research feeding one build-vs-buy verdict. Whichever fires, run the inward adopt-vs-rebuild check first (step 2) — a capability you already own beats anything you would go find or build.
IntentTriggerGoal
InterceptCode, a plan, or a diff exists and may be reinventing something.Name what was (re)built, find the incumbents, decide adopt vs. keep building.
ExploreOpen-ended: "what's out there for X", "any new tools for X", "how do people do X now".Map the space, surface the notable and the recent, arm the user to choose.
Do not ask which intent applies when it is obvious from the input. A diff or a proposal means intercept. A bare capability question means explore.

两种意图都是向外调研,最终服务于同一个外购vs自研的结论。无论触发哪种意图,都要先执行向内的复用vs重造检查(步骤2)——你已拥有的能力,比任何你要寻找或构建的方案都更优。
意图触发条件目标
拦截已存在代码、计划或差异,可能在重复造轮子。明确被(重新)构建的功能是什么,找到行业内成熟方案,决定是采用现有方案还是继续自研。
探索开放式问题:“针对X有哪些现成方案?”“有没有针对X的新工具?”“现在大家都是怎么做X的?”梳理方案全景,呈现值得关注的近期方案,帮助用户做出选择。
当输入内容明显对应某一意图时,无需询问用户。差异或提案对应拦截意图,单纯的能力问题对应探索意图。

The One Rule That Decides Everything

决定一切的核心规则

Search the capability, not the noun.
The single reason this research fails is searching the user's own vocabulary. An agent that greps the web for
"postgres polling table worker"
finds blog posts. An agent that recognizes the capability as durable background job execution finds the entire category.
So before any search: translate the implementation into the canonical term the industry uses for it.
What the agent builtWhat to actually search
Rows in a table + a polling worker + retry countjob queue, background jobs, durable task execution
Custom event bus with handler registrypub/sub, message broker, event bus
Hand-rolled retry-with-jitter wrapperretry library, resilience/backoff library
Bespoke role/permission matcherauthorization / policy engine, RBAC / ReBAC
Cron-ish
setInterval
+ lockfile
job scheduler, distributed cron, workflow orchestration
Diff-and-apply state machine for a wizardstate machine library, workflow engine
Custom CSV/Excel export writerspreadsheet / serialization library
If unsure of the canonical term, the first search is for the term itself: "what is it called when …". Get the vocabulary right, then fan out.

搜索能力本身,而非具体名词。
调研失败的唯一原因是使用用户自己的词汇进行搜索。如果Agent在网上搜索
"postgres polling table worker"
,找到的只会是博客文章;但如果它能识别出该能力属于持久化后台任务执行,就能找到整个品类的方案。
因此,在任何搜索之前:要将具体实现转化为行业通用的标准术语。
Agent构建的内容实际应搜索的术语
表行 + 轮询工作器 + 重试次数job queue, background jobs, durable task execution
带处理器注册的自定义事件总线pub/sub, message broker, event bus
手动实现的带抖动重试包装器retry library, resilience/backoff library
定制化角色/权限匹配器authorization / policy engine, RBAC / ReBAC
类Cron的
setInterval
+ 锁文件
job scheduler, distributed cron, workflow orchestration
向导的差异应用状态机state machine library, workflow engine
自定义CSV/Excel导出工具spreadsheet / serialization library
如果不确定标准术语,首先搜索:“当……时,它被称为什么?”。先确定正确的词汇,再展开搜索。

Workflow

工作流程

text
1. Name the capability  ─►  2. Read the ground truth  ─►  3. Fan out lanes  ─────────►  4. Reduce  ─►  5. Shortlist + verdict  ─►  6. Hand off
   (canonical vocabulary)     (stack, constraints)          adopt-vs-rebuild (inward) ┐   (dedupe, kill dead)   (ask_question)
                                                            outward lanes (web)       ┴─ same concurrent batch;
                                                                                          inward hit short-circuits
text
1. 定义能力  ─►  2. 梳理基础事实  ─►  3. 并行调研分支  ─────────►  4. 整合结果  ─►  5. 候选清单 + 结论  ─►  6. 交付执行
   (标准术语)     (技术栈、约束条件)          复用vs重造(向内) ┐   (去重、淘汰无效项)   (发起决策询问)
                                                            向外调研分支(网络)       ┴─ 同一并发批次;
                                                                                          向内命中则直接终止流程

1. Name the capability

1. 定义能力

State in one line what the thing does, stripped of the local implementation. List 2–5 canonical search terms and any obvious synonyms. Show this to the user before fanning out — a wrong capability name wastes the whole run.
用一句话描述该功能的作用,剥离本地实现细节。列出2-5个标准搜索术语及明显同义词。在展开调研前展示给用户——错误的能力定义会导致整个调研无效。

2. Read the ground truth (inline, must be first)

2. 梳理基础事实(内联,必须优先执行)

This quick read stays on the main thread because the outward lanes cannot be briefed without it. Gather the constraints that will decide fit:
  • Language and runtime, and what is already in the manifests (
    package.json
    ,
    requirements.txt
    /
    pyproject.toml
    ,
    go.mod
    ,
    Cargo.toml
    ,
    Gemfile
    ,
    pom.xml
    )
  • Infrastructure already paid for: cloud provider, Postgres/Redis/Kafka, vendors already in the bill
  • Hard constraints: self-host only, data residency, licensing policy, air-gapped, no new vendors, budget
  • Scale reality: 100 jobs/day and 100k jobs/second do not shortlist the same tools
If this cheap read already surfaces a blatant hit — the capability is literally a direct dependency or an obviously enabled vendor feature — stop here and report it. Do not fan out to buy something you already own. Otherwise, carry the constraints into step 3 and let the deep adopt-vs-rebuild check run concurrently.
这一步快速检查在主线程执行,因为向外调研分支需要这些信息才能开展。收集决定方案适配性的约束条件:
  • 语言与运行时,以及清单中已有的依赖 (
    package.json
    ,
    requirements.txt
    /
    pyproject.toml
    ,
    go.mod
    ,
    Cargo.toml
    ,
    Gemfile
    ,
    pom.xml
    )
  • 已付费的基础设施:云服务商、Postgres/Redis/Kafka、已在账单中的供应商
  • 硬性约束:仅支持自托管、数据驻留要求、许可政策、离线环境、不新增供应商、预算限制
  • 规模实际情况:每天100个任务和每秒10万个任务的候选工具完全不同
如果这一步就发现明显匹配项——该能力确实是直接依赖或已启用的供应商功能——则立即停止并报告结果。不要去外购你已经拥有的能力。否则,将约束条件带入步骤3,同时让深度的复用vs重造检查并发执行。

3. Fan out parallel lanes

3. 并行调研分支

Dispatch independent research lanes concurrently — one subagent per lane, each running multiple web searches along its own path (except adopt-vs-rebuild, which is mostly local). Lanes hunt different kinds of answers, not different keywords. The inward lane and the outward lanes launch in the same concurrent batch, so you do not pay the inward check as serial latency.
LaneWhat it hunts
Adopt-vs-rebuild (inward, privileged)The deep version of the step-2 check: transitive deps, framework/stdlib built-ins, a vendor plan that already covers this, an internal monorepo library. Mostly local work plus targeted doc lookups. Short-circuit authority — see below.
CanonThe category's standard name and the 3–8 options every comparison lists. Awesome-lists, category pages, "X vs Y" roundups.
EcosystemLibraries and OSS in this project's language. Package registries, GitHub, framework-native answers.
CommercialManaged services, dev tools, SaaS, cloud primitives. Includes the boring cloud answer nobody mentions.
VerdictsWhat practitioners actually say: HN/Reddit threads, "we migrated off X", postmortems, why people regret each option.
Counter-caseWhy rolling your own is sometimes right here, and the known failure modes of the incumbents. Keeps the shortlist honest.
For explore intent, add a Frontier lane for what shipped in the last 6–12 months, since that is exactly where model memory is stale.
Short-circuit rule: if the adopt-vs-rebuild lane returns a confirmed hit — a real, live capability you already own that covers the need — the run ends. The outward lanes' results are discarded (that wasted compute is the price of running inward and outward in parallel instead of gating). Report the owned option and stop; do not shop for a replacement for something already paid for.
Scale the lane count to the stakes: 3 lanes for "is there a retry library", all 6 for "should we build our own orchestrator". Do not spawn a lane per website — a source is where a lane looks, not the unit of work.
If the user supplied seed names, sources, or "check X too", route those into a dedicated lane rather than diluting the others.
Lane briefs, query patterns, hunting grounds, and the candidate row schema live in
references/lanes.md
. Give every lane the capability statement, the constraints from step 2, its one question, a source cap, and the evidence contract.
并发调度独立的调研分支——每个分支对应一个子Agent,每个分支沿自身路径执行多次网络搜索(复用vs重造分支除外,主要是本地检查)。不同分支寻找不同类型的答案,而非不同关键词。向内分支和向外分支同时启动,避免将向内检查作为串行步骤增加延迟。
分支调研目标
复用vs重造(向内,优先级最高)步骤2的深度检查:传递依赖、框架/标准库内置功能、已覆盖该能力的供应商方案、内部单体库。主要是本地工作加针对性文档查询。直接终止权限——见下文。
标准方案该品类的标准名称,以及所有对比文章都会列出的3-8个选项。Awesome列表、品类页面、“X vs Y”综合评测。
生态方案适配当前项目语言的库与开源软件。包注册表、GitHub、框架原生方案。
商业方案托管服务、开发工具、SaaS、云原生服务。包括没人提及的常规云方案。
用户反馈从业者的真实评价:HN/Reddit帖子、“我们从X迁移了”、事后复盘、人们后悔选择某方案的原因。
反向论证何时自行实现才是正确选择,以及成熟方案的已知失败模式。确保候选清单客观。
对于探索意图,增加一个前沿方案分支,调研过去6-12个月发布的新方案,因为模型记忆在这部分往往过时。
直接终止规则:如果复用vs重造分支确认找到匹配项——你已拥有的真实可用能力能满足需求——则流程立即终止。向外分支的结果将被丢弃(并行执行向内和向外分支的代价就是可能浪费部分算力)。报告已拥有的选项并停止;不要为已付费的能力寻找替代方案。
根据决策重要性调整分支数量:“是否有重试库”这类问题用3个分支,“是否应自研编排器”这类问题用全部6个分支。不要为每个网站创建分支——来源是分支的调研渠道,而非工作单元。
如果用户提供了初始名称、来源或“也检查X”,将这些内容分配到专门分支,不要分散其他分支的注意力。
分支说明、查询模式、调研渠道和候选条目结构详见
references/lanes.md
。每个分支需要能力说明、步骤2的约束条件、自身的调研问题、来源上限和证据规范。

4. Reduce

4. 整合结果

Merge all lanes, then: verify-or-drop → kill dead → dedupe identities → cluster by approach (not name) → rank by fit to the step-2 constraints (popularity is only a tiebreaker, never the criterion). The full merge rules — dead-cutoffs, identity and origin collapsing, hard-constraint disqualification — live in
references/lanes.md
.
合并所有分支的结果,然后:验证或丢弃 → 淘汰无效项 → 去重 → 按实现思路(而非名称)聚类 → 按步骤2的约束条件适配度排序(流行度仅作为平局决胜因素,而非主要标准)。完整的合并规则——无效项判定标准、身份与来源合并规则、硬性约束淘汰规则——详见
references/lanes.md

5. Deliver the shortlist and the verdict

5. 交付候选清单与结论

Cap at 3–6 candidates. A list of twenty is a research dump, not a recommendation.
markdown
undefined
候选数量限制在3-6个。20个选项的列表只是调研数据堆砌,而非推荐。
markdown
undefined

⚖️ Buy vs Build: durable background jobs (Node/TypeScript, Postgres, no new vendors)

⚖️ 外购 vs 自研:持久化后台任务(Node/TypeScript,Postgres,不新增供应商)

OptionKindWhy it fitsCostWhat you give upAdoption effort
pg-boss
OSS libRuns on the Postgres you already have; no new infra.FreeThroughput ceiling vs. Redis-backed.~half a day
BullMQOSS libMature, huge ecosystem, good observability.Free + RedisRequires Redis you don't run today.~2 days incl. infra
Trigger.devSaaS/OSSDurable workflows + retries + UI out of the box.Paid tier / self-hostNew vendor; violates the stated constraint.~1 day hosted
Already in your stack: none —
bull
is not installed; Redis is not provisioned.
What no option gives you: the per-tenant fairness rule in
worker.ts:88
. Any adoption keeps that logic as your own scheduling layer.
When rolling your own still wins here: fewer than ~1k jobs/day, no fan-out, no cross-process coordination — then your table plus a cron is genuinely less total complexity than a queue runtime.

Then put the decision to the user with `ask_question`:

1. `Adopt <recommended option> and remove the hand-rolled version`
2. `Adopt, but keep the custom layer for <the part nothing covers>`
3. `Keep the custom implementation (record why)`
4. `Research further — different constraints or more options`

**Never rip out working code on your own initiative.** This skill reports and
recommends the buy-vs-build call. The user rules.
选项类型适配原因成本取舍点接入工作量
pg-boss
开源库运行在你已有的Postgres上;无需新增基础设施。免费吞吐量上限低于Redis方案。约半天
BullMQ开源库成熟、生态庞大、可观测性良好。免费 + Redis需要你当前未部署的Redis。约2天(含基础设施部署)
Trigger.devSaaS/开源开箱即用的持久化工作流 + 重试 + UI。付费版/自托管新增供应商;违反既定约束。约1天(托管版)
你的技术栈中已存在的方案:无 —— 未安装
bull
;未部署Redis。
所有方案均不支持的功能
worker.ts:88
中的租户公平性规则。无论采用哪种方案,该逻辑都需保留为自定义调度层。
自行实现仍更优的场景:每日任务少于约1000个,无需扇出,无需跨进程协调——此时你的表加Cron确实比队列运行时的整体复杂度更低。

然后通过`ask_question`让用户做出决策:

1. `采用<recommended option>并移除手动实现的版本`
2. `采用现有方案,但保留自定义层以实现<无方案覆盖的功能>`
3. `保留自定义实现(记录原因)`
4. `进一步调研——调整约束条件或查看更多选项`

**绝不能主动替换可用代码**。该技能仅报告并推荐外购vs自研的决策,最终决定权在用户手中。

6. Hand off

6. 交付执行

  • Adopt → integrate it via the smallest path, or realign the design if the swap reshapes it.
  • Keep building → proceed, and leave one WHY comment recording what was evaluated and rejected, so the next agent does not re-run this debate.
  • The need itself now looks shaky → revisit whether the need is real.
  • A shortlisted option needs stress-testing before commitment → proof the pick before writing code.

  • 采用现有方案 → 通过最简路径集成,若替换方案改变设计则重新调整。
  • 继续自研 → 推进开发,并留下一条WHY注释,记录已评估的方案及淘汰原因,避免后续Agent重复此讨论。
  • 需求本身存疑 → 重新确认需求是否真实存在。
  • 候选方案需压力测试 → 在编写代码前验证方案可行性。

Evidence Contract

证据规范

Models hallucinate confident, plausible, nonexistent packages. This skill is worthless if it invents
@vercel/queue-kit
.
Always web search. Memory generates hypotheses; only search produces candidates.
  • Every candidate carries a URL that appeared in live results this run.
  • Every candidate carries a liveness signal: last release, last commit, or a current pricing/docs page.
  • Recalled-but-unverified names are labeled as such and must be confirmed before they reach the shortlist.
  • Version numbers, pricing, limits, and license terms are quoted from the source or omitted. Never estimated.
  • Report an empty lane honestly. "Nothing credible found in this ecosystem" is a real and useful finding.

模型会虚构自信且看似合理的不存在包。如果该技能发明出
@vercel/queue-kit
,它就毫无价值。
必须始终进行网络搜索。记忆仅生成假设;只有搜索才能产生有效候选方案。
  • 每个候选方案都需附带本次调研中实时搜索结果的URL。
  • 每个候选方案都需附带活跃度信号:最后发布版本、最后提交记录,或当前的定价/文档页面。
  • 回忆但未验证的名称需标记,且必须在进入候选清单前完成验证。
  • 版本号、定价、限制和许可条款需直接引用来源或省略。绝不估算。
  • 如实报告无结果的分支。“该生态中未找到可信方案”是真实且有用的结论。

Do / Don't

注意事项

Do: "This is a job queue. Canonical terms: background jobs, durable task execution, work queue. Searching those before anything else."
Don't: Search the user's phrasing (
"tasks table with status column"
) and conclude nothing exists.
Do: Check the manifests first — "
p-retry
is already a transitive dep; your custom backoff wrapper is 40 lines of it."
Don't: Recommend a new vendor when the capability is already installed or already billed.
Do: "Three of these are dead: last release 2021, repo archived, company acquired and sunset. Dropping them."
Don't: Pad the shortlist with abandoned projects to look thorough.
Do: "None of these handle your per-tenant fairness rule. That part stays yours either way."
Don't: Imply a library is a drop-in replacement without saying what it misses.
Do: "At your volume, the hand-rolled version is genuinely simpler. Keep it."
Don't: Conclude "use a library" every time. A skill that always says adopt is not research, it is a reflex.
Do: Present the shortlist and let the user choose.
Don't: Start swapping out working code because a more popular option exists.
正确做法:“这是一个任务队列。标准术语:background jobs, durable task execution, work queue。将优先搜索这些术语。”
错误做法:直接搜索用户的表述(
"tasks table with status column"
)并得出无方案可用的结论。
正确做法:首先检查清单——“
p-retry
已是传递依赖;你的自定义退避包装器只是它的40行简化版。”
错误做法:当能力已安装或已付费时,仍推荐新增供应商。
正确做法:“其中三个方案已失效:最后发布于2021年,仓库已归档,公司被收购后停止维护。将其剔除。”
错误做法:为了显得调研全面,在候选清单中加入已废弃项目。
正确做法:“所有方案均不支持你的租户公平性规则。无论如何,该部分都需由你自行维护。”
错误做法:在未说明缺失功能的情况下,暗示某库可直接替换现有实现。
正确做法:“以你的业务规模,手动实现的版本确实更简单。保留它。”
错误做法:每次都得出“使用库”的结论。总是推荐采用现有方案的技能不是调研,只是条件反射。
正确做法:呈现候选清单并让用户选择。
错误做法:因为存在更流行的方案就开始替换可用代码。",