与智能体交朋友:AI智能体(Agentic AI)应用的心智模型

作者:Cornelia Davis

当我告诉一位同事,我正在写一篇关于AI智能体(AI Agent)心智模型的文章时,他问:“这篇会和市面上几十篇同类文章有什么不同?”

这个问题问得好,我琢磨了一会儿,最后想明白了:我读了好多相关文章,但脑子里还是没有一个清晰、能实际操作的模型。那些文章要么太过宏观,要么一头扎进了细节里。我无法理解“目标(goals)”、“工具(tools)”、“循环(loops)”和大语言模型(LLM)这些部分是如何融为一体的。

于是,我继续深入研究。我玩了玩 LangGraph,和 Cursor 一起体验了“凭感觉编程”(vibe coding)(编程智能体就是AI智能体很好的例子)。我用同事 Steve 创建的一个示例构建了一个新的智能体。我画了一些图(稍后会和大家分享),并和一些在这条学习曲线上遥遥领先的朋友们交流,也和一些和我一样正在学习的人聊了聊。现在,我终于明白了。别误会,我还有很多东西要学,但现在我有了个框架,可以围绕它继续学习。

这篇文章就是我希望我刚开始时就有的那个心智模型。它是为那些想要真正理解AI智能体应用是如何运作的开发者同仁们准备的:你需要构建什么、各个部分如何协同工作,以及为什么它不像最初看起来那么神奇(或神秘)。

我在这里所说的,是关于大语言模型和工具

首先,我要明确一下我所谈论的智能体类型:那种利用大语言模型(LLM)来驱动应用流程的智能体。也就是说,LLM决定了应用接下来要采取什么步骤,而智能体的工作就是按照LLM的指示去执行工具(tools)。别担心,我很快就会更清楚地解释“工具”。

我不会去讨论,对于那些通过代码来调用LLM和下游服务、且流程预先确定的应用,我们是否应该用“智能体”这个词来形容。这当然是个有趣的辩论,但这个问题已经在前面提到的那些文章中得到了充分讨论(我特别喜欢LangChain 的这篇)。

从现在开始,当我使用“AI智能体”或简称“智能体”时,我指的是一种大致按以下方式运行的应用:

Fig1
  • 智能体通常被实现为一个事件循环(event loop),以某种目标的表达(an expression of some goal)作为启动。

  • 在循环中,它会:

    • 要求大语言模型(LLM)来确定流程中的下一步,然后

    • 调用一个或多个工具来执行这些操作。

  • 它会持续循环,直到LLM达成目标或用户停止它。

一个智能体拥有一套固定的可用工具;目前,你可以把工具看作是一个API(稍后会详细说明)。每次LLM给出一些指令作为响应时,智能体的工作就是接收这个响应,并为工具的执行做准备。智能体可能会在执行工具前请求用户的确认。工具执行完毕后,智能体的工作是更新将要输入给LLM的内容,以进行下一个回合。

Fig2

这些就是作为AI智能体开发者,你需要负责构建的部分:

  • 一个提示词(prompt),它会引导LLM启动智能体的工作。

  • 一个可供智能体调用的工具库。

  • 一种将LLM的决策转化为具体工具执行的机制。

  • 一种在循环的每个回合更新LLM输入内容的机制。

然后你需要把所有这些部分组合起来,因此你还需要:

  • 一个能够持久化(durably)实现事件循环的应用。持久化事件循环是指,即使应用崩溃,它也能从上次中断的地方恢复。

  • 最后,一个能够持久化地调用LLM和工具的方法。持久化调用意味着,即使面对间歇性网络和服务器中断、LLM请求限流等问题,调用也能成功。

这,就是我所说的AI智能体心智模型。

在这篇文章的其余部分,我将更详细地介绍列表中的每一项。

大语言模型与工具的语言

现在,你可能已经了解大语言模型(LLM)的基本工作原理:它接收一些内容作为一串词元(tokens),然后输出内容,通常也是一串词元。输出的词元是根据模型训练时所用的海量内容(比如整个互联网上的内容)来确定的。模型的训练过程与我们在此的讨论无关,但输入和输出的“语言”是关键。

举几个场景:

  • 自然语言作为输入,自然语言作为输出——比如,获取会议纪要的摘要。

  • 自然语言作为输入,图像作为输出——比如,生成你最新的猫咪表情包 😸

  • 自然语言加代码作为输入,代码作为输出——比如,让Claude Code、Github Copilot、Codex 或 Cursor 更新代码库。

也就是说,LLM的接口就是输入和输出的语言。作为AI智能体开发者,你可以决定这个接口是什么。最常见的情况是,输入至少会包含一些自然语言,来表达智能体要完成的目标 ← 记住这一点,稍后会用到。

现在,我们来看看工具的接口。

一个工具最终会转化为对某个服务的调用,这个服务具有严格定义的输入和输出,通常通过 OpenAPI、GraphQL SDL 或 gRPC 的 Protobuf 等规范来描述。但前面我提到,事情不止于此——这完全取决于“语言”。

为了让LLM决定应该执行哪些工具以及以何种顺序执行,它必须有一种方法将构成目标的词语与正确的工具关联起来。这通过将一套词语与每个工具关联来实现——具体来说,每个工具都将拥有其功能的自然语言描述,包括:

  • 工具的总体功能——例如,一个可以搜索有空座航班的服务。

  • 每个输入参数的含义——例如,出发地、到达地和旅行日期。

  • 每个输出参数的含义——例如,航班号和价格。

模型上下文协议(Model Context Protocol)(MCP)已经成为工具规范的事实标准。

Fig3

目标描述应该非常详细,并且使用户可以很容易地将它与可用的工具集关联起来。虽然LLM非常擅长处理同义词和不同的措辞——这确实是智能体系统相比过去那种死板的、基于表单的数字体验的一大优势——但你的目标语言与工具描述的语言越接近,结果可能就越好。

为了启动智能体循环,目标、工具描述和一些额外的上下文(我稍后会更详细地介绍)会被输入到LLM中,LLM会返回一个输出,指示要调用哪个工具。

现在,我们来讨论如何处理这个输出,并为工具调用做准备。

为工具调用做准备

我们来看一个具体的例子。假设目标是搜索航班、预订一个,然后向用户收费。通过精心编写的目标描述,LLM会在被调用后决定,智能体要做的第一件事是使用航班搜索工具来搜索相关航班。该工具需要出发地、目的地和旅行日期等参数。因此,在运行工具之前,智能体必须收集这些参数,并以一种工具能够以正确的值调用的方式进行组织。智能体负责为调用工具做准备。

智能体进行这种准备的方式可能有所不同。如果需要,比如在上面的例子中,它可以向用户展示一个表单,让他们提供必要的信息,或者它可以和用户进行聊天来获取数据;后者在下面的图中有所体现。

Fig4

图的左下角描绘了主事件循环,但你可以看到另一个循环,用于为工具执行做准备。在这个次级循环中,左侧的LLM用于生成给用户的提示,引导他们提供所需的输入,而右侧的LLM(嗯,这看起来我用的工具也像是个LLM!!👀)则用于验证用户的响应。需要明确的是,这种智能体结构并非强制性——你可以决定你的智能体结构——但我发现将主事件循环的心智模型作为框架,有助于我更好地组织智能体。

一旦收集到所有输入,API就会被调用,而数据必须被结构化。还有什么比LLM更好的方式,能把非结构化数据(“我想4月16号从LAX去多伦多”)转化为结构化形式({ “departure” : “LAX”, “destination” : “YYZ”, “date” : “2025-04-16” })呢?你可以通过向LLM提供额外的指令来做到这一点。

例如,右上角的循环会包含一些指令,可能会说“一旦你收集到当前工具所需的所有输入,就将它们结构化为JSON,使用你在工具描述中找到的参数名。”还记得我前面留下的伏笔吗?我说LLM除了目标和工具描述之外,还会接收额外的上下文。这正是一个完美的例子。作为智能体开发者,你应该让LLM为你做大量工作,你提供的指令和上下文越多,效果就越好。

说到为LLM提供数据,现在让我们把注意力转向事件循环的下半部分,在那里我们将评估工具执行后的状态,并为LLM的下一个回合准备输入。

更新LLM输入

你可能已经注意到,我们越深入这篇文章,我谈论提示词就越多。事实上,提示工程(prompt engineering)是AI智能体开发者的主要工作之一。我发现,将LLM的输入看作包含以下几个数据块会很有帮助:

  • 目标(The goal)——这提供了智能体功能的总体描述;它应该非常详细,并且以一种能让LLM在可用工具的上下文中做出决定的方式来表达。

  • 工具(The tools)——将用于实现目标的API,以及其功能、输入和输出的自然语言描述。

  • 对话示例(Example conversation)——这展示了理想的互动是什么样的。

  • 上下文指令(Context instructions)——指导LLM输出的额外指令,例如提供输出格式或输入验证指令。

  • 对话历史(Conversation history)——记录了用户与智能体之间的对话;LLM在多次调用中不会保留任何状态,因此由智能体来跟踪对话。

我前面已经谈到如何用“目标”和“工具”来启动事件循环,虽然我在这里将“对话示例”单独列出,但它也可以被看作是目标的详细组成部分;这些部分应该在启动时就包含在内,并贯穿事件循环的所有迭代。

当你更新LLM的后续回合输入时,你将主要处理“上下文指令”和“对话历史”。后者非常简单——你将把问给用户的问题(当然,这是LLM生成的)和用户的回答都附加到对话历史中。

上下文指令会根据工具执行的结果和一些额外的指令进行更新,这使得LLM能够评估目标的进展并选择下一步。我最喜欢的一个例子是,当编程智能体对源代码进行了一些更改后,上下文指令必须更新以反映这些源文件的新状态。这样想是不是很酷?

Fig5

好了,我们已经涵盖了所有的组成部分,现在让我们把它们组合在一起。

组合所有部分

再来回顾一下这些组成部分:

  • 目标和工具,用能够让LLM在正确的时间利用正确工具的语言来表达。

  • 遵循LLM指令,为工具调用做准备的机制。

  • 根据工具调用后世界的新状态,更新LLM输入的机制。

当然,我们还需要智能体来调用LLM和工具。

这对我来说听起来像是个编排(orchestration)问题,如下图所示:

Fig6

这只是一个应用,你可以用你喜欢的任何编程语言来编写。Python?TypeScript?Java?Golang?.NET?Ruby?甚至是PHP?随便挑!

我要提醒你注意两件需要特别关注的事情。

首先,请注意LLM和工具的调用都是外部调用,你当然知道这里可能会出各种问题。LLM的限流可能导致调用失败,即使只是间歇性的。网络可能会不稳定。甚至工具API本身也可能失败。但在我们所处的云原生时代,你的应用应该能够弹性地应对这些类型的故障。你需要确保这些外部调用具有持久性(durability)。

其次,AI智能体应用本身——也就是上图流程中描绘的部分——可能会崩溃,但你希望你的应用能够在像Kubernetes这样的系统重新启动它之后,能从中断的地方继续工作。换句话说,你需要确保AI智能体本身的持久性。这意味着我们必须保存智能体的状态,并知道当崩溃发生时,智能体究竟在哪里。

好了,这就是我的AI智能体心智模型的详细内容。

核心要点

正如我所暗示的,我正在构建一些智能体,既是为了探索各种想法,也是为了在AI背景下演示一些Temporal的能力。这项工作不仅促使我形成了刚刚介绍的心智模型,也让我对AI智能体开发的三个要素有了更深的体会。

第一,是提示工程(prompt engineering)。提示工程是ChatGPT发布后最早出现的AI编程技术之一。还记得那些关于“单次提示”(one-shot)和“少量提示”(few-shot)的讨论吗?(你能相信那只是4-5年前的事吗?!)虽然这个开发领域持续演进,并包含了像思维链(chain-of-thought)和思维树(tree-of-thoughts)这样的概念,但现在,当机器人而不仅仅是人类在进行提示时,“提示工程”这门“科学”变得更加重要。提示词是智能体工作方式的核心,我们看到像MCP这样的标准正围绕它们出现。

第二,我知道自己对于构建智能体的最佳语言问题的立场了。答案是:任何你喜欢的编程语言!尽管智能体的大部分实现都包含在提示词中(目标、工具、上下文指令等),但你仍然需要一个驱动整个流程的引擎。虽然我建议我在这里提出的心智模型是一个很好的设计框架,但事件循环各个部分的具体实现将因情况而异。例如,在调用工具之前,你可能需要包含安全性和合规性检查。你需要对这些逻辑有完全的控制权,而用一种通用编程语言来做这件事是最好的方式。简单来说,你需要灵活性。

最后,确保这些智能体系统的持久性(durability)是绝对关键的。在过去10-15年中占据主导地位的分布式、云原生应用已经证明,需要一系列模式(如重试和外部化状态)来在固有的不可靠基础设施上提供可靠的应用。AI智能体应用将这一挑战提升到了一个新水平,它能轻松地将对LLM和工具的下游调用数量增加一个数量级。有关更多细节,请查看这个短视频

借此,我邀请你来看看我在文章开头提到的那个AI智能体示例。这里还有一个Steve演示它的短视频

我也很想听听你的意见。最好的方式之一,就是在Temporal的社区 Slack 上找到我——我是那里唯一一个叫 Cornelia Davis 的人!🙂

查看我们的Cookie政策

我们使用Cookie和类似技术来帮助个性化内容、定制和衡量广告,并提供更好的体验。点击“接受”即表示您同意我们的Cookie政策中的规定。


原文链接: https://temporal.io/blog/a-mental-model-for-agentic-ai-applications