欢迎访问晨星博客!

  • 当前位置: 首页 WordPress 正文

    在 WordPress 中集成 AI Agent 工作流:使用自托管平台 Buzz 实现自动化内容编辑

    生成摘要
    AI 生成,仅供参考

    一个很常见的场景:站点上装了个 AI 写作插件,定时任务每天生成三篇草稿,某天有篇文章把过期的价格写进了正文并自动发布。你想回溯——是哪次运行、用了什么提示词、模型返回了什么、谁点了发布——结果只能翻到一行 cron 日志和一条 post_modified 时间戳。这不是模型能力问题,是流程没有留下可核对的痕迹。

    Buzz 有意思的地方正好在这里。它是 Block 开源的自托管协作平台(仓库 block/buzz,Apache-2.0),在它的设想里,人和 AI agent 待在同一批频道里,而每个参与者持有属于自己的密钥对——不是借用某个人的登录态。对做内容自动化的站长来说,这句话翻译过来就是:agent 的每一次动作有独立的行为主体,而不是「管理员账号又干了点什么」。

    自托管 AI Agent 与 WordPress 内容发布流水线的示意图

    先分清 Buzz 负责什么、你负责什么

    官方在 VISION 文档里把定位说得很直白:relay 就是工作区,Buzz 是管道——事件存储、搜索索引、订阅、投递——不是大脑。智能由人和 agent 带进来。

    这句定位决定了整套集成的边界。指望 Buzz 内置一个「WordPress 发布模块」是想错了方向;它提供的是一个可自托管、有身份体系、消息可检索的共享空间。内容怎么生成、按什么标准审、什么时候允许发布,得由你在这个空间之上定义。仓库里带有容器编排配置,自建 relay 是设计中的常规用法,这也是我愿意把内容流水线接到它上面的主要原因:数据和身份都在自己的域里。

    所以整条链路实际分成三段职责。Buzz 负责承载对话、事件与 agent 身份;你的 WordPress 站点负责暴露一组受控的操作能力;中间那层流程定义负责规定这些能力按什么顺序、在什么条件下被调用。三段分开,出问题时才知道该看哪儿。

    把 WordPress 暴露成一组受限的工具,而不是一把万能钥匙

    已经有实现走通过这条路。VayuPress 做的 Buzz 连接器(随其 v3.15.86 提供)就是让 Buzz 频道里的 agent 通过站点已有的 MCP 接口来调用工具,比如发布文章、更新页面、读取分析数据。作者特别强调它是 inbound only:agent 进来用你的工具,站点不为此新增依赖、新增密钥或新增出站路径。

    这个取舍值得抄。入站单向的好处是攻击面和审计面都收窄了——所有动作都从你自己的接口进来,权限校验、参数校验、记录都由你控制。如果你不打算直接用现成插件,最小可用的做法是自己注册一组窄接口,每个接口只做一件事:

    add_action( 'rest_api_init', function () {
        register_rest_route( 'agent-flow/v1', '/draft', array(
            'methods'             => 'POST',
            'callback'            => 'agent_flow_create_draft',
            'permission_callback' => function ( WP_REST_Request $request ) {
                // 只允许被授权的机器身份,且只给「写草稿」这一项能力
                return current_user_can( 'agent_flow_write_draft' );
            },
            'args' => array(
                'run_id' => array( 'required' => true, 'type' => 'string' ),
                'title'  => array( 'required' => true, 'type' => 'string' ),
                'body'   => array( 'required' => true, 'type' => 'string' ),
            ),
        ) );
    } );
    
    function agent_flow_create_draft( WP_REST_Request $request ) {
        $post_id = wp_insert_post( array(
            'post_title'   => sanitize_text_field( $request['title'] ),
            'post_content' => wp_kses_post( $request['body'] ),
            'post_status'  => 'draft', // 生成阶段永远只落草稿
        ), true );
    
        if ( is_wp_error( $post_id ) ) {
            return $post_id;
        }
    
        update_post_meta( $post_id, '_agent_run_id', sanitize_key( $request['run_id'] ) );
        update_post_meta( $post_id, '_agent_stage', 'generated' );
    
        return array( 'post_id' => $post_id, 'status' => 'draft' );
    }

    关键在 post_status 和那个 run_id。生成接口不给发布能力,发布是另一个接口、另一项 capability;run_id 则是后面所有审计动作的串联键,缺了它,多个 agent 并发写稿时你分不清哪篇属于哪次运行。

    机器身份不要和人共用账号

    按 Buzz 的身份思路做延伸:给 agent 单独建 WordPress 用户,配一个只含必要 capability 的自定义角色,认证凭据独立签发和轮换。这样做不只是安全洁癖——审计的前提是行为可归属。共用管理员账号的自动化,事后所有记录都指向同一个人,等于没有记录。

    为 AI Agent 分配最小权限而非共用管理员账号的对比示意

    用 YAML 把生成、审稿、发布写成可复核的流程

    到这里能力面已经就绪,但「什么时候调哪个」还散落在代码和定时任务里。我的做法是把流程本身抽出来写成 YAML 文件,跟主题或插件代码一起进版本库。声明式描述带来两个直接收益:改流程会产生 diff,出事故能 checkout 到当时的版本重放。

    需要说明的是,下面这份结构是我为自己的编排层定的约定,不是 Buzz 的内置格式——你完全可以按团队习惯改字段名,重点是把阶段、条件和人工关卡显式写出来:

    name: post-editing-pipeline
    version: 3
    identity: agent-editor            # 对应站点里那个专用机器身份
    stages:
      - id: draft
        tool: agent-flow/v1/draft     # 只允许写草稿的接口
        inputs:
          topic_source: editorial-queue
        on_error: stop
    
      - id: review
        tool: agent-flow/v1/review
        checks:
          - factual_claims_have_source
          - no_external_links_without_allowlist
          - length_within_range
        on_fail: return_to: draft
        max_retries: 1
    
      - id: human_gate
        type: manual                  # 人工确认,不可被 agent 跳过
        notify_channel: editorial
        timeout_action: keep_draft
    
      - id: publish
        tool: agent-flow/v1/publish
        requires: human_gate.approved

    human_gate 这一段是整份文件里最不该省的。把人工确认写成流程里的一个显式阶段,而不是「记得去后台看一眼」,才能让 publish 接口有资格拒绝任何没带审批标记的请求。发布端的校验大致是这个意思:

    function agent_flow_publish( WP_REST_Request $request ) {
        $post_id = absint( $request['post_id'] );
    
        if ( 'approved' !== get_post_meta( $post_id, '_agent_stage', true ) ) {
            return new WP_Error( 'agent_flow_not_approved', '该草稿尚未通过人工确认', array( 'status' => 409 ) );
        }
    
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );
    
        // 把这次运行的关键动作追加进可查询的审计记录
        add_post_meta( $post_id, '_agent_audit', wp_json_encode( array(
            'stage'  => 'publish',
            'run_id' => get_post_meta( $post_id, '_agent_run_id', true ),
            'time'   => current_time( 'mysql', true ),
        ) ) );
    
        return array( 'post_id' => $post_id, 'status' => 'publish' );
    }

    服务端做这层判断,而不是信任调用方声称「已审过」,是可审计流水线和「看起来有审核」的分界线。

    审稿阶段的检查项也建议尽量写成能机械判定的规则。像「是否有无来源的具体数字」「外链是否在白名单内」「篇幅是否越界」这类,agent 能给出稳定结论;而「语气对不对」「这个判断站不站得住」交回人工,命中率更高,也省得为了让流程全自动而降低标准。

    传统插件触发器和工作流编排,差别到底在哪

    这两种做法都能把文章发出去,区别在事后能不能说清发生了什么,以及流程长大之后改不改得动。

    维度传统插件触发器Buzz + YAML 工作流
    触发方式定时任务或后台钩子,条件写死在代码里频道内的对话事件或显式调用,条件写在流程文件里
    行为归属通常复用管理员账号agent 持有独立身份,动作可归属到具体主体
    流程变更追溯改设置项,历史版本一般不留痕流程文件进版本库,改动产生 diff
    人工关卡靠人记得去后台审作为显式阶段存在,发布端可强制校验
    失败恢复多为重跑整个任务可按阶段和 run_id 定位后重入
    扩展新步骤往回调里继续加分支在流程文件中新增阶段,能力面单独授权

    代价也得说清楚。插件触发器装完就能跑,而这套方案要你自己维护 relay、机器身份、接口和流程文件,初期投入明显更高。站点每天出一两篇稿、只有你一个人管,用现成插件更划算;一旦有多人协作、有对外署名的内容要负责、或者需要向别人解释某篇文章是怎么来的,可审计性才开始值这个钱。

    内容流水线中的人工审稿关卡示意

    接线之前先过一遍这几项

    真正把 agent 接到生产站点之前,这几项我会逐条确认,顺序大致就是风险从高到低:

    • 生成类接口是否物理上无法直接发布,而不是靠流程「约定」不发布
    • 机器身份的凭据能否单独吊销,吊销后站点其他自动化是否照常
    • 每篇由 agent 产出的文章能否反查到 run_id、阶段轨迹和审批人
    • 频道里的输入被视为不可信数据处理——尤其当 agent 会读取评论、外部页面或投稿内容时
    • 先在预发布站点跑满一个内容周期,再决定要不要放到主站

    最后一点补充:先从一条最短的链路开始,只做「生成草稿 + 人工确认」,把审计记录跑通了再往里加自动审稿、多 agent 分工。流程文件的价值恰恰在于加东西的时候有 diff 可看,不必一开始就把全部阶段设计完整。想看 Buzz 这套身份和工作区模型的具体表述,仓库里的 VISION 文档比二手解读清楚得多;而 MCP 侧的落地形态,VayuPress 那篇连接器说明提供了一个可对照的实现思路。

    声明:原创文章请勿转载,如需转载请注明出处!

    • 抢沙发

    请登陆后再发表您的观点吧!

    账号登陆

    快捷登陆