插件配置
使用 Cordis Schema 构建强类型配置字典,实现默认值约束、环境变量读取与配置热重载更新。
在构建高弹性的企业级智能体系统时,“严禁硬编码可调参数”(No Hardcoded Tunable Parameters) 是 Harness 架构设计的重要铁律。无论是网络超时时间、并发重试阈值、网关 Endpoint,还是敏感认证密钥,都应当通过声明式配置文件进行统一管理。
DeepSeek Harness 基于 @deepseek-ai/schemastery 构建了强类型的配置代数系统,支持在启动与热重载阶段对 cordis.yml 进行严格的运行时类型推导与自动默认值注入。
本文将以一个 “智能体推理网关与速率熔断插件(Inference Gateway & Rate Limiter)” 为例,系统拆解 Schema 契约定义与敏感信息脱敏实践。
核心范式:双重导出机制与 Standard Schema
在 Cordis 插件体系中,配置项通过 同名双重导出 的方式定义:同时导出一个 TypeScript interface Config 与一个同名的 export const Config: Schema<Config> 运行时对象:
import type { Context } from '@deepseek-ai/cordis';
import Schema from '@deepseek-ai/schemastery';
export const name = 'inference-gateway-plugin';
// 1. 编译期静态类型定义(供 IDE 提供自动补全与类型检查)
export interface Config {
endpoint: string;
maxConcurrency: number;
timeoutMs: number;
enableFallback?: boolean;
}
// 2. 运行时强校验 Schema(负责解析 YAML、注入默认值并阻断非法输入)
export const Config: Schema<Config> = Schema.object({
endpoint: Schema.string().required().description('模型代理网关的基础 URL 接口地址'),
maxConcurrency: Schema.number().default(5).min(1).max(50).description('允许的最大并发请求量'),
timeoutMs: Schema.number().default(15000).description('单次请求超时阈值(毫秒)'),
enableFallback: Schema.boolean().default(true).description('在主通道故障时是否自动启用降级通道')
});
// 3. apply 函数接收经过 Schema 校验并填充了默认值的完整 config 对象
export function apply(ctx: Context, config: Config) {
console.log(`[Gateway] 已连接到网关: ${config.endpoint} (最大并发: ${config.maxConcurrency})`);
}
架构规范警告: 绝不要在
Config中导出普通的 JavaScript 字面量对象。Cordis 微内核要求配置描述必须符合 Standard Schema 规范,以便在微内核启动阶段完成类型收窄与断言。
步骤一:在 cordis.yml 中注入配置
开发者可以在工作区的 cordis.yml(或配置补丁文件中)通过声明式语法注入该插件的参数:
- insert:
- id: gateway-instance
name: './custom-plugins/gateway'
config:
endpoint: 'https://api.deepseek.com/v1'
maxConcurrency: 10
timeoutMs: 20000
enableFallback: false
当 Harness 启动时,微内核会自动加载并比对 YAML 中的键值。对于未在 YAML 中显式提供的字段,Schema 会自动将预设的 default 值填充至 config 中。
步骤二:高级校验与“Fail Loudly 尽早报错”原则
对于涉及生产安全的插件,应充分利用 Schemastery 的复合校验算子,贯彻 Fail Loudly(尽早报错) 原则:
import type { Context } from '@deepseek-ai/cordis';
import Schema from '@deepseek-ai/schemastery';
export const name = 'secure-vault-plugin';
export interface Config {
masterApiKey: string;
environment: 'production' | 'staging' | 'development';
ipWhitelist: string[];
rateLimitPerMinute: number;
}
export const Config: Schema<Config> = Schema.object({
// required() 声明必填;.role('secret') 实现控制台与 Trajectory 轨迹脱敏
masterApiKey: Schema.string().required().role('secret').description('主认证密钥'),
// union 声明枚举范围限制
environment: Schema.union(['production', 'staging', 'development']).default('development').description('运行环境标签'),
// array 声明数组类型
ipWhitelist: Schema.array(Schema.string()).default([]).description('允许访问的受信任 IP 列表'),
// 数值范围硬性约束
rateLimitPerMinute: Schema.number().default(60).min(1).max(600).description('每分钟最大调用频次')
});
export function apply(ctx: Context, config: Config) {
console.log(`[Vault] 环境: ${config.environment}, 限制: ${config.rateLimitPerMinute} req/min`);
}
若用户在配置文件中遗漏了必填的 masterApiKey,或者将 environment 误写为 'testing',Harness 将在 服务初始化阶段立即中断并打印精准的路径报错,绝不将隐患留到运行时。
生产配置管理的四大最佳实践
┌─────────────────────────────────────────────────────────────┐
│ 配置工程化治理核心四原则 │
├───────────────────┬─────────────────────────────────────────┤
│ 1. 严格去除硬编码 │ 超时、并发上限与重试次数全部收拢至配置 │
│ 2. 敏感凭证必脱敏 │ 认证 Key 必须链式追加 .role('secret') │
│ 3. 杜绝非法边界值 │ 使用 .min() / .max() 防止参数溢出 │
│ 4. 动态平滑重载 │ 支持在 Web UI 或 YAML 修改后瞬时热生效 │
└───────────────────┴─────────────────────────────────────────┘
常见问题解答 (FAQ)
Q1: 为什么使用 Schemastery 而不是常规的 TypeScript 类型断言?
解答:TypeScript 的 interface 在编译为 JavaScript 后会被完全擦除,无法在运行时提供任何数据校验;而 Schemastery 既能生成静态 TypeScript 类型,又能在运行时执行深度的类型检查与默认值注入。
Q2: 如果用户在 cordis.yml 中传入了 Schema 中未声明的属性,会怎样?
解答:Schemastery 会自动过滤掉未声明的冗余字段,并在终端输出警告提示,帮助开发者及时发现因拼写错误(例如将 timeoutMs 误写为 time_out)导致的配置失效。
Q3: .role('secret') 在 Harness 运行时具体起什么作用?
解答:当字段被标记为 'secret' 时,Harness 的 Web 控制台、CLI dump 导出以及持久化的 Trajectory 会话审计日志,都会自动将其替换为 *** 掩码,防止生产凭证在日志流转中泄漏。
Q4: 在生产环境中修改了 cordis.yml,插件如何感知新配置?
解答:当运行在支持 HMR 的环境下(如 pnpm dsh web --patch),微内核监听到文件变更后会自动校验新参数。如果校验通过,会平滑调用新配置重新初始化插件 Fiber 分支。