本案例研究将现有的 AI 故事 SaaS StoryShelf 连接到 AgentChat。用户通过对话创建故事;代理通过 StoryShelf API 写入结构化的故事和章节记录,启动插图任务,检查返回的图片 URL,并更新故事。随后,StoryShelf 读取自身的数据库,并在其常规的作品库和编辑器中显示结果。
重要的一点是,AgentChat不会变成故事数据库,StoryShelf也不会将一段很长的助手回答解析成记录。代理执行的是StoryShelf应用已经理解的同样的受控操作。
步骤1:公开StoryShelf能力包
POST /v1/stories
GET /v1/stories/{story_id}
POST /v1/stories/{story_id}/chapters
PUT /v1/stories/{story_id}/chapters/{chapter_id}
POST /v1/image-jobs
GET /v1/image-jobs/{job_id}
PUT /v1/stories/{story_id}/cover 每个创建响应都会返回稳定的ID。故事和章节写入操作使用client_request_id实现幂等,因此重试不会创建重复项。图像任务是异步的,并返回poll_after_seconds。已完成的图像响应包含asset_id和image_url,绝不包含base64数据。
步骤2:配置StoryShelf文档
POST /api/api-documents
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"title": "StoryShelf Story and Illustration API",
"description": "Create stories and chapters, generate illustrations, and attach image assets.",
"content": "# StoryShelf API\nBase URL: https://stories.example.com/v1\n\nCreate the story record before chapters and preserve every returned ID. Write chapters one at a time.\n\nPOST /stories body: client_request_id, title, audience, style, premise, outline[]. Response: story_id, status.\n\nPOST /stories/{story_id}/chapters body: client_request_id, position, title, content. Response: chapter_id, revision.\n\nPOST /image-jobs body: client_request_id, story_id, chapter_id optional, prompt, aspect_ratio. Response: job_id, status, poll_after_seconds. Start the job in one turn; sleep and poll in a later turn.\n\nGET /image-jobs/{job_id} returns status and, when succeeded, asset_id and image_url. Call view_image when visual inspection is useful.\n\nPUT /stories/{story_id}/cover body: asset_id.\n\nNever publish a draft unless the user explicitly asks."
} 该文档包含一些无法仅从OpenAPI路径列表中可靠推断出的工作流规则:保留ID、分开处理异步轮次、检查图像URL,以及不要隐式发布。
步骤3:创建用户的故事会话
POST /api/agent/sessions
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"title": "Story creator for user_88",
"llm_config_id": "creative_model_uuid",
"api_document_ids": ["story_api_document_uuid"],
"system_prompt": "Help the user plan and create stories. Save approved creative work through StoryShelf APIs. Keep the user informed when image jobs are running.",
"max_turns": 25,
"tool_timeout_seconds": 180,
"tool_result_max_chars": 12000,
"host_headers": [
{ "host": "stories.example.com", "header_key": "Authorization", "header_value": "Bearer short_lived_story_user_token" }
]
} StoryShelf 从后端创建此会话,并将返回的会话 UUID 存储在用户对话旁边。这个短期有效的请求头将所有故事 API 的读取和写入限制为 user_88。它会在请求时注入,不会包含在 LLM 上下文或 AgentChat API 响应中。
第 4 步:让用户通过聊天创建内容
POST /api/agent/sessions/session_uuid/chat
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"message": "Create a three-chapter story for ages 8-10 about a child who repairs a lighthouse for lost spaceships. Use a gentle watercolor style and make an illustrated cover."
} AgentChat 存储用户消息并返回 processing。StoryShelf UI 不会让聊天请求保持打开状态,而是立即开始轮询消息。
具体的工具调用顺序
- 代理规划标题、前提、受众、风格以及三部分大纲。
- 调用 POST /stories,并接收 story_id story_123。
- 通过单独的 API 调用分别写入第一章、第二章和第三章,并保留每个 chapter_id。
- 创建与已保存故事风格一致的图像提示词,并调用 POST /image-jobs。
- 由于任务必须异步完成,下一次模型轮次会使用 poll_after_seconds 调用 sleep,随后在之后的请求中轮询 GET /image-jobs/job_7。
- 当响应包含 image_url 时,代理会调用 view_image,使插图作为原生多模态输入进入上下文。
- 如果图像与故事匹配,代理会携带 asset_id 调用 PUT /stories/story_123/cover。如果不匹配,则会将修改后的提示词作为新任务提交。
- 最后返回已保存的故事 ID、章节摘要和封面状态。
工具结果会在完成后立即持久化,但下一次模型请求会按原始工具调用顺序接收并发执行的工具结果。API 文档应建议:当一个调用需要另一个调用返回的 ID 时,不要在同一个并行批次中执行相互依赖的写入操作。
第 5 步:正确合并 AgentChat 消息
GET /api/agent/sessions/session_uuid/messages?after_id=msg_uuid&after_revision=6
Authorization: Bearer ac_live_AGENT_CHAT_KEY StoryShelf 客户端仅在 revision 增大时替换消息。它可以渲染助手文本、简洁的插图任务活动信息以及最终图像预览。失败的部分助手消息仍会显示,但 AgentChat 会将其排除在未来的 LLM 上下文之外。
如果图像生成使用了剩余的回合预算,AgentChat 会返回 next_action 为 continue 的状态。StoryShelf 会显示“继续”按钮,并调用 POST /api/agent/sessions/session_uuid/continue。新的运行会获得全新的回合预算,并从持久化消息继续执行。
第 6 步:从 StoryShelf 数据库渲染故事
POST /stories、POST /chapters 和 PUT /cover 已经将经过验证的记录写入 StoryShelf。资料库页面会查询 StoryShelf 表,并显示新的标题和封面。编辑器会根据 story_id 加载章节。系统不会解析聊天记录来重建故事。
这种设计可以安全地处理部分完成的情况。如果封面任务失败,三个章节仍然存在。用户可以继续使用同一个 AgentChat 会话,并请求生成新封面,而无需重新生成故事。
上线前必须测试的内容
- 使用相同的 client_request_id 重试创建故事和章节,并验证不会出现重复记录。
- 返回图像任务失败,并验证代理保留故事内容并解释可恢复的步骤。
- 在图像轮询期间停止,然后继续会话并完成封面。
- 使用注入的令牌尝试读取其他用户的故事 ID,并验证 StoryShelf 返回 403 或“未找到”。
- 返回无效的图像 URL,并验证代理报告工具错误,而不是将其作为文本嵌入。
- 每次完成变更后,从自身数据库刷新 StoryShelf 内容库。