大家好,我是十三!欢迎来到十三Tech。
上一篇我们探索了 Agent 的"记忆系统"。但一个强大的 Agent 不仅要能"记住",更要能"做到"——它需要与外部世界交互的能力。今天的主角是 Coze 的 plugin 模块,Agent 的"行动系统"。它给出了一个优雅的答案:以 OpenAPI 3.0 为基石,集成多层次认证与智能执行引擎的通用插件架构,一次性解决标准化、安全性和执行力三大挑战。
1. 插件的"契约":基于 OpenAPI 3.0 的标准化设计
Coze 插件体系全面拥抱 OpenAPI 3.0 规范,并将其作为整个系统的通用语言与核心"契约"。无论是官方插件还是用户自定义工具,本质都是一份 OpenAPI 文档——这种选择为系统带来了无与伦比的标准化和扩展性。
插件的"身份证":PluginManifest
每个插件由 PluginManifest(插件清单)定义,描述了一切元信息:
// api/model/crossdomain/plugin/plugin_manifest.go:32-42
type PluginManifest struct {
SchemaVersion string `json:"schema_version"`
NameForModel string `json:"name_for_model"`
NameForHuman string `json:"name_for_human"`
DescriptionForModel string `json:"description_for_model"`
DescriptionForHuman string `json:"description_for_human"`
// 核心:认证配置
Auth *AuthV2 `json:"auth"`
LogoURL string `json:"logo_url"`
// 核心:API 定义类型
API APIDesc `json:"api"`
// 核心:全局参数
CommonParams map[HTTPParamLocation][]*api.CommonParamSchema `json:"common_params"`
}
关键设计点:
- 给谁看:
NameForModel/DescriptionForModel帮助大模型理解插件功能、决定何时调用;NameForHuman/DescriptionForHuman展示给用户。 - 如何认证:
Auth字段定义认证类型,下一节详述。 - 通用参数:
CommonParams定义全局参数,例如在每个请求的 Header 中自动加入User-Agent。
工具的"说明书":ToolInfo 与 OpenAPI Operation
插件中每一个可执行的动作(Tool),其"说明书"就是 OpenAPI 中的 Operation 对象:
// api/model/crossdomain/plugin/toolinfo.go:34-47
type ToolInfo struct {
ID int64
PluginID int64
Name string
Desc string
SubURL *string
Method *string
// 核心:OpenAPI 操作定义
Operation *Openapi3Operation `json:"operation"`
}
type Openapi3Operation = openapi3.Operation
Operation 字段详细描述了 API 的一切:Parameters(参数位置、类型、是否必需)、RequestBody(请求体结构与媒体类型)、Responses(响应码与响应体)。通过这种方式,Coze 把外部世界五花八门的 API 统一到了 OpenAPI 这门"世界语言"之上。
2. 安全的"守卫":深入多层次认证体系
当 Agent 与外部 API 交互时,安全是头等大事。Coze 在 PluginManifest 中通过 AuthV2 字段,设计了一套覆盖绝大多数 API 认证场景的灵活体系:
// api/model/crossdomain/plugin/plugin_manifest.go:44-53
type AuthV2 struct {
Type AuthType `json:"type"`
AuthorizationType AuthorizationType `json:"authorization_type"`
AuthorizationContent map[string]string `json:"authorization_content"`
CredentialLocation CredentialLocation `json:"credential_location"`
CustomHeaders map[string]string `json:"custom_headers"`
CredentialSchema *openapi3.SchemaRef `json:"credential_schema"`
OAuthProvider *OAuthProviderSchema `json:"oauth_provider"`
}
type AuthType string
const (
AuthTypeNone AuthType = "none"
AuthTypeServiceToken AuthType = "service_token" // API Key
AuthTypeOAuth AuthType = "oauth"
)
Type 字段像一个开关,定义了三种截然不同的认证模式。
模式一:AuthTypeNone - 开放的门户
最简单的模式,适用于无需认证的公开 API(天气、资讯、开放数据源)。type=none 时,Coze 调用 API 不附加任何认证信息。零配置,直接调用第三方。
模式二:AuthTypeServiceToken - API Key 认证
最常见的 API 认证方式(Bearer Token / Service Token)。Coze 的设计非常灵活:
AuthorizationType:Key 的类型,通常是bearer或basicCredentialLocation:Key 的位置,header还是queryAuthorizationContent:map[string]string,精确指定 Key-Value 模板,例如{Authorization: "Bearer {{bstudio_api_key}}"}
{{bstudio_api_key}} 是占位符,Coze 在实际请求时将用户为该插件配置的安全凭证动态填充进去。定义(manifest)与凭证(credentials)物理分离,既保证模板通用,又确保敏感信息隔离存储。
模式三:AuthTypeOAuth - 授权的艺术
对于代表用户操作资源的场景(读取用户的 Google Drive、以用户名义发推),OAuth 2.0 授权码模式是事实标准。OAuthProvider 字段定义了完整的第三方配置,Coze 实现了完整流程:
核心步骤:GetOAuthURL 生成授权页 URL → 用户授权 → OAuthCode 用 code 加 client_secret 换 access_token + refresh_token → 安全存储 → access_token 过期时用 refresh_token 自动刷新,对用户和上层应用完全透明。
3. 智能执行引擎:Tool Calling 的实现艺术
认证机制保证了"谁可以调用",执行引擎则决定了"如何调用"。核心问题是:如何将大模型输出的"意图"(Tool Calling 参数),精确转换为可执行的 HTTP 请求?
答案在 ExecuteTool 这一核心领域服务中——它是连接 AI "思维"与现实世界"动作"的桥梁。
// domain/plugin/service/exec_tool.go:25-40
func (p *pluginService) ExecuteTool(ctx context.Context, req *entity.ExecuteToolRequest) (*entity.ExecuteToolResponse, error) {
// 1. 构建工具执行器 - 获取正确的插件和工具版本
toolExecutor, err := p.buildToolExecutor(ctx, req)
if err != nil {
return nil, err
}
// 2. 预处理参数 - 将 LLM 的 JSON 参数转换为结构化对象
arguments, err := p.preprocessArgumentsInJson(ctx, toolExecutor.Tool.Operation, req.Arguments)
if err != nil {
return nil, err
}
// 3. 构建 HTTP 请求 - 将参数映射到具体的 HTTP 请求
httpReq, err := p.buildHTTPRequest(ctx, toolExecutor, arguments)
if err != nil {
return nil, err
}
// 4. 注入认证信息 - 根据插件的认证配置添加凭证
if err := p.injectAuthInfo(ctx, httpReq, toolExecutor); err != nil {
return nil, err
}
// 5. 执行 HTTP 请求并返回结果
return p.executeHTTPRequest(ctx, httpReq)
}
关键步骤拆解
第一步 buildToolExecutor 按场景选择版本:根据 Scene 字段智能选择——SceneDraft 用草稿版(调试)、SceneOnline 用线上版(生产)。开发者可安全测试新功能,不影响线上用户。
第二步 preprocessArgumentsInJson 解析验证 LLM 参数:把 JSON 字符串映射到 OpenAPI Operation 定义的结构。不仅做 JSON 解析,还包括类型验证(确保值符合 Schema)、必填校验(required: true)、默认值填充。
// domain/plugin/service/exec_tool.go:85-120
func (p *pluginService) preprocessArgumentsInJson(ctx context.Context, operation *openapi3.Operation, argumentsJson string) (map[string]interface{}, error) {
var arguments map[string]interface{}
if err := json.Unmarshal([]byte(argumentsJson), &arguments); err != nil {
return nil, fmt.Errorf("invalid arguments JSON: %w", err)
}
for _, param := range operation.Parameters {
paramName := param.Value.Name
if value, exists := arguments[paramName]; exists {
if err := p.validateAndConvertParam(param.Value, value); err != nil {
return nil, fmt.Errorf("parameter %s validation failed: %w", paramName, err)
}
} else if param.Value.Required {
return nil, fmt.Errorf("required parameter %s is missing", paramName)
}
}
return arguments, nil
}
第三步 buildHTTPRequest 精确映射:这是最复杂的一步。通过标准化的参数位置描述(in: path、in: query、in: header),Coze 能机械而精确地把任意参数放置到 HTTP 请求的正确位置——路径参数替换 URL 占位符、查询参数拼到 query string、请求体序列化为 JSON、Header 参数设到请求头。
第四步 injectAuthInfo 安全注入凭证:读取 AuthV2 配置,按类型(None 跳过、ServiceToken 读 API Key、OAuth 读 access_token)将凭证注入到请求的正确位置。占位符 {{bstudio_api_key}} 在此处被替换为真实凭证。配置与实现分离——插件作者只声明"认证应该如何被使用",凭证获取与注入由 Coze 统一处理。
此外,每一步的执行结果都会被详细记录(参数解析错误位置、HTTP 请求详情、第三方响应、认证失败类型),为调试和运维提供强支持。
4. 草稿与线上的双版本哲学
与 memory 模块类似,插件体系同样采用"草稿"(Draft)与"线上"(Online)双版本设计。这不是简单的版本管理,而是对安全部署和持续迭代的深层思考。
实体层面的双版本设计
// domain/plugin/entity/plugin.go:15-25
type PluginInfo struct {
ID int64 `json:"id"`
CreatorID int64 `json:"creator_id"`
Name string `json:"name"`
Description string `json:"description"`
Version PluginVersion `json:"version"` // Draft 或 Online
Status PluginStatus `json:"status"`
Manifest *PluginManifest `json:"manifest"`
// 版本关联
DraftID *int64 `json:"draft_id,omitempty"`
OnlineID *int64 `json:"online_id,omitempty"`
Tools []*ToolInfo `json:"tools,omitempty"`
}
type PluginVersion string
const (
PluginVersionDraft PluginVersion = "draft"
PluginVersionOnline PluginVersion = "online"
)
每个插件物理上存在两份独立记录:草稿版(version="draft",开发测试预览)和线上版(version="online",生产稳定运行)。DraftID 和 OnlineID 建立双向关联,形成"影子版本"架构模式。
发布流程的原子化同步
// application/plugin/plugin.go:150-180
func (p *PluginApplicationService) PublishPlugin(ctx context.Context, req *plugin.PublishPluginRequest) (*plugin.PublishPluginResponse, error) {
// 1. 获取草稿版本插件
draftPlugin, err := p.pluginService.GetPluginByID(ctx, req.DraftPluginID)
if err != nil {
return nil, fmt.Errorf("draft plugin not found: %w", err)
}
if draftPlugin.Version != entity.PluginVersionDraft {
return nil, fmt.Errorf("plugin %d is not a draft version", req.DraftPluginID)
}
// 2. 检查是否已有线上版本
if draftPlugin.OnlineID != nil {
// 更新现有线上版本
return p.updateOnlinePlugin(ctx, draftPlugin)
} else {
// 创建新的线上版本
return p.createOnlinePlugin(ctx, draftPlugin)
}
}
PublishPlugin 的核心逻辑简洁清晰:先 GetPluginByID 取得草稿插件,然后检查 OnlineID 字段——已存在走 updateOnlinePlugin 分支(复制草稿配置到线上),不存在走 createOnlinePlugin 分支(创建新线上记录、回填 OnlineID 到草稿、同步工具定义)。整个流程在事务中,原子化——要么完全成功要么完全回滚。 DraftID 与 OnlineID 的双向指针让版本追溯变得简单。
场景驱动的版本选择策略
回到 §3 的 buildToolExecutor,版本选择逻辑因此清晰:
- 开发者体验:Coze Studio 插件编辑器测试时自动用草稿版
- 用户体验:Agent 在实际对话中调用工具始终用稳定线上版
- 灰度发布:可让特定用户先体验草稿版,验证无误后全量发布
这为 CI/CD 提供了天然支持。
5. 架构层次的优雅流转
完整的 Tool Calling 请求遵循本系列第一篇解析过的 DDD + 整洁架构分层:接口层(api)做 HTTP 适配与转换,应用层(application)编排用例、协调权限检查与日志记录、不含核心业务逻辑,领域层(domain)承载纯粹的执行逻辑(版本选择、参数验证、请求构建、认证注入),基础设施层(infra)处理所有"脏活累活"——数据库查询、HTTP 客户端、缓存连接池、第三方集成,并实现领域层定义的所有接口,但绝不向上"泄露"技术细节。
每一层只依赖接口而非实现,整个系统耦合度降到最低、可测试性达到最高。无论插件体系如何复杂化、认证方式如何扩展、第三方服务如何增加,核心业务逻辑始终保持清晰稳定。
总结
Coze 插件体系展现了三个层面的架构艺术:通过 OpenAPI 3.0 实现标准化,把千变万化的外部 API 统一到一门"世界语言"之上;通过 AuthV2 实现多层次安全保障,配置与实现分离既灵活又安全;通过草稿/线上双版本与场景驱动选择实现安全迭代,让 CI/CD 天然落地。这些设计思想不仅适用于 AI Agent 平台,对任何需要集成第三方 API 的系统都具有重要参考价值。
正如《整洁架构》所言:"好的架构让系统易于理解、易于开发、易于维护、易于部署。" Coze 的插件架构,正是这一理念的完美诠释。
关于十三Tech
资深服务端研发工程师,AI 编程实践者。 专注分享真实的技术实践经验,相信 AI 是程序员的最佳搭档。 希望能和大家一起写出更优雅的代码!
联系方式:569893882@qq.com GitHub:@TriTechAI VX:TriTechAI(备注:十三 Tech)
