Twenty Partners Lead Brief 设计文档准则:把客户通话翻译成伙伴可报价的 Twenty 术语
这份指南围绕 Twenty 合作伙伴工作区内的 twenty-lead-brief 技能所依赖的设计文档准则(docctrine)展开:它定义了一份"把合格潜客需求翻译成 Twenty 术语"的伙伴设计文档应该长什么样、包含哪些结构、必须遵守哪些规则、以及如何验证其中的每一条能力声明。读完后,你既能复现这份准则的完整产出规范(头部表格、标志体系、必需/条件章节、零推断模式、--full 模式、自检清单),也能理解它在 twenty-partners 应用与 in-product playbook 中的真实落地方式。
准则是什么,给谁用
源文件位于 design-doc-doctrine.md,它被明确定位为一份可移植准则(portable doctrine):与具体工具无关,只定义"一份 Twenty 伙伴设计文档是什么、结构如何、规则如何、如何验证"。
从源码结构看,它有两个消费者:
- Claude Code 技能 twenty-lead-brief/SKILL.md——当前使用者,负责把销售/发现通话转化为伙伴可报价的 brief;
- 后续阶段中,Twenty
defineSkill的content,驱动 in-product agent 完成同样工作。
因此准则刻意不绑定任何单一工具的运行机制(不写文件路径、不提工具名),并贯彻一条单一事实源原则:每条规则只在这里出现一次,其他位置要复述时,用链接指过来而不是抄一遍。SKILL.md 也遵守了这一点——它的 Step 3 只说"准则在这个文件夹的 design-doc-doctrine.md 里,读它并照做",本节其余内容只保留机械流程。
目的与核心原则
准则要产出的文档,目的是把一位合格潜客(qualified lead)的需求翻译成 Twenty 术语(数据模型、权限、集成、托管,以及客户点名的其他一切),让实施伙伴(partner)能据此定范围并报价。
三条核心原则:
- 识别全部工作,不留盲区(no blindspots);
- 每一条声明都要有依据:要么来自通话等源材料,要么来自主活的 Twenty 文档;
- 呈现选项,而非指定方案(present options rather than prescribe)。伙伴是拿这份文档去报价的,所以"自信但错误的功能声明"和"隐藏的需求"是最坏的失败模式。
另外两条定位约束同样重要:
- 紧盯客户的业务结果:文档的每一行都必须改变伙伴"要构建什么"或客户"将得到什么"。它是设计文档,不是会议记录。
- 面向伙伴、可原样转发:文档可以 verbatim 转发给客户。它是一份"为了让定范围更容易"的建议,不是约束伙伴如何构建的规格书。
输出结构:四字段头部与标志体系
头部:紧凑表格,只有四个字段
头部永远是一个紧凑表格,只含四个字段,绝不用一摞粗体行:
| Field | Value |
|---|---|
| Lead | 名称(一句话描述他们是谁) |
| Date | YYYY-MM-DD |
| Author | Twenty (partnerships) |
| Status | 一行短句(如 "Draft for partner review") |
Status 行必须短:承重性的警告(例如"数据模型是推断,待 discovery 确认")放进后面的 "What this is" callout,而不是塞进头部单元格。永远不列:源材料清单、内部时间线、谁承诺了什么——这些既非承重、也不适合客户看到。
表格之后,放一个 "What this is" callout,把文档框定为覆盖全部表面的伙伴定范围建议,而不是一个 MVP。
标志(Flags):emoji 与文本标签永远成对
- ❓ open——报价前需要解决的开放问题。
- ⚠️ heavy——受产品约束、需要专门设计、或有真实成本。
- 🛑 blocker——交易级(dealbreaker)问题,不解决就不报价。
只有这三个。禁止发明新标志、禁止换 emoji(🟥 / 🚩 / 🚨 / ✅)、禁止丢掉文本标签。--full 模式会新增第四个:🔮 inf.(推断)。
必需章节:顺序编号,不得跳号
章节按顺序编号,不允许有空洞。一份含 Context、Data model、Integrations、Permissions、Hosting、Phasing、Open questions、References 的文档,就是 §1 到 §8。
-
Context——30 秒读完的部分:他们是谁、想要什么、部署要求、规模、语言与地区。
-
Data model in Twenty terms——核心章节。用表格,每个对象一行,列为:
Object | Std/Custom | Represents | Key fields | Core relations。只列客户明确点名的对象;只列客户明确点名的字段;空单元格写—;SELECT 选项集要写明。要建模关系,而不只是字段:谁引入/提供了某条记录(如大使大使对 Opportunity 的
sourcedBy)、父子关系、归属权——这些关系与属性一样携带定范围信号。写成散文、或只列字段不列链接的数据模型章节,就是错过了重点。产品约束只在它改变构建或报价时才写,且写在内联位置:例如没有公式字段,所以报表比率需要一个由 logic function 维护的存储字段;自定义对象自动获得附件、笔记、任务和时间线,所以关系追踪是"免费"的。
当客户术语与 Twenty 术语冲突(他们的 "partner" 其实是 donor)时,在表格上方用小列表"term collisions"内联说明映射。永远不要加一个术语表(glossary)章节。
-
Roles, permissions & RLS——把点名的角色映射到 Twenty 的对象级、字段级和行级模型;针对已验证的、按套餐(plan)门控的能力回答"我们需不需要 RLS?"
-
Hosting & compliance——云还是自托管、数据驻留要求(需验证)、GDPR。矛盾要标出来。
-
Suggested phasing——分层建议,标注"(这是伙伴的决定,不是 Twenty 的)"。
-
Open questions / blindspot-killers——伙伴定价前必须解决的问题清单。这是"用表格和列表代替段落"的唯一刻意例外:这里必须始终是编号列表,这样伙伴可以当着客户的面说"问题 1、2、3"。每一条都要点明它锁住什么决策,并链回正文对应章节。
-
References & verification——先是一张
Claim (§) | Verified against表,然后是显式的"Could not be confirmed in public docs (check with Twenty directly):"列表。引用人类可读的(非.md)URL:.md孪生页面是给你抓取用的,在伙伴的浏览器里渲染出来是裸 markdown。
条件章节:客户没点名,就整节省略
如果客户没有点名某个主题,整节省略。绝不为了说"X 没被提到"而保留一个章节——那是填充物。未知项属于 Open questions。
- Views & navigation——当数据模型规模足以支撑一次界面讨论时纳入。用紧凑表格,列为
Surface | Shows | Audience,每个日常应暴露的表面一行。没有Type列:表格 vs 看板 vs 页面布局是伙伴的选择,不是定范围决策。如果客户点过 pipeline 或布局,记在Shows里。永远不要渲染成项目符号列表;仅当一个横切开放问题需要标注时,补一条后续 bullet。 - Automations——仅当客户点名了要自动化的流程。每个自动化给出 Workflow 或 logic function 两种路径;命名自动化及其触发器。
- Integrations——仅当客户显式点名外部系统(Gmail、Slack、WhatsApp)。写清方向、指示性机制、数据流、风险。客户从未点名的"可能集成",只是一条 ❓ open,不是一个章节。
- Reporting & analytics——仅当客户点名了报表需求。映射到原生 Dashboards;缺口要标出并给出路径。
每个章节的篇幅与其内容相称。覆盖面(surface area coverage)比单条深度更重要。
默认行为:零推断伙伴 brief
默认产出是一份零推断(zero-inference)伙伴 brief:锋利、短小、严格有据:
- 不做任何推断。客户没说的,就不出现。
- 没有有据内容的必需章节只写一行占位:
> ⬜ Not discussed on call — needs input before this section can be filled. - 没有有据内容的条件章节整节省略。占位行只用于必需章节。
- 数据模型单元格没有内容就写
—,绝不填发明值。 - 数据模型表格没有
Source列:每行都是client,这一列只是噪声。 🔮 inf.永不出现。你想用它,说明这一行本不该存在。- 目标长度:1 页。每节 1 到 5 行。
- 验证只对含有据内容的章节执行。
- 文件名:
YYYY-MM-DD-<lead>-partner-brief.md。
Full 模式(--full)
当 discovery 已完成、潜客资料充分、推断能给伙伴更丰富的起始模型时,使用 --full:
| 维度 | Default | --full |
|---|---|---|
| 推断 | 永不 | 允许,标 🔮 inf. |
| 空章节 | 占位行 | 用带标记的推断填充 |
数据模型 Source 列 |
省略 | client / inf. |
| 推断的字段名与关系 | 不出现 | 标 🔮 inf. |
| 长度 | 1 页目标 | 内容需要多长就多长 |
| 验证 | 仅有据章节 | 所有承重声明 |
| 文件名 | …-partner-brief.md |
…-design-doc.md |
核心规则:每条规则都对应它防止的失败
准则的 Rules 部分每条规则都写明"做什么"以及"防止哪种失败",这里完整继承:
- 简洁:每个词承载最大信号。 砍掉清嗓、铺垫、对冲和功能巡礼式文字。长度不等于覆盖:点名每个需求的短文档,胜过给每条注水的长文档。犹豫中的买家看到聚焦的文档;臃肿的文档读起来就是成本。
- 列表和表格优先于段落。 只要行共享结构(对象、视图、套餐、路径)就用表格;只有当某个细微处没有 bullet 或单元格能承载时才用散文。Open questions 的编号列表是唯一刻意例外。
- 业务决策优先于技术机制。 定范围的是伙伴构建什么和客户得到什么:数据敏感性、谁能看什么、套餐选择、托管选择、集成面、成本驱动因素。砍掉不影响报价的 SDK、运行时和构建工具细节:Docker 版本、OAuth 风味、自动系统关系、环境变量名、CI/CD 细节。那些在 References 里读。
- 定范围高度:命名决策,推迟机制。 说出决策及其成本或范围后果,实现细节留给技术阶段。"生产自动化需要一个沙箱 serverless logic-function 后端,这是一笔属于平台工作流的 infra 成本"携带了报价信号;而确切的
LOGIC_FUNCTION_TYPE/LAMBDA/ region / role / key 设置不携带。深挖机制会让文档变长且快速过时。 - 一切有据;推断打标签;绝不扩张范围。 如果概念来自源材料但字段名是你起的,那是推断:打标签。从源材料抬取的值(客户自己的类别列表变成 SELECT 选项)是有据的;只有你自己起的名字才是推断。伙伴照此报价,发明的字段或需求会抬高报价或制造错误预期。
- 记录设计后果,而不是前因故事。 说出需求,以及随之而来的客户路径;不要去论战它为什么为真。当需求追溯到供应商内部或第三方细节(公司架构、法定住所、所有权、内部商务安排、谁找谁确认什么)时,只保留后果:这是商务事项,不是构建输入,无论通话里占了多长气口。客户在等待的开放项,记为它锁住的决策,而不是叙事。
- 禁止"left out"或"not named"占位。 一条说*"sessions 和 programmes 被刻意排除"的 bullet,或一节说"没点报表"*,都是填充物,砍掉。要标注缺失,就写成锁住某个具体决策的 Open question。否则,沉默。
- 永不重复。 每个事实说一次,写在它的主章节;别处用链接指过去。Open questions 和 References 是刻意的汇总:给指针和该条锁住的决策,而不是重新解释。重复是臃肿的主要来源,两份拷贝的声明会失步。
- 交叉引用必须是功能性锚链接。 写
[§N](#n-section-slug),绝不写裸§N。slug 遵循 GitHub 自动锚定规则:小写、空格转连字符、标点丢弃、&去掉留下双连字符。只扫一眼裸§7的伙伴看到的是一个没有跳转入口的数字。 - 数据库纪律:复用并扩展标准对象。 Company、Person、Opportunity 加上内置 Notes、Tasks、Timeline 覆盖大多数 CRM 需求;每新增一个对象都放大构建与维护成本。一个人物角色先做"带角色标记的 Person",再考虑新对象:只有当它需要自己的 pipeline 或报表时才建对象。添加时要点名这堵墙。
- brief 稀薄时,少建模(under-reach)。 模糊的局面(没有 discovery 通话、笔记稀疏)是理由去建模最少、最确定的对象,其余留 ❓ open,而不是用一套华丽的推断域来补偿。过度细致的推断读起来像是客户从没要过的范围和成本,会把犹豫的买家吓跑。从标准对象加上一两个领域显然必需的自定义对象起步,并在开头明说:模型是最小起始草图,待验证。
- 呈现构建路径,不要指定。 一个自动化可以是无代码 Workflow或者应用里的 logic function:两个都写。指定其中一个,会惩罚选择另一个的伙伴。文档识别需求,不是构建方式。
- 每个问题都带一条路径。 如果你标注了一个约束(dashboard 不能对外共享),至少配一个解法(CSV 导出、front component、基于 API 的公开站点)或一个能解决它的问题。没有路径的标志,对正在定价的人是没用的。
- 标注某条路径满足不了什么。 文档的价值在于按需求暴露墙和限制,让伙伴绕着它们定价,而不是挑出"唯一正确解"。
- 伙伴向声音。 说 "Twenty",永不第一人称("we"、"our"、"ours")。不写本地文件路径:只引用可分享的
docs.twenty.comURL。含 "we" 或 "our" 的客户原话引用没问题:那是引用。 - 禁止刻画性评价和旁白。 文档可转发给客户,所以把源聊天里的随口感评挡在外面:对买家的刻画(预算、性格、成熟度)、点名对比竞争厂商、内部合作备注(截止日期、谁承诺了什么)。如果价格敏感度或竞品替换确实塑造了构建,就中性地作为需求陈述,永不作为引用或评判。
- 断言能力之前先验证。 任何改变报价的"Twenty 能/不能、有/没有 X",必须实机验证。"文档没写"不等于"做不到"。
排版细则(Formatting)
- 一个段落一行。句中硬换行永远不写:它们会渲染成断行。
- 永不使用 em dash(长破折号)。重构句子,或用冒号、逗号、括号、句号。
- 永不使用裸
~表示"大约":GitHub markdown 会把~…~配对成删除线。写 "around" 或 "about"。 - 未验证的能力声明标 ❓ open,绝不写成事实。
验证机制:声明必须"活"着才能被说出口
任何 "Twenty can, can't, has or lacks X" 形式、且会改变伙伴报价的声明,在下结论前必须实机验证。模型训练对快速变化的产品是过时的;最坏的失败是一种自信的、听起来权威的、但错误的声明。
来源层级(Source hierarchy):
- 活文档(
docs.twenty.com):第一真相源。对最高风险的声明,读页面的主体文本,而不是相信摘要。 - 成熟的 Twenty SDK 构建模式(hands-on):客户文档没写的构建级事实——没有公式字段;自定义对象自动获得附件、笔记、任务和时间线;双文件关系。
- Twenty operator(Twenty 团队成员):最适合回答"已发布、内部还是未文档化"。
- 模型训练:永不作为高风险声明的唯一依据。
正确的文档层(陷阱所在)。能力存在于两层,要查对的那一层:
- 产品能力(CRM 为客户做什么):用户指南和定价页。覆盖角色、行级权限、dashboard、套餐、托管、数据驻留。
- 应用能力(应用能定义什么):开发者与 extend 文档。覆盖字段类型、字段、logic functions、views、页面布局。
只查应用层,正是"行级权限不支持"(错误结论)的由来:行级权限是 Organization 套餐的产品功能。反过来也成立:成熟的 SDK 构建模式足以断言构建层事实,即使客户文档沉默,所以不要把有据的构建事实降级为 ❓ open。
两条声明在模型训练中已经过时,必须每次都查:"Twenty 不是 BI 工具"(它有 Dashboards)和"Twenty 做不到行级"(Organization 套餐)。
每次运行都必须实机验证的清单:
- 字段类型与约束(没有公式或计算字段)。
- 标准对象扩展与重命名(加字段;能否重命名内置 SELECT 选项?)。
- 角色与权限:对象级、字段级、行级,以及哪个套餐档门控。
- Dashboard 与报表:图表和 widget 类型、beta 状态、导出与对外共享限制。
- 自动化面:Workflows 与 logic functions 各自能做什么。
- 集成机制:webhooks、HTTP 触发器、计划函数、connections。
- 托管与部署:云套餐与区域、EU 数据驻留、自托管可得性与要求。
再加上草稿中任何带 ⚠️ heavy 或 ❓ open 的其他能力声明。
降级链(Fallback chain):
- 文档证实声明:作为事实陈述,并把来源记入 References。
- 文档沉默或含糊:如有 operator,问 operator。
- operator 不可用或不确定:渲染为 ❓ open。绝不断言。如果你抓取了页面而它只是沉默,记 "docs silent (URL)",而不是让声明没有来源。
文档地图(Doc map)。准则给出的验证地图以 docs.twenty.com 为基址,抓取 <path>.md 的干净 markdown 孪生页。在本仓库中,这些文档路径与 packages/twenty-docs/ 下的本地源文件一一对应,可直接查阅:
| 层 | 文档路径 | 本地对应文件 |
|---|---|---|
| 产品 | user-guide/dashboards/overview |
dashboards/overview.mdx |
| 产品 | user-guide/dashboards/capabilities/widgets |
widgets.mdx |
| 产品 | user-guide/permissions-access/how-tos/permissions-faq |
permissions-faq.mdx |
| 产品 | user-guide/data-model/overview |
data-model/overview.mdx |
| 产品 | user-guide/data-model/capabilities/fields |
fields.mdx |
| 产品 | user-guide/data-migration/how-tos/export-your-data |
export-your-data.mdx |
| 开发 | developers/extend/apps/data/objects |
objects.mdx |
| 开发 | developers/extend/apps/data/extending-objects |
extending-objects.mdx |
| 开发 | developers/extend/apps/data/relations |
relations.mdx |
| 开发 | developers/extend/apps/logic/logic-functions |
logic-functions.mdx |
| 开发 | developers/extend/apps/logic/connections |
connections.mdx |
| 开发 | developers/extend/apps/layout/views |
views.mdx |
| 开发 | developers/extend/apps/layout/page-layouts |
page-layouts.mdx |
| 开发 | developers/extend/apps/config/roles |
roles.mdx |
| 自托管 | developers/self-host/self-host |
self-host.mdx |
| 定价 | 定价页(营销页,无 .md 孪生,按 HTML 抓取) |
无本地文件 |
如果某个 .md 404,去掉后缀或从文档索引重新推导:地图会过时。
自检:保存前逐项过一遍
准则的 Self-check 是上述规则的可扫描形式,不是新的规则集。
硬失败(保存前必须修):
- [ ] 任何位置的 em dash。
- [ ] 用裸
~表示"大约"。 - [ ] 客户引用之外出现第一人称("we"、"our")。
- [ ] 本地文件路径。
- [ ] 头部不是四字段表格。
- [ ] 标志不是
**❓ open**、**⚠️ heavy**、**🛑 blocker**(以及--full下的🔮 inf.)。任何游离的 🟥 🚩 🚨 ✅,或没有文本标签的裸 emoji,都是错的。 - [ ] 默认模式出现
🔮 inf.。要删就删掉整个推断,而不是只删标签。 - [ ] 默认模式的数据模型表格出现
Source列。 - [ ] 一个章节只是说"X 没被点名",或列出被刻意排除的内容。
- [ ] 裸
§N而非[§N](#n-section-slug)。 - [ ] 重编号空洞:某节被删了,但周围编号没跟着改。
- [ ] 能力声明没有 References 来源却被写成事实。
警告(不能自证就修):
- [ ] 一个以段落为主的章节,而列表或表格本可以胜任。Open questions 是例外。
- [ ] 不改变报价的构建、运行时或 SDK 机制。
- [ ] 一个点在多个章节重复,而不是
§N交叉引用。 - [ ] 遗留的术语表或领域语言章节。
- [ ] 带
Type列的 Views 表格,或渲染成项目符号列表的 Views。 - [ ] 为一个客户从未点名的系统写了 Integrations 章节。
- [ ] 默认模式文档超过 2 页。
准则在 twenty-partners 应用中的真实落地
从源码结构看,这份准则不是孤立的文档,它嵌在 twenty-partners 应用(把 CRM 变成 Twenty 伙伴计划的操作系统,见 README)的完整 lead 路径中:
- 技能流水线:
twenty-lead-brief → twenty-partner-shortlist → twenty-partner-intro。SKILL.md把准则作为 Step 3 的"唯一内容源",自己只保留机械流程:收集全部源材料 → 有据提取 → 按准则结构起草 → 按文档地图实机验证承重声明 → 对账源材料间的分歧(双向往返标注,从不静默解决) → 用 operator 解决 ❓(自主运行时跳过提问,未知项全部留 ❓) → 跑准则的 self-check 后保存。 - in-product playbook:how-to-process 的 playbook 常量把
twenty-lead-brief登记为 lead 路径第一步技能,其四个产出物与SKILL.md完全一致:对话中的资格摘要、粘进 Google Doc 的伙伴 brief、partner-match-criteria.md、以及把 Design Doc URL 写入 Opportunity 的 CRM 记录。 - CRM 侧落点:准则产出的 brief 最终落到 Opportunity 对象上,对应字段包括 opportunity-design-doc-url.field.ts 和 opportunity-design-doc-status.field.ts;凭证与全部 GraphQL 查询统一收敛在 partner-api.md,
SKILL.md明确"读它而不是复述"——这正是准则"每条规则只出现一次"原则在技能目录里的延伸。 - 配置与运行环境:应用本身通过 application-config.ts 声明工作区级变量(如
DISCORD_WEBHOOK_URL、PARTNER_APP_FRONTEND_URL),brief 发布到共享 Drive 后,Opportunity 的designDocUrl字段承载该链接,供下游twenty-partner-intro技能在 Gmail 草稿中发送。
复用要点
这份准则的价值在于它是"工具无关的产出规范":换一个 agent、换一套技能加载方式,只要照抄这份文件,产出的伙伴设计文档就保持同一种纪律。核心可迁移的机制有四条:
- 单一事实源:结构、规则、验证都写一遍,消费方只链接不复述,避免两份拷贝失步;
- 零推断默认值 + 显式推断模式:用
--full这样的开关把"推断是否允许"变成可声明的参数,而不是靠模型自觉; - 验证降级链:文档证实 → 问 operator → 渲染为 ❓ open,任何一环失败都不许"自信的断言"冒出来;
- 可扫描的自检:把规则编译成保存前逐项打勾的清单,硬失败与警告分级处理。
对想要为自己的产品写"agent 设计文档规范"的团队,可以直接以 design-doc-doctrine.md 为模板:保留"四字段头部 + 标志体系 + 条件章节 + 零推断默认值 + 验证层级 + 自检"的骨架,替换其中与 Twenty 绑定的验证地图和标准对象假设即可。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00