Agent Factory:大规模构建一致的Agent
I’m ready to translate the article, but I need the full text you’d like translated. Could you please paste the content (excluding the source link you already provided) here? Once I have the article text, I’ll translate it into Simplified Chinese while preserving all formatting, markdown, and code blocks.
无处不在的代理——扩展问题
将 相同的代理 部署到多个活动、客户或产品线比看起来要困难得多。
- 如何保证每个实例都有正确的配置?
- 当某些内容得到改进时,如何在不手动编辑每个代理的情况下传播更改?
我在将一次会议演示扩展到多个活动时开发了 Agent Factory 模式。本文解释了该模式,并展示了如何将其应用于任何需要在多个上下文中一致部署代理的项目。
代理到底是什么?
剥离 API 表层后,每个代理都是由 三部分 构成:
| 部分 | 描述 |
|---|---|
| 模型 | LLM 提供商和模型名称——推理引擎。决定响应质量、上下文窗口以及每次查询的成本。 |
| 工具 | 代理能够执行的操作。对于基于 Algolia 的代理,这通常是指向一个或多个索引的 algolia_search_index 工具。索引描述不仅是元数据——模型会读取它们以了解每个索引包含的内容以及何时查询。 |
| 提示词 | 形塑代理行为的系统指令:角色、语气、约束,以及 如何使用其工具。领域知识就存放在这里。 |
在大多数代理框架中,这三部分在创建时 一次性配置。这使得代理可预测且易审计,但也意味着当你需要在多个上下文中提供相同的代理体验时,每个上下文都需要一个正确配置的实例。手动管理显然无法扩展。
真实案例:宝可梦卡片自动售货机
我使用 Algolia 的 Agent Studio 构建了一个宝可梦卡片自动售货机的演示,供 Algolia 会议展位使用。参与者与 AI 代理聊天,以:
- 查找卡片
- 查看价值
- 领取他们收到的卡片
代理通过类似 MCP 的工具从可搜索索引中获取所有数据。
每个会议都有一台全新的机器,装载该活动的卡片,因此 三条腿都必须适配:
- 工具 – 必须指向该活动的索引(例如
shoptalk-2026,而不是etail-palm-springs-2026)。 - 提示词 – 必须引用正确的活动名称、展位号和上下文。
- 模型 – 可能会根据成本或活动而更换(例如在 AWS 活动中避免使用 Gemini)。
这三部分都可能因活动而异。如何在 不手动操作 的情况下为每个活动生成一个正确配置的代理?
为什么不能使用单一共享代理?
一个拥有所有活动索引访问权限的单一共享代理听起来很方便,但代理是 静态 的。共享代理无法知道自己正在服务哪个活动,因此只能:
- 无差别 地搜索所有内容,或
- 需要设置难以可靠执行的防护栏。
因此,每个活动一个代理 是提供正确上下文的唯一方式。挑战在于保持它们 一致。
代理工厂模式
将 代理创建 视为可重复的过程:
- 将三条腿定义为模板。
- 对每个新上下文 一起渲染它们。
- 注册生成的代理 ID。
- 统一管理整支代理队伍。
下面的概念图展示了流程:
[Template Store] → render (event variables) → [Agent Studio API] → create agent
↓
return agent_id
↓
store agent_id in registry核心洞见
模型、工具和提示 并非独立——它们引用同一个上下文。工具配置中的索引名称必须与提示中告知代理的搜索目标相匹配。将它们 分开渲染 会导致不一致。
基于模板的配置
由于 Agent Studio 提供了用于代理创建的 API,我们将所有内容存为模板,使用共享的占位符变量,并在一次渲染中 一起渲染三条腿。
agent-config.json
{
"name": "Demo Agent — {{event_name}}",
"provider": "your-llm-provider",
"model": "your-model",
"instructions": "PROMPT.md",
"tools": [
{
"type": "algolia_index_search",
"index": "catalog_{{event_id}}",
"description": "Product catalog for the {{event_name}} event."
}
]
}PROMPT.md(摘录)
You are an agent at {{event_name}} (booth {{booth}}).
Use Algolia search to help attendees find cards in the vending machine.{{event_id}}、{{event_name}}和{{booth}}会 在两个文件中一起解析。- 缺失或不匹配的变量会在 任何 API 调用之前 导致失败。
- 当提示改进或工具配置变更时,两者会 原子化 更新。
存储代理 ID
Agent Studio 将每个代理作为受管端点托管,并在创建时返回一个 唯一 ID。你的应用在运行时使用该 ID 加载相应的代理,但该 ID 事先不可预测——必须将其 存储 在可访问的位置(例如数据库、配置文件或其他 Algolia 索引)。工厂会把每个返回的 agent_id 写回 事件注册表,完成创建与运行时之间的闭环。
完整生命周期管理
Agent 的创建仅是起点。当提示词发生变化、新模型发布,或某个活动退役时,工厂会处理更新和删除。
# New event
python agent.py create shoptalk-2026 "Shoptalk 2026" 701 --publish
# Prompt improvement — preview then push to all existing agents
python agent.py update --all --dry-run
python agent.py update --all --publish
# Retire an event
python agent.py delete etail-palm-springs-2026update --all是工厂的核心动力。一次命令即可对 每个 拥有 Agent 的活动重新渲染当前模板。一次提示词改进或工具修复就能变成 一条命令,而不必进行 N 次容易出错的仪表盘编辑。
基于文件的版本控制设置的优势
- 历史 – 完整的审计追踪,记录了更改的内容及原因。
- 回滚 – 能够恢复出现回退的提示。
- 清晰度 – 清晰记录生成每个代理的确切配置。
将提示和配置存为文件,使您能够获得 Git(或任何版本控制系统)的所有优势,同时保持部署过程的确定性和可重复性。
TL;DR
- 代理 = 模型 + 工具 + 提示。
- 当需要多个代理时,将这三部分一起模板化。
- 根据上下文渲染模板,通过 API 创建代理,并 存储返回的 ID。
- 使用一个小型 CLI(Agent Factory)来 批量创建、更新和删除 代理。
使用此模式,您可以从单个演示扩展到数十个事件——或任何其他多租户场景——同时保持每个代理 一致、可审计且易于演进。
大规模管理代理更新
在任何时候运行代理都可以让您比较模型升级前后的行为,以审查提示更改的方式审查代码更改,并推断到底是什么真正改进了效果。
这在当前代理领域快速发展时尤为有用——模型能力提升,出现了更好的提示模式,工具本身也在演进。当您通过仪表板管理代理时,这种纪律很容易被忽视。
工厂模式拆分
随着工厂的成熟,代码中出现了明显的拆分:
| 层 | 职责 |
|---|---|
| 通用 | 对 Agent Studio 的 HTTP 调用、提供者解析、渲染模板、更新差异比较、发布、删除。这些都不涉及宝可梦卡片或会议事件。 |
| 特定领域 | 验证事件是否存在于事件注册表中、根据事件 ID 构建索引名称、将 agent_id 写回注册表。所有这些都是演示特有的。 |
这种拆分就是代码中所体现的模式。我将通用层提取为一个独立的开源 CLI —— algolia-agent —— 并创建了一个轻量的演示包装器,调用该 CLI 的 API,并仅包含其领域内的三项独特内容。
Source: …
algolia-agent CLI
CLI 让工厂模式对任何项目都可用:
algolia-agent init # 交互式定义代理的三个部分
algolia-agent create # 渲染模板并调用 API
algolia-agent update # 对已有代理进行差异比较并推送更改
algolia-agent publish # 将草稿提升为正式版本init 工作流
init 命令按顺序引导完成定义:
- 选择提供商和模型
- 选择工具(或不选——仅使用模型和提示的代理也是有效的)
- 编写提示
Source: …
实际案例提示修复
展位上的一位用户问:
“你们有价值超过 50 美元的卡片吗?”
最初的提示没有对数值过滤提供指导。代理将 “cards worth more than 50 dollars” 作为关键词查询进行搜索。它得到了结果,但并不是正确的结果——关键词搜索匹配了卡片描述中出现 “worth” 一词的条目,而不是按实际价值过滤的卡片。
修复方法
在提示中添加一行:
对于数值字段的 “more than” / “less than” 问题,使用
searchParams过滤器中的比较运算符,而不是使用 facets。
示例:
{
"searchParams": {
"filters": "estimated_value > 50"
}
}添加此行后,代理能够将问题正确转换为对 estimated_value 属性的过滤,只返回实际价格高于 50 美元的卡片。
因为我在多个活动中同时运行代理,执行一次 algolia-agent update --all 就把改进推送到所有实例。下一次会议的代理比上一次会议的代理更好,而无需单独对每个实例进行操作。这正是将提示视为可版本化的工件、将代理 fleet 视为整体来管理的收益。
安全网
管理多个代理的最大难点不在于创建它们,而在于事后保持它们的一致性。在对整个代理群体推送任何更改之前,你需要预览到底会有哪些变化:
- 提示词的变化
- 哪些工具被添加或移除
- 模型是否有变更
一次错误的更改如果被推送到 N 个代理,调试难度将是 N 倍,而在部署前捕获则要容易得多。在我的 CLI 中,我加入了 --dry-run 标志,以在调用 API 之前显示将要更改的差异。
要点
- Agent anatomy: 三条腿——模型、工具集和提示。
- Separation of concerns: 核心代理配置 与 事件特定上下文 的分离。
- Factory pattern: 搭建代理定义的框架,根据上下文渲染,并在每个实例上执行一致的 CRUD 操作。
- One‑command propagation: 当有改进——更好的提示、模型升级、工具修复——只需一条指令即可一次性更新所有代理。
随意自行尝试我的 algolia-agent。我也很想了解该工厂模式对你是否有用,或者如何改进!