将流程编译为故事线
将多步骤流程转换为有向状态图——创建、验证、发布。
create_storylinevalidate_storylinepublish_storylinelist_storylinesupdate_storyline故事线(Storyline)是挂在智能体上的有向图:它将“回答一个问题”转变为“端到端地执行整个任务”(包括信息收集、辅导、教练等)。节点是步骤(每个步骤都有自己的任务/技能/知识库/工具以及可写的配置维度);出口携带条件(ai / user_choice / rule / callback / goto_storyline)。运行时永远不会编辑智能体的核心或安全边界——它在第一个节点到最后一个节点之间保持不变,这正是受监管产品或面向儿童的产品所需要的。
创建草稿
create_storyline(
agent_name="Support", key="loan-intake", name="Loan intake",
profile_schema={"docs_ready": {"type": "bool"}}, # dims that accumulate across nodes
graph={"nodes": [
{"node_key": "n1", "title": "Understand need", "flags": {"is_entry": True},
"on_enter_opening": "Hi — which kind of loan are you applying for?",
"exits": [{"kind": "ai", "label": "need clear", "to_node_key": "n2",
"ai_criteria": "the user stated the loan type and rough amount"}]},
{"node_key": "n2", "title": "Collect documents",
"task": "Collect the checklist items; chase missing ones across turns.",
"exits": [{"kind": "user_choice", "label": "documents ready", "to_node_key": "n3",
"user_choice": {"button_text": "I've uploaded everything"},
"writes": [{"ref": "dim", "key": "docs_ready", "op": "set", "value": True}]}]},
{"node_key": "n3", "title": "Hand off", "task": "Summarise the case and hand off to a human.",
"flags": {"is_terminal": True}, "exits": []}
]},
allow_agent_enroll=True,
enroll_trigger="the visitor says they want to apply for a loan",
)★ 验证,然后发布 ★
validate_storyline(storyline_id="…") # → {"ok": true} is required to publish
publish_storyline(storyline_id="…") # freezes an immutable version and goes live注册 —— 谁进入,何时进入(均需发布)
is_default=True—— 每个智能体一个;在第一次对话时自动注册。allow_agent_enroll=True+enroll_trigger—— 当智能体判断触发条件满足时,由智能体注册用户。entry="user"(或"both")—— 该流程会显示在聊天小部件的引导式流程菜单和新聊天下拉菜单中,因此由用户主动启动(是一个按钮,而非模型判断)。提供display_name和一行description—— 这就是菜单显示的内容。结合concurrency="session"用于“每次对话一个案例”的流程:每次选择都会开启一个新案例。- 在控制台中手动分配。
用户所见 —— 可见性、横幅和只读地图
user_visibility 控制运行中流程的终端用户展示(默认为 invisible):
invisible—— 没有任何 UI;流程在后台静默驱动(之前的行为)。named—— 聊天上方显示一个细长的横幅,展示流程名称。除此之外无其他内容。trail—— 横幅 + 一个 View 按钮,打开只读地图:已完成的步骤显示其标题;未完成的分支和未来的步骤显示为匿名灰色块(服务器端隐藏 —— 用户只能看到流程有多长,看不到具体内容)。full—— 带有步骤x / y的横幅 + 完整地图:每个步骤都有名称,并根据已完成/当前/即将进行的状态进行颜色编码。
附加功能:allow_exit=True 会在横幅中添加一个退出按钮(退出的流程在该对话中不会自动重新注册;用户选择的流程可以从菜单重新进入,进度保留)。show_profile=True 会在地图下方列出配置维度的当前值(当 schema 声明了最小值/最大值时,数字显示为进度条)。对于每个节点,rewind: "reset" | "keep" 允许用户在完整地图中点击已完成的步骤并返回到该步骤 —— reset 会恢复进入时捕获的配置快照,keep 会保留收集到的数据(用于学习/审查流程)。现实世界的副作用(已归档的记录、已提交的文档)永远不会回滚,因此仅标记无副作用的步骤。在 IM 渠道(Telegram/WhatsApp)上,/storyline 命令会报告当前流程,对于 trail/full,返回一个指向同一只读地图的短期有效签名链接。
旧的 learner_visibility 参数名称及其 hidden / completed_only 值仍然被接受(它们分别映射到 invisible / trail),但已弃用 —— 请使用 user_visibility。
并发 —— 进度是跟随人,还是跟随案例?
concurrency 决定一个用户在此流程线上可以有多少个运行实例:
"user"(默认)—— 每人一个运行实例;每次对话都延续相同的进度。适用于课程、入职流程、KYC:关注“这个人进展到哪一步了”。"session"—— 每次对话一个运行实例;新聊天开启一个全新的独立案例。适用于许可证申请、支持工单、按产品流程:关注“这个案例进展到哪一步了”。同一用户可以在三个聊天中运行三个产品申请,每个申请都有自己的进度和黑板。
将状态放在合适的位置:案例状态在黑板上(它随运行实例的生而生、死而死 —— 产品名称、此申请的文件列表),关于人的事实在配置维度中(它们跟随用户跨运行实例和故事线 —— 公司详情、已验证的身份)。每次对话一个案例是有意为之:要开启另一个案例,请开启另一个聊天。更改 concurrency 仅影响未来的注册;已在运行中的实例保留其键。
检查表、门控选择、文件和确定性操作
四种节点级功能将“由 AI 决定何时完成”转变为累积的、确定性的状态:
checklist—— 节点上的[{key, label}, …]。每次对话,平台都会根据访客实际提供的内容(上传的文件,或包含具体细节的描述 —— 承诺不算数)勾选项目,并且当所有项目都勾选完毕时,退出规则{"op": ">=", "left": {"ref": "checklist"}, "right": {"value": 1}}会推进流程。只读地图会向用户展示一个实时的 ✓/○ 列表。这是申请/审批流程的正确形态:第一步宣布需要什么,第二步的检查表逐项收集。choices_offer: "on_ready"—— 选择按钮的游戏式节奏:它们保持隐藏(并且禁用文本匹配 —— 不能通过输入按钮文字来跳过),直到步骤完成 —— 检查表完成,或者你提供的choices_ready_criteria被判断为真。对于真正的替代方案决策,请使用user_choice;单独的“继续”按钮是一个警示信号。{"ref": "files"}在退出规则中 —— 在此节点期间上传的文件/图像数量(转换时重置)。files >= 2是一个完全确定性的“文档已接收”门控。questions—— 每个节点的破冰小部件(最多 6 个):用户在该步骤可能会问的问题,作为可点击的建议显示在他们停留期间。与on_enter_opening配合使用,使每个步骤既介绍自己又提供入口 —— 用户不应感到困惑“我在这里该做什么”。on_enter_actions/on_complete_actions——[{tool, args}]平台在步骤进入/完成流程时确定性执行(例如,在终端步骤使用mcp__agent4__submit_lead归档潜在客户)。字符串参数使用大括号模板插值维度和黑板键。失败会被记录,且绝不会破坏聊天。
无论故事线有多长,上下文保持扁平:每次对话仅注入当前节点(任务、资源、选择)、配置维度以及大小受限的黑板 —— 绝不会是整个图或过去的步骤。长旅程(一学年、一整个游戏赛季)应链接故事线(on_complete: goto_next):每条线的黑板从头开始,而配置维度会延续,这正是“总结过去,如实保留现在”。
退出判断器现在可以看到最近的对话窗口和收集到的状态,而不仅仅是最后一条消息 —— 但请保持 ai_criteria 关于访客说或做的事情;上述检查表机制仍然比任何文本标准更强大。
设计陷阱 —— 每一个都曾在生产中导致流程卡死
你(构建此智能体的人)最有可能制造这些错误。在发布前检查每一项:
rule出口需要写入器。readiness >= 100是一个死胡同,除非有东西实际写入readiness:出口的writes(确定性 —— 首选)、节点的profile_writes(带source: "ai",从对话中评分)、另一个故事线或手动控制台编辑。validate_storyline现在将其标记为warn.rule_unwritten_dim—— 除非你知道存在外部写入器,否则将此警告视为错误。这个确切的错误曾导致一次发布:一个三步信息收集流程,其第二步门控在一个没有任何东西写入的维度上;用户永远无法通过它。- AI 评分的维度几乎从不达到精确边界。 如果维度由模型评分,
>= 100(或== max)实际上永远不会触发 —— 模型评分保守。门控在合理的阈值上(>= 70),或将步骤的完成设为user_choice并使用出口的writes确定性设置值。 user_choice精确匹配按钮文本 —— 且标签必须说明其作用。 访客的消息必须等于button_text。在可见行上,小部件将这些渲染为真实按钮,因此请编写完整、精确的动词短语 —— “开始文档收集”,而不是“开始”(开始什么?—— 来自测试的真实反馈)。保持它们不同且使用受众的语言。在invisible行上没有按钮 —— 在节点task中重述选项。对于真正的决策(哪个分支、提交还是继续编辑),首选user_choice;“我是否完成了此步骤”是 AI/规则出口的工作,而不是按钮。- 发布不会触及已在运行中的实例。 注册固定在它们开始的修订版上 —— 错误修复发布仅影响新实例。要移动现有用户,调用
POST /storylines/{id}/enrollments/migrate(reset回到入口或move到节点 —— 两者都将运行实例重新固定到当前发布的修订版)。 - 在分发之前,以用户身份走过这条线。 打开共享的
/s/页面,进入流程,点击每个按钮和分支直到结束。编辑器的测试运行模拟图;只有真实页面同时练习开口、按钮、可见性和完成。
出口是按优先级排序(列表顺序):确定性 rule / user_choice / callback 优先判断,ai 最后。使用确定性出口构建 if/else、重试循环和 AND 连接 —— 不要赌 LLM。使用 update_storyline 编辑草稿(PUT 语义;保持所有 node_key 稳定,因为出口和漏斗引用它)。
报告回来。 返回已发布 Storyline 的控制台链接 ——
https://console.agent4.io/#/storylines/<id>(来自create_storyline的 id)—— 并附上流程的一行摘要以及用户如何进入它。