Skip to content

内容概述

基础文档展示了最简单的场景:用户说一句话,AI 自动创建需求。但 ToB 业务里大量操作远比单表增删改复杂——比如修改需求状态,必须同时更新主表、写入历史记录、通知相关人,缺一不可。

本案例以「需求状态变更」为例,展示:当业务逻辑涉及多表写入、状态流转校验、事务一致性时,技术团队如何开发函数接口,AI 加载 Skill 后一句话完成整个流程。


业务场景:为什么需要函数接口

在基础文档的例子里,AI 直接操作数据库就够了。但现实业务中,很多操作有更严格的要求:

强校验:状态必须按顺序流转(新建 → 指派 → 进行中 → 测试 → 完成 → 关闭),不能从新建直接跳到完成。

数据一致性:改状态时,必须同步记录谁改的、什么时候改的、从哪改到哪——主表和历史表必须同时更新,不能一张成功一张失败。

事务性:一个操作涉及多张表,任何一张表写失败都要回滚。

遇到上述场景,需要技术团队开发函数接口,封装校验逻辑和事务保证,注册到平台后供 AI 调用。业务人员不需要知道函数里写了什么 SQL、做了几次写入,只需要调用接口,数据一致性由技术保证。


技术实现:开发函数

注册路径

独立端点脚本(ENDPOINT),注册后通过以下路径访问:

Plain
POST /api/endpoint/{appCode}/{scriptName}

本案例使用:

  • 脚本名称: update_requirement_status
  • 应用: app-173e8652(启智云图)
  • 完整路径: POST /api/endpoint/app-173e8652/update_requirement_status

前置依赖

技术团队开发前需确认:

  • 应用 app-173e8652 已创建并拥有 yt_requirements(需求主表)和 yt_requirement_history(状态历史表)两个数据模型
  • 操作人有写入这两个模型的权限

函数代码

技术团队实现需求状态变更,同时完成主表更新和历史记录写入:

JavaScript
/**
 * 需求状态变更(双写主表 + 历史表)
 * 脚本名称: update_requirement_status
 * 所属应用: app-173e8652
 */
export default async function updateRequirementStatus(params, context) {
  const { id, new_status, operator_id, reason } = params;

  // -------- 第一部分:查询校验 --------
  
  // 1. 查询需求当前信息
  const requirement = await context.client.models.yt_requirements.findOne({
    id: id
  });

  if (!requirement) {
    throw new Error("需求不存在");
  }

  const oldStatus = requirement.status;

  // 2. 校验状态流转是否合法
  const validTransitions = {
    "new": ["assigned", "closed"],
    "assigned": ["in_progress", "closed"],
    "in_progress": ["testing", "closed"],
    "testing": ["completed", "in_progress"],
    "completed": ["closed"],
    "closed": []
  };

  if (!validTransitions[oldStatus]?.includes(new_status)) {
    throw new Error(`状态不允许从 ${oldStatus} 直接变更为 ${new_status}`);
  }

  // -------- 第二部分:双写(事务保证) --------
  // 系统检测到写操作,自动开启 Best Effort 1PC 事务
  // 无需手动 commit/rollback,脚本正常返回即提交,抛异常即回滚

  // 3. 更新主表:需求状态
  await context.client.models.yt_requirements.update({
    id: id,
    status: new_status
  });

  // 4. 写入历史表:变更记录
  await context.client.models.yt_requirement_history.create({
    requirement_id: id,
    user_id: operator_id,
    field_name: "status",
    old_value: oldStatus,
    new_value: new_status,
    created_at: new Date().toISOString()
  });

  // -------- 第三部分:返回结果 --------
  return {
    success: true,
    requirement_id: id,
    old_status: oldStatus,
    new_status: new_status,
    operator_id: operator_id,
    message: "状态变更成功,历史记录已同步"
  };
}

事务机制说明

Lovrabet 平台采用 Best Effort 1PC 事务模型,技术团队无需手动管理事务:

时机行为
读操作(findOne / getList)不开启事务,不占连接
第一个写操作(update / create)自动开启事务
后续写操作自动加入同一事务
脚本正常返回自动提交所有事务
脚本抛出异常自动回滚所有事务

技术团队只需要按业务顺序编写逻辑,事务由平台自动管理。


Skill 封装:让业务人员一句话完成操作

函数接口开发完成后,业务人员如何使用?

把操作流程封装成 Skill,AI 加载后自动完成:确认需求存在 → 调用函数 → 通知相关人。

Skill 范本

Markdown
---
name: update_requirement_status
version: 0.1.0
description: "需求状态变更。触发词:标记为已完成、把需求改为、变更需求状态。"
---

# 需求状态变更

## 第一步:确认需求存在

根据用户提供的需求 ID,查询该需求是否存在、当前状态是什么。如果不存在,告知用户并终止。

## 第二步:变更状态并记录历史

调用 `update_requirement_status` 接口,同时完成:
- 修改需求状态为用户指定的状态
- 在历史记录中新增一条状态变更记录(记录原状态、新状态、操作人、操作时间)

如果接口返回失败,告知用户失败原因,终止流程。

## 第三步:通知需求提出人

查询该需求的创建人,向其发送邮件或飞书消息,告知:
- 哪个需求的状态发生了变更
- 变更后的状态是什么

## 注意事项

- 状态值必须在合法范围内(new / assigned / in_progress / testing / completed / closed)
- 如果用户没有指定变更原因,询问后再继续
- 第三步的通知仅需告知结果,无需额外操作
- 禁止直接调用数据集原始接口

使用示例

用户输入

Plain
把需求 App主题根据用户手机壳颜色自动适配 标记为已完成

AI 自动完成

加载 Skill → 确认需求存在 → 调用函数接口(主表更新 + 历史表写入同时完成)→ 通知需求提出人

返回结果示例

Plain
✅ 状态更新完成
━━━━━━━━━━━━━━━━━━
需求 ID:305
标题:App主题根据用户手机壳颜色自动适配
状态:进行中 → 已完成
操作人:梓骞
变更历史:已记录
━━━━━━━━━━━━━━━━━━
通知:已发送邮件给需求提出人

常见问题

Q:开发函数接口需要自己搭基础设施吗?

A:不需要,在已有的 Lovrabet 应用下开发脚本并注册即可,事务、连接管理、权限控制都由平台提供。可以使用 Rabetbase-CLI 开发者套件

Q:状态流转规则写在函数里会不会改起来麻烦?

A:比直接暴露数据库给 AI 安全得多。规则变更只需技术团队修改函数代码,Skill 和 AI Prompt 无需改动。

Q:函数接口报错怎么办?

A:检查返回的错误信息,常见原因包括:需求 ID 不存在、状态流转不合法、权限不足等。错误会直接透传给 AI,AI 会告知用户。

Q:业务人员需要了解状态值有哪些吗?

A:不需要,Skill 里已经定义好了合法状态值。业务人员只需要说「标记为已完成」,AI 自动映射到对应的状态码。

Q:后续要新增操作维度怎么办?比如加上优先级变更记录?

A:在函数里增加历史表字段即可,Skill 描述的是业务步骤,不涉及具体字段名。

基于飞书知识库同步生成,内容以飞书源文档为准