搞懂 Actions 系统是怎么工作的——从 AI 生成按钮、到用户点击、到后端执行。

第8课:一键操作 —— Actions 系统详解

本课目标

搞懂 Actions 系统是怎么工作的——从 AI 生成按钮、到用户点击、到后端执行。


Action 是什么?

Action = 一个可以在聊天界面里点击执行的按钮

关键特点: - 不是通用的——每个 Action 都是针对特定场景的(如"归档 Acme Corp 的旧邮件",不是"归档邮件") - AI 动态生成——根据对话上下文,AI 判断需要什么 Action - 用户确认——按钮出现后,用户点了才执行,不会自动执行 - 有完整上下文——执行时能访问邮箱API、AI、数据库、通知系统


Action 的生命周期

graph TD A["1. 用户在聊天里说: 帮我把过期订阅邮件清理了"] A --> B["2. AI 分析上下文,找到合适的 Action 模板<br>(archive-old-newsletters)"] B --> C["3. AI 在回复中生成 ActionInstance<br>templateId: archive-old-newsletters<br>label: 归档 47 封过期订阅邮件"] C --> D["4. 前端渲染为可点击的按钮"] D -->|"用户点击"| E["5. 后端加载 action 模板的 handler 函数"] E --> F["6. handler 执行(搜索邮件 -> 批量归档)"] F --> G["7. 执行结果返回前端 + 记录到日志"]

Action 模板长什么样?

位置:agent/custom_scripts/actions/

每个 Action 模板包含两部分:config(配置)和 handler(执行逻辑)。

示例:归档过期订阅邮件

code
// agent/custom_scripts/actions/archive-old-newsletters.ts

// 第一部分:配置(告诉 AI 这个 Action 是干什么的)
export const config = {
    templateId: "archive-old-newsletters",
    name: "归档过期订阅邮件",
    description: "归档指定天数前的订阅类邮件",
    parameters: {
        type: "object",
        properties: {
            olderThanDays: {
                type: "number",
                description: "归档多少天前的邮件",
                default: 30
            }
        }
    }
};

// 第二部分:执行逻辑(用户点击按钮后运行)
export async function handler(params, context) {
    const { olderThanDays } = params;
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);

    // 1. 搜索过期订阅邮件
    const emails = await context.emailApi.search({
        query: `category:promotions before:${formatDate(cutoffDate)}`
    });

    // 2. 批量归档
    let archived = 0;
    for (const email of emails) {
        await context.emailApi.archive(email.id);
        archived++;
    }

    // 3. 通知用户
    context.notify(`已归档 ${archived} 封过期订阅邮件`);

    // 4. 记录日志
    context.log({ action: "archive-newsletters", count: archived });

    return { success: true, count: archived };
}

示例:转发 Bug 报告

code
// agent/custom_scripts/actions/forward-bugs-to-engineering.ts

export const config = {
    templateId: "forward-bugs-to-engineering",
    name: "转发Bug报告给工程团队",
    description: "分析邮件中的Bug信息,附上AI分析摘要后转发",
    parameters: {
        type: "object",
        properties: {
            emailId: { type: "string", description: "要转发的邮件ID" },
            engineeringEmail: { type: "string", description: "工程团队邮箱" }
        }
    }
};

export async function handler(params, context) {
    const { emailId, engineeringEmail } = params;

    // 1. 读取原始邮件
    const email = await context.emailApi.read(emailId);

    // 2. 调用 AI 分析 Bug 内容(递归 AI!)
    const analysis = await context.callAgent({
        prompt: `分析这封 Bug 报告邮件,提取关键信息:
            主题: ${email.subject}
            内容: ${email.body_text}`,
        schema: {
            type: "object",
            properties: {
                severity: { type: "string", enum: ["critical", "high", "medium", "low"] },
                summary: { type: "string" },
                steps_to_reproduce: { type: "string" },
                affected_component: { type: "string" }
            }
        }
    });

    // 3. 构造转发内容
    const forwardBody = `
        === AI 分析摘要 ===
        严重程度: ${analysis.severity}
        摘要: ${analysis.summary}
        影响组件: ${analysis.affected_component}
        复现步骤: ${analysis.steps_to_reproduce}

        === 原始邮件 ===
        ${email.body_text}
    `;

    // 4. 发送转发
    await context.emailApi.send({
        to: engineeringEmail,
        subject: `[Bug-${analysis.severity}] ${email.subject}`,
        body: forwardBody
    });

    context.notify(`Bug 报告已转发给 ${engineeringEmail}`);
    return { success: true };
}

看到了吗?handler 里调用了 context.callAgent() ——让 AI 帮忙分析 Bug 内容,然后代码根据 AI 的结果构造转发邮件。这就是代码+AI 配合的典范。


ActionContext 里有什么?

handler 函数的第二个参数 context 是一个"百宝箱":

属性/方法 功能
context.emailApi.search() 搜索邮件
context.emailApi.read() 读取邮件
context.emailApi.archive() 归档邮件
context.emailApi.star() 标星邮件
context.emailApi.label() 贴标签
context.emailApi.send() 发送邮件
context.callAgent() 调用 AI 做判断
context.uiState.get() 读取看板数据
context.uiState.set() 更新看板数据
context.notify() 给用户发通知
context.addMessage() 在聊天里追加消息
context.log() 记录日志

日志系统

所有 Action 的执行都会被记录到 .logs/actions/ 目录下:

code
.logs/actions/2026-02-28.jsonl

每行一个 JSON 对象:

code
{"timestamp":"2026-02-28T14:30:22Z","action":"archive-old-newsletters","params":{"olderThanDays":30},"result":{"success":true,"count":47},"duration_ms":3200}

方便你事后审查"AI 代你做了什么"。


本课小结

  1. Action = 聊天里的可点击按钮,AI 动态生成,用户确认执行
  2. 每个 Action 模板有 config(配置)+ handler(执行逻辑)
  3. handler 能访问完整的 ActionContext:邮箱API、AI、看板、通知
  4. callAgent() 让 Action 在执行过程中调用 AI 做分析
  5. 所有执行都有 JSONL 审计日志

沿着当前专题继续,或返回课程目录重新整理阅读顺序。

返回课程目录