这篇文章记录我现在的博客发布工具链,以及怎么让它跟任意 AI Agent 配合。
如果你也在用 AI 写东西,并且有一个自己的站,这套结构可能比你想的更省事。
之前的工具链
先说说为什么要改。
我之前的架构是 MX Space Core + Shiro + Hermes Agent + taifost-writer。taifost-writer 自己带一条 collect → write → polish → format → review_pending 的流水线,还要连模型、连 QQ、维护角色配置和阶段产物。
问题很直接:我平时用别的 AI Agent 写文章,写到满意才需要"发出去"这一个动作。writer 那套自动收集素材、自动写作、自动润色的流程,跟我的实际用法完全重复。为了一个"发布"动作,我要维护五个阶段的数据库、模型调用审计、队列和重试——投入产出完全不成比例。
所以我把它整个删了。
现在的结构
现在的链路只有三层:
- Shiro:前台,负责页面渲染
- Core:内容、分类、发布,所有文章真正的归属地
- Agent Publish API:一个只做"把 Markdown 发上去"的接口
没有中间服务,没有队列,没有阶段产物。Agent 生成的文章直接进 Core。
怎么用
第一步:让 Agent 读文档
文档地址:
https://api.taitres.com/api/v3/agent/docs
这是 Markdown 格式,Agent 可以直接抓取。里面有完整字段、curl 示例和错误码。另有一个给人看的网页版:
https://api.taitres.com/api/v3/agent/docs.html
第二步:把密码告诉 Agent
接口用一个 6 位数字密码保护,通过请求头传递:
Authorization: Bearer <6位数字密码>
密码只单独告诉 Agent,不写进文章,也不放进 URL。连续输错 10 次,同一 IP 会被锁 10 分钟。
第三步:发布
最小请求只需要标题和正文:
curl -X POST 'https://api.taitres.com/api/v3/agent/publish' \
-H 'Authorization: Bearer <6位数字密码>' \
-H 'Content-Type: application/json' \
-d '{"title":"文章标题","markdown":"# 正文\n\n内容..."}'
成功后返回:
把 url 拿回来,就是文章的公开地址。
字段
| 字段 | 必填 | 说明 |
|---|---|---|
title | 是 | 标题,300 字以内 |
markdown | 是 | 正文,纯 Markdown |
slug | 否 | URL 地址,只能用拉丁字母、数字、短横线 |
summary | 否 | 摘要 |
tags | 否 | 标签数组,最多 20 个 |
category | 否 | 分类 slug,默认 default |
draft | 否 | true 只存草稿,不公开 |
几个设计上的取舍
不用传 hash。 之前的接口要求客户端计算正文的 SHA-256 来做幂等。对脚本没问题,对 LLM Agent 就是个多余的失败点。现在服务端自己处理。
同一 slug 等于更新。 改完稿子重新提交同一个 slug,会更新原来那篇,不会多出一篇。这比让 Agent 维护 revision 号可靠得多。
中文标题不用愁。 slugify 会把纯中文标题吃成空串,所以服务端做了兜底:没有可用 slug 时生成一个稳定的 p-xxxxxxxxxxxx。同标题重发仍然落到同一篇。
响应不做包装。 Core 全局会把响应字段转成 snake_case 再套一层 data,这个接口用 RawResponse 绕过了。文档里写的返回结构就是真实返回结构,Agent 不需要猜。
安全
6 位数字只有一百万种组合,直接暴露在公网上,几分钟就能被跑完。所以密码之外加了一层失败计数:同一 IP 十分钟内错 10 次返回 429。密码本身用常量时间比较,避免时序侧信道。
对一个个人博客的发布接口来说,这个强度够了。
实际体验
现在我的流程是:
- 跟 Agent 说"写一篇关于 X 的文章"
- 来回改到满意
- 说"帮我发到这个网站上"
- Agent 读文档、调接口、把链接给我
从"维护一条流水线"变成"维护一个接口",中间省掉的东西,比我预想的多。