主题
EXTENDING · 扩展指南:往 engine 里加自己的东西
教学文档(01-09)回答「这是什么、为什么这么设计」;本篇回答「我要加自己的东西,从哪下手」。 每节都给最小步骤 + 参考实现(仓库内现成的样板)。
1. 自定义一个工具(最常见)
三件套:description(给模型看的说明书)+ inputSchema(zod 参数图纸)+ execute(真实现)。
ts
import { tool } from "ai";
import { z } from "zod";
const queryStock = tool({
description: "查询股票当前价格。用户提到股票代码或名称并询问价格时调用。",
inputSchema: z.object({ symbol: z.string().describe("股票代码,如 AAPL") }),
execute: async ({ symbol }) => fetchFromYourApi(symbol), // 真实现在这
});然后把它放进工具表({ stock: queryStock })传给 runToolLoop——模型自动获得这个能力,循环零改动。
三条纪律(详见 03-tools.md):
- description 写清「适合什么 / 不适合什么」——模型靠它选工具;
- zod schema 的 message 写成「给模型的修正指令」(校验失败会回灌给模型);
- 写操作(建单/下单)建议套幂等壳(
wrapToolsWithIdempotency)。
完整可跑示例:packages/engine/examples/custom-tool.ts。
2. 加一种 Memory 实现(如 SQLite)
SessionStore 接口五个方法:append / getWindow / clear / listSessions / getHistory。
- 新建
src/memory/session.sqlite.ts实现SessionStore; factory.ts的 env 分支里加一个值(如SESSION_STORE=sqlite)——注意:不认识的值会警告并回退内存(离线优先铁律),你加的值要进分支白名单;- 契约测试挂上:
test/memory.contract.spec.ts里runSessionStoreContract("sqlite 实现", makeStore)——行为一致性由契约背书,不用复制断言。
参照实现:session.memory.ts(最简)/ session.redis.ts(带 TTL、分布式锁的完整版)。
3. 加一种 RAG 存储
RagStore 接口六个方法:upsert / deleteDoc / listDocs / readDoc / search / count。
同上三步:实现接口 → store.factory.ts 加 env 值 → test/rag.contract.spec.ts 挂契约(用 docIdPrefix 圈定测试数据)。 参照:store.memory.ts(余弦手算版)。
4. 接一个新 LLM 网关
只要它兼容 OpenAI 协议(绝大多数主流网关都兼容),改 .env 三行即可,零代码:
env
OPENAI_BASE_URL=https://api.deepseek.com/v1
OPENAI_MODEL=deepseek-chat
# 注意:DeepSeek 无 embeddings 接口,RAG 功能需换 Qwen/GLM(EMBEDDING_MODEL 跟着改)要接非 OpenAI 协议的厂商:在 llm.ts 加一个分支返回对应 SDK 的 LanguageModelV2 适配(ai SDK 有各厂商的 provider 包)。
5. 自定义库日志
engine 内部的警告(配置降级、脏数据跳过)走可注入的 Logger,默认 console:
ts
import { setEngineLogger } from "@agent-app/engine/logger";
// 换成你的日志系统(应用启动早期、任何工厂调用之前)
setEngineLogger({ info: myLog.info, warn: myLog.warn });
// 测试静音:setEngineLogger({ info: () => {}, warn: () => {} })边界:轨迹(trace.ts,stderr + AGENT_TRACE 开关)与评测报告输出是独立通道,不归 Logger 管——见 src/logger.ts 头注。
6. 调运行参数
步数保险丝的库级默认值集中在 agent-loop.ts:
ts
import { DEFAULT_MAX_STEPS } from "@agent-app/engine/agent-loop";
// runToolLoop({ ..., maxSteps: 8 }) ← 调大换更复杂任务,代价是失控风险(见 01 文档保险丝节)审批超时 / 幂等 TTL / 存储开关都是环境变量(见根 .env.example 的分区注释)。
7. 验证你的扩展
powershell
pnpm verify # typecheck → engine/api 测试 → selftest → examples 类型检查 → 架构红线加了自己的实现后,把契约测试挂上(第 2/3 节)再跑 verify——契约全绿 = 你的实现遵守了接口承诺。