从聊天到干活:OpenBot 如何把一句话变成一整套行动
打开任何一个 AI 对话界面,输入“帮我整理下周的客户拜访记录并发送给团队”,你大概率得到的是一段“好的,我建议你这样做……”的建议。但如果你是市场、运营或行政岗位的人,你真正想要的不是建议,而是结果——记录被整理好了,邮件已经发出去了,团队已经收到了。
这就是“聊天机器人”和“AI 同事”之间最本质的差距。前者陪你说话,后者帮你干活。
OpenBot 想做的是后者。它不是又一个能聊天的对话框,而是一个面向非开发者的 AI 助手,核心能力在于两件事:任务规划(Task Planning)和工具调用(Tool Calling)。本文拆解 OpenBot 背后的实现原理,看它如何把用户模糊的意图拆解为可执行的行动计划,并通过调用外部工具完成真实工作。
第一章 从 Agent 到 AI 同事:概念演进
什么是 Agent

Agent(智能体)这个词在 AI 圈已经泛滥了,但多数人并没有说清楚它和“调用一次大模型”有什么区别。最直白的定义是:Agent 是一个具备感知(Perception)、决策(Decision)和行动(Action)能力的闭环系统。
- 感知:接收用户输入,理解上下文和环境状态
- 决策:根据目标规划行动步骤,选择合适策略
- 行动:调用工具、执行操作,并对结果做出反应
单一的模型调用只是“感知 → 生成文字”的线性过程,没有决策和行动环节。而 Agent 是一个循环:它规划、执行、观察结果、再调整,直到完成目标。
从“单轮问答”到“多步骤任务”

传统的对话机器人是“一问一答”模式:你输入,它输出,结束。这种模式适合查资料、翻译文本、写文案,但无法胜任真实工作场景中的多步骤任务。
真实工作是什么样?以“帮我整理下周的客户拜访记录并发送给团队”为例,这个任务包含至少五个步骤:
- 找到客户拜访记录的数据源(可能是 Excel 或 CRM 系统)
- 读取数据并理解字段含义(客户名、拜访日期、拜访人、结果摘要)
- 清洗和格式化数据(补全缺失字段、统一日期格式、剔除无效记录)
- 生成一份摘要或报表(按客户汇总、按日期排序、提炼关键信息)
- 将结果通过邮件发送给指定团队
每一步都需要不同的能力:文件读取、数据处理、文本生成、邮件操作。一个“问答式”AI 无法完成这些,因为它不能“动手”。Agent 的核心能力恰好是“规划 + 执行 + 反馈”:它把大目标拆成小步骤,逐步执行,并在每一步之后观察结果、决定下一步动作。
AI 同事的定义
“AI 同事”不是营销话术,它有一个很实在的标准:能不能主动完成一项完整的工作任务。
如果 AI 能帮你发邮件、整理表格、排日程、生成报表,并且这些操作是真实发生的(不是给你一段“建议代码”让你自己去跑),那它就是“AI 同事”。如果它只能给你“建议”,那它仍然是一个“聊天机器人”。
OpenBot 的定位很清晰:面向非技术用户,把 Agent 的复杂性藏起来,提供一种“同事式”的交互体验。用户不需要理解什么是 API、什么是工具调用、什么是任务分解,只需要用自然语言描述目标,OpenBot 负责拆解和执行。
第二章 任务规划:把大目标拆成小步骤
规划的本质
任务规划是 Agent 的“大脑”。它的核心问题只有一个:如何将用户模糊的自然语言指令转化为一组可执行的子任务序列?
举个例子,用户说:“帮我统计本月加班时长并生成周报邮件。”
这句话信息密度很低,但隐含了大量需要明确的内容:
- “加班时长”的数据源在哪里?(考勤系统?Excel 表格?)
- “本月”是指自然月还是最近 30 天?
- “统计”是按人统计还是按部门统计?要不要计算加班费?
- “周报邮件”发给谁?格式是什么?
规划的第一件事不是“拆步骤”,而是“搞清楚意图”。
关键机制一:意图识别与目标解析
意图识别在传统 NLP 时代是一个分类问题:预定义几个意图类别,然后做文本分类。但在 LLM 时代,意图识别变成了“结构化信息抽取”——从自然语言中提取出动作、对象、时间、目标等要素。
以“帮我整理下周的客户拜访记录并发送给团队”为例,OpenBot 内部的意图解析模块会生成类似这样的 JSON 结构:
{
"intent": "send_report",
"target_entity": "客户拜访记录",
"time_range": {
"start": "2025-03-03",
"end": "2025-03-09"
},
"action": "整理并发送",
"recipient": "team",
"channel": "email",
"format": "summary"
}
这个结构化表示是后续任务分解的基础。它让系统知道:要做什么(发送报告)、对象是什么(客户拜访记录)、时间范围(下周)、收件人(团队)。
这个环节最关键的工程挑战是:如何保证 LLM 输出的 JSON 结构稳定。实践中的做法是使用函数调用(Function Calling)机制,让模型严格按照预定义的 schema 输出,而不是自由发挥。OpenBot 会定义这样的工具调用协议:
{
"name": "parse_intent",
"parameters": {
"type": "object",
"properties": {
"intent": { "type": "string" },
"target_entity": { "type": "string" },
"time_range": { "type": "object" },
"action": { "type": "string" }
},
"required": ["intent", "target_entity", "action"]
}
}
关键机制二:任务分解(Task Decomposition)
目标解析完成后,下一步是任务分解。这一步依赖 LLM 的推理能力,但不能完全依赖 LLM 自由发挥——需要约束输出格式。
OpenBot 的做法是让 LLM 生成一个结构化的任务列表,每个任务包含:任务描述、依赖的输入、预期输出、调用的工具类型。以上面的“客户拜访记录”任务为例,分解结果如下:
{
"tasks": [
{
"task_id": 1,
"description": "查找并读取客户拜访记录数据源",
"input": "data_source=crm_export.csv",
"output": "raw_records",
"tool": "file_reader",
"dependencies": []
},
{
"task_id": 2,
"description": "清洗数据,统一日期格式并剔除无效记录",
"input": "raw_records",
"output": "cleaned_records",
"tool": "data_processor",
"dependencies": [1]
},
{
"task_id": 3,
"description": "按客户汇总生成拜访摘要",
"input": "cleaned_records",
"output": "summary",
"tool": "llm_text_generator",
"dependencies": [2]
},
{
"task_id": 4,
"description": "发送邮件给团队",
"input": "summary",
"output": "email_sent",
"tool": "email_sender",
"dependencies": [3]
}
]
}
这个 JSON 结构的价值在于:它是机器可读的,执行引擎可以直接遍历这个任务列表,按顺序或按依赖关系执行。同时它又是人类可读的,用户可以在执行前检查 OpenBot 的计划是否合理。
关键机制三:依赖关系与执行顺序
任务分解产生的不只是一个列表,而是一个有依赖关系的有向无环图(DAG)。某些任务可以并行执行,某些必须串行。
举一个并行执行的例子:用户说“帮我统计上周的销售数据和客户反馈,生成一份周报”。这里“统计销售数据”和“整理客户反馈”是两个独立的数据源,可以并行处理;但“生成周报”必须等两者都完成后才能开始。
OpenBot 在执行引擎中维护一个任务队列,基于依赖关系决定哪些任务可以立即执行,哪些需要等待:
任务 1: 读取销售数据(无依赖,立即执行)
任务 2: 读取客户反馈(无依赖,立即执行)
任务 3: 生成周报(依赖任务 1 和 2,等待)
失败处理与回退
真实环境中,任务执行不可能一帆风顺。数据文件不存在、字段格式与预期不符、邮件服务返回 500 错误——这些都会发生。OpenBot 的规划器必须处理这些异常。
OpenBot 采用了两层策略:
- 预检查:在执行任务前,先检查前置条件是否满足。比如文件是否存在、权限是否足够。
- 重试与回退:如果某一步失败,先重试(最多三次);重试仍失败,则尝试替代方案(比如用另一个工具实现同样的功能);如果替代方案也没有,就停下来,向用户报告失败原因,而不是“假装成功”。
这个环节很容易被忽略,但恰恰是“AI 同事”和“玩具 Demo”的分水岭。
规划结果的结构化表示
最终,规划器的输出不是一段自然语言描述,而是一个结构化的任务描述(JSON 或 DSL),供执行引擎读取。这个表示必须包含足够的信息让执行引擎“无需思考就能执行”。
在工程实现上,OpenBot 用 JSON Schema 做校验,确保 LLM 生成的规划结果符合预定义格式,避免“模型自由发挥导致执行引擎崩溃”的经典问题。
第三章 工具调用:让 Agent 真正“动手”
工具的本质
规划只解决了“做什么”的问题,工具调用解决“怎么做”的问题。
工具的本质非常朴素:把外部 API、脚本、软件操作封装为一个统一接口,让 LLM 能够“选择”并“调用”它。
从工程师视角看,工具就是一个函数,有输入、有输出、有副作用(副作用指:发邮件、改文件、创建日历事件等真实世界的影响)。
常见工具类型
在 OpenBot 面向白领用户的设计中,最常见的工具类型包括:
- 文件读写:读取 CSV、Excel、TXT;写入结果文件
- 表格处理:对表格数据进行筛选、排序、聚合、透视
- 邮件发送:发邮件、带附件、支持多收件人
- 日历操作:创建日程、查询空闲时间、发送会议邀请
- 网页搜索:抓取网页内容、搜索公开信息
- 数据库查询:连接内部数据库执行 SQL 查询
工具注册与描述
每个工具在 OpenBot 中注册时,需要附带两样东西:功能描述和参数 Schema。LLM 根据功能描述决定“该用哪个工具”,根据参数 Schema 决定“怎么填参数”。
以下是一个邮件发送工具的函数签名示例:
def send_email(
to: str, # 收件人邮箱,支持逗号分隔多个
subject: str, # 邮件主题
body: str, # 邮件正文,支持纯文本
attachments: list[str] = [], # 附件路径列表
cc: str = "", # 抄送
) -> dict:
"""
发送一封邮件。成功返回 {"status": "success", "message_id": "xxx"},
失败返回 {"status": "error", "error": "详细错误信息"}。
"""
# 实现略
LLM 在规划执行时,会把用户指令映射到这个函数的参数上。例如用户说“把摘要发给团队”,LLM 会填充 to 参数为团队邮件列表,subject 为“客户拜访记录摘要”,body 为生成的摘要内容。
工具描述必须非常精确。如果描述模糊,LLM 可能选错工具或填错参数。OpenBot 在实践中发现,工具描述写得越具体、示例越丰富,LLM 选对工具的概率越高。
调用流程
工具调用的标准流程如下:
- 规划器生成任务列表,每个任务指定了工具类型和输入参数(参数可以来自用户原始指令,也可以来自前一个任务的输出)
- 执行引擎按依赖关系顺序执行,依次调用对应工具
- 工具返回结果(结构化数据或状态信息)
- 执行引擎将结果传给下一个任务,或者返回给用户
- LLM 在关键节点参与:比如生成摘要、提炼关键信息、决定下一步动作
多轮工具调用与中间结果传递
一个复杂任务往往需要连续调用多个工具,中间结果需要在任务之间传递。例如“从 CSV 中提取转化率并做图表,放进 PPT”这个任务,实际调用序列是:
工具 1: file_reader → 读取 CSV 数据
工具 2: data_processor → 计算转化率(按周分组,计算转化百分比)
工具 3: chart_generator → 生成折线图或柱状图(输出为 PNG 文件)
工具 4: ppt_editor → 新建 PPT,插入图表,保存文件
中间结果的传递方式是内存中的变量传递,类似 Unix 管道:前一个工具的输出是后一个工具的输入。OpenBot 内部维护一个“共享状态池”,每个任务的输出按任务 ID 存储,后续任务通过引用任务 ID 来获取数据。
这也带来了一个工程难点:数据格式的兼容性。文件读取工具输出的是 DataFrame 格式,而图表生成工具期望输入的是二维数组。OpenBot 在每个工具之间增加了一个“格式转换层”,确保数据能正确流转。
第四章 从开发者到普通白领:OpenBot 的交互设计
隐藏复杂性
OpenBot 的核心用户不是开发者,而是市场、运营、行政、销售这些“普通白领”。这意味着交互设计的第一原则是:用户不需要知道“工具”和“API”的存在。
用户不会说“调用一个 email_sender 工具”,他们会说“帮我发个邮件”。OpenBot 需要做的是把后一句话自动翻译成前一句话,执行完成后,再翻译回用户能理解的语言。
这听起来简单,实际做到位非常难。用户说“帮我统计本月加班时长”,系统需要:
- 搞清楚“加班时长”数据在哪里(可能根本没有现成的数据结构)
- 搞清楚“本月”是自然月还是最近 30 天
- 搞清楚统计口径(含不含周末?含不含法定节假日?)
- 搞清楚输出格式(表格?图表?邮件正文?)
OpenBot 的策略是:能自动推断就自动推断,不能自动推断就问。在规划阶段,如果某个关键参数缺失且无法从上下文推测,OpenBot 会向用户提出澄清问题,而不是“猜一个值”然后出错。
确认与反馈机制
AI 同事和聊天机器人的另一个区别是:AI 同事需要“责任意识”。它执行的操作有真实世界的影响——发出去了收不回来的邮件、删掉了无法恢复的文件。因此,OpenBot 在关键操作之前,会向用户展示执行计划并请求确认。
交互流程如下:
用户: 帮我整理下周的客户拜访记录并发送给团队
OpenBot: 我计划执行以下操作:
1. 读取 CRM 导出文件(customer_visits.xlsx)
2. 筛选下周(3月3日-3月9日)的拜访记录
3. 按客户生成摘要
4. 发送邮件给团队(team@company.com)
5. 邮件主题:客户拜访记录摘要(3月3日-3月9日)
确认执行?[确认 / 修改]
这个确认机制不是“多此一举”,而是建立信任的关键。用户只有看到 AI 的计划是合理的,才会放心让它执行。OpenBot 的确认页还会展示“预计影响”:发了几封邮件、改了几个文件、创建了几个日程事件。
进度可视化与错误处理
执行过程中,OpenBot 会实时展示当前进度:
✓ 读取客户拜访记录(耗时 0.8s)
✓ 筛选下周拜访记录(找到 23 条)
✓ 生成客户拜访摘要(耗时 2.1s)
→ 正在发送邮件...
如果某一步失败,OpenBot 不会抛出一个“系统错误,请重试”的冷冰冰的提示,而是用人类可读的语言解释问题,并给出建议:
✗ 邮件发送失败
原因:无法连接邮件服务器(smtp.office365.com)
建议:请检查网络连接,或联系 IT 部门确认邮件服务是否正常。
你可以选择:重试 / 跳过此步骤 / 修改收件人后重试
示例场景一:行政人员统计加班时长
行政人员张姐的使用场景:“帮我统计本月加班时长并生成周报邮件。”
OpenBot 的规划输出如下:
{
"intent": "overtime_statistics",
"tasks": [
{
"task_id": 1,
"tool": "file_reader",
"description": "读取考勤数据文件",
"params": { "path": "attendance/2025-02.xlsx" },
"dependencies": []
},
{
"task_id": 2,
"tool": "data_processor",
"description": "筛选本月加班记录并计算每人加班时长",
"params": { "filter": "date >= 2025-02-01 AND date <= 2025-02-28", "group_by": "employee_name", "agg": "sum(hours)" },
"dependencies": [1]
},
{
"task_id": 3,
"tool": "llm_text_generator",
"description": "生成周报邮件正文",
"params": { "prompt": "基于以下加班统计数据,生成一份周报邮件正文:{task_2_output}" },
"dependencies": [2]
},
{
"task_id": 4,
"tool": "email_sender",
"description": "发送邮件给部门负责人",
"params": { "to": "manager@company.com", "subject": "2025年2月加班统计周报" },
"dependencies": [3]
}
]
}
张姐不需要理解 JSON,不需要知道什么是“依赖关系”。她看到的只是确认页面上的四行计划,点一下“确认”,几分钟后邮件就发出去了。整个过程她只做了两个动作:输入指令、点击确认。
示例场景二:运营人员制作转化率图表 PPT
运营人员小王的需求更复杂:“从这份 CSV 中提取上周的转化率,做成图表,放到 PPT 里。”
这个任务涉及多工具协作和数据格式转换:
工具 1: file_reader → 读取 conversion_data.csv
工具 2: data_processor → 按日期分组计算转化率(转化数/曝光数)
工具 3: chart_generator → 生成折线图(输出:conversion_trend.png)
工具 4: ppt_editor → 新建 PPT,将图表插入到第 1 页
工具 5: file_saver → 保存为 conversion_report.pptx
技术难点在于数据格式的传递:data_processor 输出的 DataFrame 需要转换为 chart_generator 能接受的二维数组格式;chart_generator 生成的 PNG 文件路径需要传给 ppt_editor。
OpenBot 的格式转换层在这里发挥了作用。对于开发者来说,这个环节可能是最复杂的部分,但对小王来说,他只需要说一句话,然后在确认页面看到“我将生成一个包含转化率趋势图表的 PPT”,点击确认即可。
第五章 局限与未来:从“能用”到“好用”
当前挑战:任务规划的准确率
尽管 LLM 的推理能力已经很强,但在复杂模糊指令下的任务规划准确率仍然有限。用户说“帮我弄一下这个”,系统很难判断“弄”是什么意思。用户说“跟上次一样”,系统需要记忆上次的操作上下文。
OpenBot 目前的策略是“多轮澄清 + 学习用户偏好”。如果某个用户经常使用相似指令,系统会记住他的偏好(比如“发给团队”默认指“team@company.com”),下次直接使用默认值。
工具调用的稳定性
工具调用最大的痛点是外部依赖的不可靠性。邮件服务可能宕机、文件可能被锁、API 可能限流、权限可能过期。OpenBot 的应对策略包括:
- 超时控制:每个工具调用设定超时时间(默认 10 秒),超时后自动重试或报告失败
- 参数校验:调用前用 JSON Schema 校验参数合法性,避免传空值或错误类型
- 降级方案:主工具失败时尝试替代工具(比如 A 邮件服务失败,尝试 B 邮件服务)
安全与隐私
普通用户的数据往往更敏感——考勤数据、客户信息、财务报表。OpenBot 必须考虑:
- 数据权限:每个用户只能访问自己有权限的数据源和工具
- 操作审计:所有工具调用记录日志,便于追溯
- 敏感操作确认:删除、覆盖、群发邮件等操作必须二次确认
未来方向
OpenBot 的路线图上有几个值得关注的方向:
- 自我学习:记录用户偏好和操作习惯,逐步减少需要用户确认的步骤
- 多 Agent 协作:不同工具由不同 Agent 负责(比如“数据 Agent”“邮件 Agent”“PPT Agent”),主 Agent 负责任务调度
- 跨平台集成:从内部工具扩展到飞书、钉钉、企业微信等办公平台,让 AI 同事真正融入工作流
总结
OpenBot 的本质不复杂:把“任务规划 + 工具调用”封装成一个对非技术用户友好的产品。它的核心价值在于,让 AI 从“回答者”变成了“执行者”——不再只是告诉你“应该怎么做”,而是直接帮你做完。
对普通白领来说,这意味着自动化的门槛被大幅降低。过去只有会写 Python 脚本的人才能自动化自己的工作流,现在只需要用自然语言描述目标,AI 同事就能接管那些重复、琐碎、多步骤的工作。
对开发者来说,OpenBot 提供了一个值得借鉴的产品化思路:Agent 技术能否落地,关键不在于模型的推理能力有多强,而在于规划是否可靠、工具生态是否丰富、交互设计是否让用户信任。模型再聪明,如果规划结果不稳定、工具调用总出错、用户不放心让它执行,那它就只能停留在 Demo 阶段。
最后想说一点:AI 同事的出现,不是为了取代人,而是把那些重复劳动接过去,让人把精力花在真正需要判断力和创造力的决策上。这也许是“AI 同事”这个概念的真正意义。
