跳到正文
LangChain Blog·· 20 天前精选AI 评分60

LangChain 如何构建付费媒体智能体

How We Built LangChain’s Paid Media Agent

AI 导读

LangChain 公开其付费媒体智能体的构建方法,并已开源该智能体,包含广告平台工具、付费媒体技能、示例 wiki、报告与审批流程。该智能体运行在 Slack 中,每周一汇总各广告平台数据并生成报告,团队可在会话中追问或提出关键词、定向与广告文案调整。文中给出关键结果:付费媒体在六个月内从贡献 0 提升到营销管道的 20%,6 月至 8 月单条合格线索成本下降 30%,月度支出增长约 60%。

推荐理由

LangChain 公开付费媒体智能体的完整工程拆解,含上下文分层、工具发现与权限审批等可迁移设计。

正文 · AI 翻译

在 LangChain 的前三年,我们的销售管道主要依靠开源、内容、YouTube、社区和线下聚会实现自然增长。今年一月,我们希望启动付费广告计划,以触达自然渠道无法覆盖的潜在客户,例如新地区和企业的决策者。

我们希望在短短六个月内,从主要依靠自然增长的引擎扩展到五个付费渠道。这给我们规模不大的营销团队带来了新的挑战。我们必须跟踪跨渠道上线的新广告系列、不同的创意和定向实验,以及不断增长、需要理解和采取行动的绩效数据。

为了扩展和优化,我们需要克服一些技术障碍。每个广告平台都有自己的数据模式,导致跨渠道的绩效难以统一比对。广告系列参数也无法清晰地映射到我们最终关心的结果,例如销售咨询、注册或内容下载。随着公司产品发布节奏加快、广告系列数量增长,手动跟踪哪些在运行、哪些有效、下一步该尝试什么,变得越来越难以管理。

我们着手构建一个智能体来帮助管理这种复杂性。它会跟踪新产品发布、起草广告系列、添加关键词、测试变体,并向团队提交建议的实验以供审批。随着时间推移,它将作为一个持续学习的循环运行:分析绩效、做出更改、观察结果、记录所学,并将这些洞察应用于未来的广告系列。我们的目标是提高营销团队的生产力,同时持续改善广告系列绩效。

在本文中,你将了解我们的付费媒体智能体如何工作、如何支持营销团队,以及我们在构建它时对智能体工程学到了什么。

我们已开源了我们的付费媒体智能体,你可以将其作为自己项目的起点。你也可以参加 9 月 23 日太平洋时间上午 11 点的GTM Engineering Live:我们如何构建付费媒体智能体。在本次网络研讨会中,我们将演示该智能体,讲解代码和设计决策,并回答关于如何将这些模式应用到你自己智能体的问题。

关键成果

  • 付费媒体在六个月内从贡献 0% 增长到我们营销管道的 20%。
  • 从六月到八月,合格线索成本(CPL)下降了 30%,而月度支出增长了约 60%。在 LinkedIn——我们最大的社交渠道上,CPL 比一月时低了 40%。 
  • 通过将分析和报告工作内部化,而不是依赖代理机构,我们每月节省了约 5 千美元。
  • 我们还通过将计算移入代码并移除不必要的模型调用,优化了智能体本身,使一个早期报告工作流成本降低约 40 倍、速度提升 13 倍,运行时间从 18 分钟降至 85 秒。

我们构建了什么

付费媒体智能体是一个长期运行的智能体,驻留在 Slack 中。每周一,它会将广告平台数据与来自我们数据仓库的线索和管道数据结合起来。它会为每个平台发布一份摘要和一份品牌化 PDF,说明发生了什么变化、为什么变化,以及团队下一步应该做什么。

团队可以在话题中标记它,询问有关广告系列、成本或管道的后续问题。它还可以根据我们的操作手册和编码化的判断,提出新的关键词、定向调整、广告文案或新的搜索广告系列。

我们如何构建它

我们围绕一个简单的原则构建了这个 agent:编码 agent 就是一名知识工作者。

知识工作通常涉及读取文件、转换信息、运行分析和记录内容。编码 agent 也会借助文件和 shell 完成这些任务。

我们把这个 agent 当作一名新入职的付费媒体分析师。我们给它一台电脑、完成工作所需的软件、对我们数据的访问权限,以及关于我们业务如何运作的文档。

操作系统

我们使用 LangChain Deep Agents 作为 agent harness,这样就不必从零开始构建核心 agent 基础设施。就像操作系统一样,Deep Agents 管理对文件、代码执行和工作记忆的访问。它为模型提供工具来规划工作、将任务委派给子 agent,并在任务变得复杂时管理上下文。这个基础就是 agent harness。我们在其上叠加付费媒体工具、技能和业务知识。

计算机

每次运行默认都有一个 LangSmith Sandbox 可用。它是一个隔离的 microVM,拥有 32 GB 磁盘和一个用于运行命令的 shell。该沙箱为 agent 提供了一个安全、隔离的环境来执行代码和处理文件,而不会影响其他运行或底层系统。

我们为它配备了 pandas 和 DuckDB 用于分析,openpyxl 用于电子表格,以及 WeasyPrint 和 Jinja2 用于生成报告。除了这些软件之外,还有它的工作数据和业务知识,以 Markdown 格式存储在六项技能和一个十九页的 wiki 中。

为了保持快速启动,我们将软件和业务 wiki 烘焙进一个快照,即沙箱启动时所用的已保存镜像。这将平均启动时间缩短了 10 秒。

 💡 不同的 agent 需要不同的计算机。我们的内容生成 agent 的沙箱更像一台视频编辑工作站,配有 headless 浏览器、ffmpeg、媒体工具和品牌手册。财务 agent 可能需要 openpyxl 处理电子表格,以及 DuckDB 进行更繁重的数据处理。工作内容决定了你如何设计这台计算机。

提供正确的上下文

一旦 agent 有了计算机,下一个挑战就是给它正确的上下文。人类分析师需要理解自己的角色、所使用的方法、所服务的公司、当前正在发生的事情,以及需要遵循的规则。

最朴素的做法是把所有这些都放进系统提示词中。然而,这会导致提示词过长、每次运行都携带成本高昂,而且很可能过时。

更好的思路是:上下文窗口往往是瓶颈,而不是模型。许多看似推理失败的情况实际上是上下文失败。要么模型缺少正确的信息,要么太多无关信息在争夺它的注意力。

我们不把提示词当作知识存放的地方,而是把它当作一张地图。知识存放在位置可预测的结构化文件中,agent 只加载当前任务所需的上下文。

 💡 你设计 agent 工作区的方式,值得像你为它提供的工具一样认真思考。我们发现,agent 能够通过组合桌面上已有的内容,回答我们从未构建过明确工作流的问题。它有指导调查的 playbook、可供使用的 campaign 数据,以及用于分析的库。设计这个工作区,成为了设计 agent 本身的一部分。

我们将上下文分为五层,下面逐一描述(按每层变化的速度排序):

  • 系统提示:定义智能体的角色和导航方式。我们的提示以一句话描述智能体的角色开头,随后是三个简短部分:如何操作、数字从何而来,以及如何呈现结果。其余内容都是给智能体的指引,例如:操作手册在这里,wiki 在那里,先读索引。提示告诉智能体在哪里找到它需要的东西。
  • 技能:六个指令文件夹,在运行时逐步披露。智能体最初只能看到每个文件夹的标题和描述。
  • Wiki:十九个页面,解释我们的漏斗如何运作、每个营销活动旨在达成什么目标、哪个数据源拥有哪个数字,以及团队做出了哪些决策及其原因。
  • 实时工具:支出、设置和管道每天都在变化,因此智能体在请求时实时获取。我们有 218 个此类调用。关于如何避免这些调用使上下文膨胀,详见下文。
  • 确定性代码:任何应当保持一致且可复现的内容,我们都用代码实现,包括计算、日期窗口、账户匹配和硬性保障措施。例如,有一条规则防止智能体在一次表现不佳的一周后就砍掉一个顶级管道驱动因素,这条规则在代码中强制执行,因此模型无法覆盖它。最难划清的界限是技能和 wiki 之间。技能解释如何完成工作:读取数据、运行数字、撰写报告、准备变更,以及应用解读付费媒体表现的操作手册。它不包含任何针对我们营销活动的具体内容。

Wiki 则是所有针对 LangChain 的具体内容:哪个营销活动用于品牌认知,哪个应该驱动演示请求,我们在七月决定了什么,以及为什么。

 💡 技能应该‘在另一家公司也能用’,而 wiki 则不应该。换句话说,技能捕捉的是可复用的工作方式,而 wiki 包含这些技能运作所需的公司特定上下文。

这遵循了 Karpathy 的 LLM wiki 笔记以及我们自己的 Wiki Memory 中的模式。

统一智能体架构

我们最初构建了两个智能体图,因为用户体验看起来不同:

  • 周报智能体是定时运行的,且产出物繁重。它使用 Deep Agent、沙箱、大模型和 PDF 生成。
  • Slack 需要在几秒内给出答案,因此它在更便宜的模型上使用轻量级循环,配备 Google Ads 和仓库工具,没有沙箱,且为只读访问。

这种拆分只持续了五周。每项新能力都必须实现两次。功能到达 Slack 和报告的时间不同。Slack 无法处理附件,因为它没有沙箱,也无法回答关于周一报告的后续问题,因为那些 PDF 来自另一个图。

错误在于把它们当成了两个产品。它们是同一分析的两个入口,背后是同一个 wiki、技能、工具和来源规则。我们改为为每个请求隔离状态和能力。每个线程都有自己的沙箱和检查点,每次运行只看到它需要的工具。

现在只有一个图,为每个请求全新实例化:

  • Slack 提及和周一 cron 以不同的运行模式进入。
  • 定时运行只看到一个工具 task(),它按平台委托给一个子智能体。
  • Slack 获得更广泛的读取、仓库和营销活动操作工具。

它与不同的能力配置文件运行在同一个运行时上,托管在 LangSmith Deployment 上,由后者负责托管、扩缩容和定时运行。而且由于 Slack 现在共享相同的沙箱架构,智能体还可以打开报告 PDF,并在生成该报告的线程中回答后续问题。

 💡 要点:为每个入口点使用一个运行时并配置相应的能力配置文件。同一个工厂可以为不同用户提供不同的技能和权限。

关键技术经验

让智能体投入实际工作,教会了我们五条关于把数字做对、回答我们未曾预料到的问题,以及将分析转化为行动的经验。

1. 用模型做判断,而不是做计算

我们第一版的每周分析让模型包办一切。我们把每一行广告活动数据、关键词、销售管道记录和落地页检查都加载到上下文中,然后让它计算支出、周环比变化、对广告活动表现进行分类,并撰写报告。

它确实能跑通,但效率低下。在我们的冻结测试集上,单份报告处理了约 390 万个输入 token,因为模型必须读取所有这些原始数据,并反复自行完成计算。这使得每次运行都更慢、更昂贵,耗时 1,112 秒,成本略高于 3 美元。这也让结果更难被信任,因为模型每次都要负责重新计算底层数字。

我们发现代码更适合做确定性的工作。现在由 Python 获取数据、对齐日期窗口、计算总计和对比、应用固定规则,并将一组紧凑的结果写入沙箱。然后模型专注于需要判断力的工作:串联证据、解释可能的原因、对照目标评估广告活动,并建议下一步该做什么。

2. 为每个指标定义唯一可信来源

我们有六个平台,它们的 ID、转化定义、归因窗口和广告活动层级各不相同。试图把所有内容归一化成一个完美的 schema,只会增加复杂性,却未必能让数据更可信。

相反,我们定义了每类指标应该信任哪个系统。广告平台是媒体活动(如支出、展示次数和点击次数)的可信来源。一旦有人完成转化,我们就依赖我们的数据仓库来获取下游结果,例如线索、商机和销售管道。

当一些 Google 视频广告活动无法干净地映射到我们的数据仓库时,我们明白了这一点为何重要。我们的数据仓库使用关键词来关联广告活动数据,但视频广告活动并不总是有关键词。结果,尽管 Google 本身拥有正确的支出数据,我们数据仓库中仍缺失了约 10% 的 Google 支出。Meta 则有相反的局限:它能告诉我们某个广告带来了转化,但我们的数据仓库更擅长告诉我们那个转化究竟是什么,比如是“联系销售”请求还是“注册”。这些例子进一步印证了为什么我们不应指望一个系统对每个指标都给出最佳答案。

我们把这些可信来源规则编码进了智能体。它们存放在 wiki 中,并且我们会移除那些会让智能体针对给定指标查询错误系统的工具。有了来源边界、转化映射和广告活动层级的定义,智能体就可以跨平台工作,而无需一个完美归一化的 schema。

当数据无法可靠地关联时,智能体不会试图填补这些空白。它会保留这些局限,并在回答中附上相关来源、日期窗口和归因模型,以便团队了解每个数字是如何得出的。

 💡 要点:你不需要先有一个完美的数据模型,智能体才能跨系统工作。更重要的是定义每个指标以哪个来源为准,把这些规则明确下来,并在底层数据无法干净地对账时保留不确定性。

3. 让智能体自行发现工具,而不是预先加载所有内容

回答诸如“我们的广告支出带来了哪些销售管道?”这样的问题需要访问两个系统。广告平台提供支出和点击数据,而我们的 BigQuery 数据仓库将广告活动与网站转化同合格线索、Salesforce 商机和销售管道关联起来。

我们希望智能体能同时跨这两个系统工作,而无需加载数百个工具定义,也不必为每个问题编写新工具。

Pipeboard 的 MCP 暴露了 200 多个广告平台工具。早在 6 月,即便是我们较小的只读目录,也需要 38,000 个 token 才能加载可用的工具名称、描述和参数,而这还是在智能体读取用户问题之前。这些上下文大部分与任何单个请求都无关。

我们的数据仓库也有类似的问题。我们为诸如按广告活动查看销售管道或按广告组查看转化等重复性问题构建了固定查询。但每一种新的数据分组方式,比如按单个销售商机查看销售管道,都需要另一个专用工具。

我们通过给智能体一个用于查找所需内容的小型接口,解决了这两个问题。

Pipeboard 的目录由三个工具支撑:

  1. 搜索:根据问题找到最多八个工具。
  2. 读取:仅为所选工具加载完整 schema。
  3. 运行:通过我们的服务器执行该工具。广告活动写入使用单独的需审批路径。

对于数据仓库,我们添加了两个灵活的工具:

  1. 描述可用的表和字段。
  2. 运行分析查询。

智能体可以检查 schema 并组合出问题所需的查询,而不必依赖为每种可能的分组预先构建的工具。

该目录将首轮交互降至约 12,000 个 token。在我们的对比中,它比加载所有 schema 便宜 4 倍,同时保持了相同的评判质量。此后目录规模几乎增长了两倍,而其上下文成本大致保持稳定。

我们在 60 次实际运行中测试了固定数据仓库工具、查询接口以及两者结合的方式。固定工具对常规问题效果良好,但会正确地将更深层的问题报告为不支持。带有查询接口的两个版本都回答了所有分析性问题。

我们保留了这两种方式。固定工具为常见问题提供快速路径,而查询接口则处理我们未曾预料到的问题。

 💡 要点:给智能体一种按需查找和查询能力的方式,而不是预先将所有工具都放入上下文。

4. 明确设计隔离

在迁移到共享运行时后,我们面临另一个挑战:智能体如何在不将每个平台的数据都放入同一个上下文窗口的情况下分析五个平台?

我们在实际数据上测试了三种架构:

  1. 每个平台一次隔离运行。
  2. 一个智能体处理所有平台。
  3. 一个父智能体委派给每个平台一个子智能体。

独立运行是最简单的架构,但在实际工作流中表现最差。每次运行只能看到一个平台,因此系统会生成多条 Slack 消息,并且难以跨渠道综合绩效表现。

两种整合方案都产出了带有跨平台综合分析的单一输出。我们最终选择了父代理加子代理的架构,因为它让父代理的上下文保持精简,同时为每个平台提供独立的上下文窗口,以容纳平台特定的数据和注意事项。

但独立的上下文窗口并不会自动带来完全隔离。我们仍然需要主动设计隔离机制。

例如:

  • 一个平台可能会意外地抑制另一个平台。两个子代理向同一位置写入报告,并共享同一个“完成”标志。一旦第一个完成,第二个就可能误以为该状态属于自己,从而在没有生成报告的情况下停止。我们通过为每个平台分配各自的报告位置和完成状态解决了这个问题。
  • 子代理可能会陷入验证自身工作的困境。当某个子代理无法确定其 PDF 是否已渲染时,它会不断检查文件,消耗大量 token,最终试图从头构建 PDF。现在子代理只获得三个工具:读取上下文、计算和渲染。如果渲染成功,任务即告完成。

子代理为你提供了一个独立的上下文窗口。隔离模型的其余部分由你自己决定。你仍然需要定义它可以使用哪些工具、可以访问哪些文件和状态、必须返回什么,以及如何处理失败。

5. 为代理提供从分析到行动的路径

一个只分析绩效的代理,最终不过是一个更好的仪表盘。我们希望代理能帮助团队根据其发现采取行动。

它可以直接在 Slack 中提出变更建议,例如添加关键词、更新地理定向或创建新的搜索广告系列。

赋予代理采取行动的能力也带来了新的要求:权限。

付费媒体之外的团队可以使用该代理询问广告系列绩效和销售管道相关的问题,但只有指定的团队成员才能编辑或批准广告系列变更。服务器在接受任一操作前会检查 Slack 用户 ID。来自其他任何人的请求都会被阻止,提案保持待处理状态。

每个提议的变更都会出现在一个使用 Block Kit 构建的 Slack 审批卡片中。获得授权的审核者可以对比当前值和提议值、进行编辑,并批准最终方案。随后代码会应用已批准的变更,并检查广告平台以确认操作成功。

这为我们带来了有用的职责分离。代理可以分析绩效并推荐行动,但由人类控制该行动是否真正被执行。

 💡 要点:闭环需要的不仅仅是写入权限。为代理提供清晰的操作路径,并内置权限、审批和验证机制。

6. 让界面与工作相匹配

Slack 作为第一个界面效果很好,因为审批卡片可以与促成它的分析和讨论存在于同一个线程中。跨团队的人员可以提问并发表意见,而广告系列负责人仍然控制着哪些变更真正被应用。

这种方法最适合相对聚焦的决策。随着代理开始处理更复杂的工作,例如包含许多广告组和创意的广告系列、批量编辑,或需要多轮修订的方案,Slack 作为主要工作空间就变得越来越难用。

我们正在把这些更复杂的工作流迁移到一个围绕 agent 构建的专用界面中,同时保留 Slack 作为一个轻量级的场所,用于提问、查看建议和批准变更。更多内容将在后续文章中介绍。

下一次构建时我们会采纳什么

我们想要一个能够处理我们未曾预料到的问题、产出我们可以验证的数字,并对其发现采取行动的 agent。以下是我们会带入另一个 agent 的设计原则:

  • 像对待新员工一样装备 agent。 给它一个沙箱、有用的库、对正确数据的访问权限,以及清晰的文档。一个设计良好的工作空间能让 agent 无需为每个问题都配备专门的工作流,就能调查新问题。
  • 将可复用的指令与公司知识分开。 技能说明如何完成工作,wiki 说明业务,实时工具提供最新信息。保持这些层次分离,可以让每一层都更容易更新,而不会让系统提示词不断膨胀。
  • 对应当可复现的工作使用代码。 计算、比较和硬性规则应当用代码实现。这样模型就可以专注于解读结果并判断其含义。
  • 明确设计边界。 子 agent 仍然需要清晰的规则,规定它们可以访问哪些工具、文件和状态,应当返回什么,以及如何处理失败。独立的上下文窗口只是隔离的一部分。
  • 以 agent 能否完成任务为优化目标。 减少 token、成本和延迟很重要,但如果这会让 agent 能力下降就不值得。我们发现,将这些指标与完成率和答案质量一起评估更有用。
  • 让真实使用情况告诉你集成需要在哪些方面改进。 agent 反复难以回答的问题,揭示了哪些地方值得构建更清晰的衔接、更好的定义或专门的工具。

下一步

目前,该 agent 主要响应定时运行和团队的请求。我们希望它变得更加主动,通过持续监控广告活动表现、呈现值得关注的变更,并提出新的实验和优化建议供团队审阅。

更大的机会在于将这些经验贯穿 GTM 连接起来。广告活动的互动情况可以为销售如何跟进提供参考,而销售管道的推进、销售对话和成交结果可以加深我们对理想客户的理解,并影响下一次广告活动。

随着时间的推移,我们希望我们的 GTM agent 能够为同一套共享知识和操作手册做出贡献,这样组织某一部分学到的东西就能改善漏斗其余部分的定向、信息和实验。

基于我们所学进行构建

参加 GTM Engineering Live:我们如何构建我们的付费媒体 agent,时间是太平洋时间 9 月 23 日上午 11 点。在本次网络研讨会中,我们将演示该 agent,讲解代码和设计决策,并回答关于如何将这些模式应用到你自己 agent 的问题。

你也可以将这个付费媒体 agent 带到你自己的团队中。我们已将其开源,包括广告平台工具、付费媒体技能、示例 wiki、报告和审批工作流。连接你的账户,提供你公司的上下文,并使用 Managed Deep Agents 通过一条命令将其部署到 Slack。

‍

来源:LangChain Blog · langchain.com