melech-buy-vs-build
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuy vs Build
外购 vs 自研
An agent asked to "add background jobs" will happily write a 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
— rebuilt badly, and now owned forever.
taskspackage.jsonNobody 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-buildThink "is there an AI for that?" — but for the build-vs-buy call, and
grounded in evidence instead of vibes.
当让一个Agent实现“添加后台任务”功能时,它会欣然创建一个表、轮询工作器、重试列以及死信标记。这确实能运行,但其实这就是BullMQ、Trigger.dev、Cloud Tasks,或者已经存在于中的队列库——只是被糟糕地重写了一遍,而且从此要由你方永久维护。
taskspackage.json没人会刻意做出这种选择。代码库层面的评审只会问“我们代码里已经有这个功能了吗?”,而模型的记忆会用自信但过时甚至虚构的包名来回答外部问题。这个代价高昂、难以逆转的决策——是自行实现能力,还是将其交给第三方——就这样默认做出,而非基于证据。
melech-buy-vs-build可以把它理解为“有没有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.
| Intent | Trigger | Goal |
|---|---|---|
| Intercept | Code, a plan, or a diff exists and may be reinventing something. | Name what was (re)built, find the incumbents, decide adopt vs. keep building. |
| Explore | Open-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 finds
blog posts. An agent that recognizes the capability as durable background job
execution finds the entire category.
"postgres polling table worker"So before any search: translate the implementation into the canonical term the
industry uses for it.
| What the agent built | What to actually search |
|---|---|
| Rows in a table + a polling worker + retry count | job queue, background jobs, durable task execution |
| Custom event bus with handler registry | pub/sub, message broker, event bus |
| Hand-rolled retry-with-jitter wrapper | retry library, resilience/backoff library |
| Bespoke role/permission matcher | authorization / policy engine, RBAC / ReBAC |
Cron-ish | job scheduler, distributed cron, workflow orchestration |
| Diff-and-apply state machine for a wizard | state machine library, workflow engine |
| Custom CSV/Excel export writer | spreadsheet / 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的 | 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-circuitstext
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.
| Lane | What 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. |
| Canon | The category's standard name and the 3–8 options every comparison lists. Awesome-lists, category pages, "X vs Y" roundups. |
| Ecosystem | Libraries and OSS in this project's language. Package registries, GitHub, framework-native answers. |
| Commercial | Managed services, dev tools, SaaS, cloud primitives. Includes the boring cloud answer nobody mentions. |
| Verdicts | What practitioners actually say: HN/Reddit threads, "we migrated off X", postmortems, why people regret each option. |
| Counter-case | Why 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 . Give every lane the capability statement, the
constraints from step 2, its one question, a source cap, and the evidence
contract.
references/lanes.md并发调度独立的调研分支——每个分支对应一个子Agent,每个分支沿自身路径执行多次网络搜索(复用vs重造分支除外,主要是本地检查)。不同分支寻找不同类型的答案,而非不同关键词。向内分支和向外分支同时启动,避免将向内检查作为串行步骤增加延迟。
| 分支 | 调研目标 |
|---|---|
| 复用vs重造(向内,优先级最高) | 步骤2的深度检查:传递依赖、框架/标准库内置功能、已覆盖该能力的供应商方案、内部单体库。主要是本地工作加针对性文档查询。直接终止权限——见下文。 |
| 标准方案 | 该品类的标准名称,以及所有对比文章都会列出的3-8个选项。Awesome列表、品类页面、“X vs Y”综合评测。 |
| 生态方案 | 适配当前项目语言的库与开源软件。包注册表、GitHub、框架原生方案。 |
| 商业方案 | 托管服务、开发工具、SaaS、云原生服务。包括没人提及的常规云方案。 |
| 用户反馈 | 从业者的真实评价:HN/Reddit帖子、“我们从X迁移了”、事后复盘、人们后悔选择某方案的原因。 |
| 反向论证 | 何时自行实现才是正确选择,以及成熟方案的已知失败模式。确保候选清单客观。 |
对于探索意图,增加一个前沿方案分支,调研过去6-12个月发布的新方案,因为模型记忆在这部分往往过时。
直接终止规则:如果复用vs重造分支确认找到匹配项——你已拥有的真实可用能力能满足需求——则流程立即终止。向外分支的结果将被丢弃(并行执行向内和向外分支的代价就是可能浪费部分算力)。报告已拥有的选项并停止;不要为已付费的能力寻找替代方案。
根据决策重要性调整分支数量:“是否有重试库”这类问题用3个分支,“是否应自研编排器”这类问题用全部6个分支。不要为每个网站创建分支——来源是分支的调研渠道,而非工作单元。
如果用户提供了初始名称、来源或“也检查X”,将这些内容分配到专门分支,不要分散其他分支的注意力。
分支说明、查询模式、调研渠道和候选条目结构详见。每个分支需要能力说明、步骤2的约束条件、自身的调研问题、来源上限和证据规范。
references/lanes.md4. 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.md5. 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,不新增供应商)
| Option | Kind | Why it fits | Cost | What you give up | Adoption effort |
|---|---|---|---|---|---|
| OSS lib | Runs on the Postgres you already have; no new infra. | Free | Throughput ceiling vs. Redis-backed. | ~half a day |
| BullMQ | OSS lib | Mature, huge ecosystem, good observability. | Free + Redis | Requires Redis you don't run today. | ~2 days incl. infra |
| Trigger.dev | SaaS/OSS | Durable workflows + retries + UI out of the box. | Paid tier / self-host | New vendor; violates the stated constraint. | ~1 day hosted |
Already in your stack: none — is not installed; Redis is not provisioned.
bullWhat no option gives you: the per-tenant fairness rule in .
Any adoption keeps that logic as your own scheduling layer.
worker.ts:88When 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.| 选项 | 类型 | 适配原因 | 成本 | 取舍点 | 接入工作量 |
|---|---|---|---|---|---|
| 开源库 | 运行在你已有的Postgres上;无需新增基础设施。 | 免费 | 吞吐量上限低于Redis方案。 | 约半天 |
| BullMQ | 开源库 | 成熟、生态庞大、可观测性良好。 | 免费 + Redis | 需要你当前未部署的Redis。 | 约2天(含基础设施部署) |
| Trigger.dev | SaaS/开源 | 开箱即用的持久化工作流 + 重试 + UI。 | 付费版/自托管 | 新增供应商;违反既定约束。 | 约1天(托管版) |
你的技术栈中已存在的方案:无 —— 未安装;未部署Redis。
bull所有方案均不支持的功能:中的租户公平性规则。无论采用哪种方案,该逻辑都需保留为自定义调度层。
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-kitAlways 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 () and
conclude nothing exists.
"tasks table with status column"Do: Check the manifests first — " is already a transitive dep;
your custom backoff wrapper is 40 lines of it."
p-retryDon'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"正确做法:首先检查清单——“已是传递依赖;你的自定义退避包装器只是它的40行简化版。”
p-retry错误做法:当能力已安装或已付费时,仍推荐新增供应商。
正确做法:“其中三个方案已失效:最后发布于2021年,仓库已归档,公司被收购后停止维护。将其剔除。”
错误做法:为了显得调研全面,在候选清单中加入已废弃项目。
正确做法:“所有方案均不支持你的租户公平性规则。无论如何,该部分都需由你自行维护。”
错误做法:在未说明缺失功能的情况下,暗示某库可直接替换现有实现。
正确做法:“以你的业务规模,手动实现的版本确实更简单。保留它。”
错误做法:每次都得出“使用库”的结论。总是推荐采用现有方案的技能不是调研,只是条件反射。
正确做法:呈现候选清单并让用户选择。
错误做法:因为存在更流行的方案就开始替换可用代码。",