2026年8月7日 2 分钟阅读

让 Agent 更新 CRM,不等于给它数据库:用 Martin 把销售动作变成可审计的状态机

tinyash 0 条评论

让编码 Agent 整理线索、补会后纪要、推进商机,听上去只是把自然语言转换成几条 CRM 写操作。但真正难的不是“能不能写入”,而是如何让每一次写入都符合销售流程,又能在 Agent 重试、并发执行或误解上下文时留下可追溯证据。若直接给 Agent 数据库连接,它可以跳过阶段、覆盖较新的记录,甚至把没有后续动作的商机遗留在管道中;这些错误通常不会在 API 调用成功时暴露。

Martin 是一个面向人和 AI Agent 的本地优先 CRM CLI。它不是托管式 CRM,也不是通用工作流自动化器,而是把组织、联系人、商机、活动与任务收束到一套固定领域规则中。项目使用 Go 编写,采用 AGPL-3.0-or-later 许可证;底层事件历史由独立的 Jaybase 提供。它目前仍是 pre-1.0,适合先在小团队或受控环境评估,而不是把 beta 软件直接当成企业 CRM 的替换品。

把“写入权限”改成“受约束的领域命令”

Martin 的关键设计是:Agent 不操作表,也不拼接任意 SQL,而是调用领域命令。它固定了一条销售阶段链:new → qualified → proposal → won|lost。每个未关闭商机必须恰好有一个待办的下一步;创建商机必须提供首个 next action,推进阶段会完成旧动作并创建新动作,赢单或输单会关闭待办动作。这样,“本周联系客户”不是散落在描述字段里的文本,而是流程状态的一部分。

这个约束特别适合语言模型。模型擅长从会议纪要中提炼“下一步发方案”,却未必能稳定维护数据模型的隐含不变量。Martin 把不变量放在命令处理层:不符合规则的请求被拒绝,而不是接受后等待人工在仪表盘里发现异常。成功结果默认从标准输出给出 JSON,错误则从标准错误输出 JSON,调用方可以把进程退出、结构化错误和审计记录纳入同一条 Agent 工具调用链。

其数据规则也减少了“猜测匹配”的空间:变更使用返回的组织、联系人或商机 ID,而不是由 Agent 根据名称构造 ID;活动不会被原地改写;记录采用归档、取消、合并或 supersede,而非删除。批量导入以 (source, source_key) 做幂等键,因此同一批来源数据重复投递时不会天然变成重复线索。

先建立本地工作区,再让 Agent 按模板执行

Martin 要求 Go 1.26.5 或更高版本构建。最小本地初始化如下:

git clone https://github.com/kyle-visner/martin.git
cd martin
go install ./cmd/martin
martin --store .martin --actor owner init --currency USD

--store 指向本地工作区,--actor 是领域身份。这里有一个容易忽略的安全边界:Martin 文档明确说明,--actor 本身不是认证证明。也就是说,把 --actor sales-bot 写进提示词或脚本,并不能证明调用者真是 sales-bot。生产自动化仍要由可信包装层将已认证的调用者绑定到允许的 actor;不要把这个 CLI 参数误当成登录机制。

初始化后,可让 Agent 只在固定的命令骨架内填充经过确认的值。下面的例子先创建客户与联系人,再创建带首个动作的商机:

martin --store .martin --actor owner organization create   --name "Acme Studio" --domain acme.example --tags prospect,design

martin --store .martin --actor owner person create   --display-name "Ada Lovelace" --organization-id org:...   --email ada@acme.example

martin --store .martin --actor owner deal create   --name "Website redesign" --organization-id org:...   --person-id person:... --value-cents 1250000   --expected-close 2026-08-31 --next-action "Run discovery call"   --next-due 2026-07-25

其中 org:...person:... 是前序命令返回的 opaque ID,不应由模型自行编造。金额使用工作区不可变 ISO 货币的最小单位,例如 USD 的 cents;业务日期使用 YYYY-MM-DD。这些看似细小的限制,实际是在阻断 Agent 把模糊自然语言直接投射为不一致数据的路径。

deal touch 保持交互与下一步原子一致

“刚开完会,范围确认了,下周发方案”是 Agent 常见的写入场景。若调用方先记录会议、再单独关闭任务、最后创建下一项任务,任何一步失败或重试都可能留下半完成状态。Martin 提供 deal touch,将一次交互记录、旧 next action 的完成与新 next action 的创建合并为一条领域操作:

martin --store .martin --actor owner deal touch   --id deal:... --kind meeting   --summary "Discovery completed; scope confirmed"   --next-action "Send proposal" --next-due 2026-07-28

随后可以用 deal advance 推进阶段,并同时指定新的下一步。对于需要回顾或监控的自动化,可使用 today 查看当日工作、使用 pipeline 查看商机管道;在大规模 Agent 操作前,先执行 snapshot create --name NAME 创建快照。不要直接编辑 .martin/ 下的文件或 Jaybase 对象、refs、密钥:文档把这些明确列为 Agent 不应绕过的存储层。

给 Agent 设计调用闭环:读取、提出、确认、执行、复核

不要把 Martin 当成“聊天文本到 CRM”的单步翻译器。更稳妥的实现是把一次更新拆为五步。第一步,Agent 用 search --query TEXTstatepipeline 获取当前事实;第二步,把拟写入的商机、活动摘要、日期和下一步动作以结构化草案呈现给用户或审批器;第三步,确认目标 ID 和阶段是否合法;第四步,执行单一领域命令;第五步,读取 JSON 结果并回查 todaypipeline。这样即使模型把“下周二”解析错了,错误也停留在执行前,而不是成为已经传播到报表和提醒系统中的事实。

对自动化尤其要区分“可重试”与“可随意重复”。网络超时后,调用方不能因为没立即拿到响应就换一个名称重新创建商机;应保存来源系统的稳定键,走 Martin 的导入幂等路径,或者先查询现有记录。远端模式还会用 expected_rootIdempotency-Key 协调写入:发生冲突表示有人已经在更晚的状态上操作,正确处理是重新读取、比较变化并重新决策,而不是盲目覆盖。

日志策略也应和数据策略一起设计。成功时只把 stdout 的 JSON 当作程序结果,错误时解析 stderr 的 JSON;将调用的 actor、记录 ID、命令类别、来源键和结果码送入独立审计系统,但不要把远端 token、完整客户内容或缓存 checkpoint 打进调试日志。Martin 的 audit 输出是元数据导向,这为“证明发生了什么”保留了路径,同时避免把每一次回放都扩展为不受控的数据泄露。

与 Magpie 共用历史时,先划清事实归属

Martin 可以和同一 Jaybase 实例上的 Magpie 协作,但两者并不是互相写对方数据的双向同步器。Martin 只写自己的 martin.* 节点类型,并读取被选定的 Magpie RBAC、客户和发票事实来形成组合客户视图;Magpie 则跳过 Martin 命名空间。客户关联是显式的一对一链接,不做名称模糊匹配,也不静默同步名称。

这种边界对 Agent 很重要。CRM 中“Acme Studio”与财务系统中的相似客户名称,不能仅凭模型相似度被认定为同一实体。正确流程是先从两个系统读到实际 ID,再显式建立关联;如果没有足够证据,返回需要人工确认,而不是猜测。领域边界并不会消除业务判断,却能把必须由人承担的不确定性从底层存储操作中暴露出来。

远端模式的边界比“能连上”更重要

Martin 也可以连接单独部署的 Jaybase 服务。远端地址和 token 使用环境变量提供,token 不应写进命令行参数、URL、请求载荷、日志或幂等键:

export JAYBASE_URL=https://jaybase.example.com
export JAYBASE_TOKEN="${JAYBASE_TOKEN}"  # 从受控密钥管理系统注入,不要写入命令、URL 或日志
martin --actor AGENT_USER_ID pipeline

远端写入使用乐观并发控制与幂等写入约定;当根状态已经变化时,应该返回冲突而非覆盖较新的数据。可选缓存目录保存的是加密、token 绑定的投影 checkpoint,用于增量回放性能,不是事实来源,也不是备份。部署时应把它视作私有临时状态,不能跨不可信用户共享。

还有一个实施细节值得提前约定:把模型输出限制为“建议的命令参数”,由确定性适配器校验必填字段、日期格式、金额单位和 ID 的来源,再决定是否执行。适配器应拒绝未知字段,并在读取结果和写入目标不一致时中止;它不应把模型的解释文字直接拼进 shell。对高风险动作,可把 deal windeal lose、合并和批量导入放进单独的人工批准队列,而将只读检索和草稿生成保留给自动路径。

Martin 的取舍很清晰:它故意不做营销自动化、批量邮件、自由阶段图、预测性评分或任意工作流构造器。对需要这些能力的团队,这会是限制;但对“让 Agent 在受控销售流程里完成少量高价值写入”的场景,固定模型反而是优势。开始前可用 go test -race ./...go vet ./...govulncheck ./... 验证构建;上线后再把命令白名单、最小 actor 权限、人工审批与审计导出组合起来,才构成完整的 Agent CRM 安全边界。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。