@gt-fe/eap-sdk
v0.2.20
Published
EAP Agent 开发 SDK — Runtime 开发服务、项目校验与确定性打包
Readme
@gt-fe/eap-sdk
@gt-fe/eap-sdk 是 EAP 单 Agent 项目的 SDK,负责项目发现与校验、用户会话、平台 API、Tool/Skill 依赖安装、Runtime 目录物化、基于 Runtime 的 Agent API 以及确定性打包。
Agent 的实际执行仍由 @gt-fe/eap-runtime 负责。SDK 不重新实现 Graph 编译、节点执行、Tool 路由或 Runtime 事件协议。
如果你要开发一个完整的 Agent 项目,请先阅读 场景一:常规 Agent 开发手册。如果你是在已有服务中把 SDK 作为依赖使用,请先阅读 场景二:外部项目 SDK 接入手册;本文随后提供 API 和配置的详细参考。
安装
npm install @gt-fe/eap-sdk本包为纯 ESM:
import { createAgent } from '@gt-fe/eap-sdk';项目模型
一个项目只开发一个 Agent,开发者维护的源文件位于项目根目录:
<project>/
├── agent.manifest.json
├── graph.json
├── eap.config.json
├── eap.lock.yaml
├── tools/<code>/...
├── skills/<code>/...
├── .eap/
│ ├── remote/ # Registry 资源缓存
│ ├── runtime/ # CLI 使用的 Runtime
│ ├── sessions/ # CLI 默认会话目录
│ ├── package-staging/ # 打包临时目录
│ └── package/ # 默认包输出目录
└── dist/ # 外部宿主的构建产物;Runtime 路径由宿主显式指定agent.manifest.json、graph.json、eap.config.json、eap.lock.yaml 以及本地 tools/、skills/ 是项目输入;.eap/ 和外部宿主指定的 dist/.eap/runtime 是 SDK 生成的可删除状态。Runtime 目录不应提交或手工编辑。启用会话持久化时,会话目录位于 Runtime 根目录旁边;CLI 默认为 .eap/sessions。
项目 eap.config.json.version 必须严格等于当前安装的 @gt-fe/eap-sdk package version;字段级配置和部署交付说明见 dev-tools 文档入口。
findAgentRoot() 和 resolveAgentProject() 只发现源项目,不使用 EAP_PREINSTALL_ROOT。选择器只支持 root 和 startDir,不存在 Agent code、版本或目录歧义选择。
import {
resolveAgentProject,
validateAgentProject,
type AgentProjectSelector,
} from '@gt-fe/eap-sdk';
const selector: AgentProjectSelector = { root: process.cwd() };
const project = resolveAgentProject(selector);
const validation = validateAgentProject(project.root);
if (!validation.valid) {
console.error(validation.issues);
}核心能力
| 能力 | 主要 API | 说明 |
|---|---|---|
| 项目发现 | findAgentRoot()、resolveAgentProject() | 查找根级单 Agent 项目 |
| 项目校验 | validateAgentProject()、validateGraph() | 校验 Manifest、Graph、eap.lock.yaml 和资源路径 |
| 用户会话 | getCurrentUserSession()、saveCurrentUserSession() | 管理当前登录用户和平台 Token;本地可用 EAP_CHAT_USER / EAP_DEBUG_USER |
| 平台 API | createPlatformClient() | 访问 Portal、Foundation 和平台认证 |
| 依赖安装 | installAgentResource()、installAgentDependencies() | 下载或恢复 Tool/Skill ZIP 制品,并维护 eap.lock.yaml |
| Runtime 物化 | prepareAgentRuntime() | 生成 Runtime 可直接读取的预装目录 |
| Agent API | createAgent() | 从已物化 Runtime 创建进程内 Agent,支持 invoke/stream 和 Graph 编排 |
| 内嵌管理 | agent.sessions、agent.messages、agent.resources、agent.events | 宿主进程内的会话、消息、资源与实时事件门面 |
| 独立 Runtime | packageStandaloneAgentProject() | 将同一套物化 Runtime 输出到宿主指定目录(推荐 dist/.eap/runtime),启动时不读取源项目 |
| 打包与验包 | packageAgentProject()、readAgentPackage() | 生成并校验单 Agent Runtime 部署包 |
| Schema | AgentManifestSchema、GraphSchema、ToolsetManifestSchema 等 | SDK 所有项目文件的 Zod Schema |
所有公共 API 均从包根导出,不需要导入内部路径。
平台 API
createPlatformClient() 是 Portal 与 Foundation HTTP 调用的统一入口。端点由调用方显式提供,客户端会使用当前用户会话 Token;也可通过 token 覆盖,便于服务端或测试宿主注入凭证。
import { createPlatformClient } from '@gt-fe/eap-sdk';
const platform = createPlatformClient({
portalEndpoint: 'https://portal.example',
foundationEndpoint: 'https://foundation.example',
});
const agents = await platform.portalFetch('/api/v1/agents');
const deployment = await platform.foundationFetch('/api/v1/deployments', {
method: 'POST',
body: JSON.stringify({ agentCode: 'report-agent', version: '1.0.0' }),
});客户端同时提供 checkPortalHealth()、checkFoundationHealth()、uploadFileToObjectStorage(),以及
resolveTokenUser(token)、会保存统一用户会话的 loginWithCas()、validateAndSaveToken(),和
吊销 Token 的 revokeToken()。Registry Tool/Skill 安装也使用此客户端,不再维护独立 HTTP 实现。
resolveTokenUser(token) 适合宿主在收到 HTTP Bearer Token 后解析本次请求的用户身份。它只返回
PlatformIdentity,不会保存当前 CLI 会话;如果校验结果的 callerType 是 client 或 service,
SDK 会拒绝把它当作用户身份:
import { createPlatformClient } from '@gt-fe/eap-sdk';
const client = createPlatformClient({
portalEndpoint: process.env.EAP_PLATFORM_ENDPOINT!,
foundationEndpoint: process.env.FOUNDATION_SERVICE_URL!,
token: requestToken,
});
const user = await client.resolveTokenUser(requestToken);
console.log({ userId: user.userId, roles: user.roles, permissions: user.permissions });不要打印或持久化 requestToken;生产环境应由宿主负责 Token 的来源、租户校验和错误映射。
当前用户会话
SDK 将当前用户资料和平台凭证统一保存在 ~/.eap/config.json;可通过 EAP_CONFIG_DIR 修改目录。
import {
clearCurrentUserSession,
getCurrentUserSession,
getCurrentUserToken,
saveCurrentUserSession,
} from '@gt-fe/eap-sdk';
saveCurrentUserSession({
userId: 'U001',
username: 'alice',
roles: ['developer'],
permissions: [],
token: '<platform-token>',
authMethod: 'token',
platformUrl: 'https://foundation.example',
});
const user = getCurrentUserSession();
const token = getCurrentUserToken();
clearCurrentUserSession();规则如下:
- 同一时刻只有一个当前用户,不随 CLI profile 或 Runtime storage profile 切换。
getCurrentUserSession()始终返回用户资料;没有已保存会话时返回default-user。getCurrentUserToken()优先读取EAP_TOKEN,否则读取已保存 Token;默认用户不提供 Token。- Runtime 环境准备会把当前 Token 映射为
EAP_DELEGATION_TOKEN。 - 用户资料在进程内缓存;测试或特殊宿主可调用
clearUserSessionCache()清除缓存。
版本锁定文件与资源安装
开发态版本锁定文件是 eap.lock.yaml(规格称 eap.lock)。项目根锁文件供 dev-tools 在安装、校验、Runtime 准备和打包时使用;物化副本会随 Runtime 和生产包交付并接受格式与摘要校验。运行中的 Runtime 不用它访问 Registry 或重新安装资源;dependencies.lock 仍是实际预装资源的目标态清单。
lockfileVersion: 2
resources:
tools:
- code: search-tool
version: 1.2.0
source: registry
path: .eap/remote/tools/search-tool/1.2.0
skills: []
subagents: []每条 Tool/Skill 记录包含:
code:Agent Manifest 中声明的资源编码。version:确定的语义化版本。source:registry或local。path:相对于项目根的可移植目录路径。
Registry 资源存放在 .eap/remote;工程内资源在 tools/<code> 或 skills/<code>。锁文件只记录来源、路径和版本;资源摘要在 package/standalone 物化时从实际入口文件临时计算。source: registry 也可以是 toolset;SDK 把它及同目录制品作为整体复制,不展开或校验其 tools[] 子工具。绝对路径、.. 穿越、符号链接、缺失目录、缺失入口文件和本地/Registry 同名冲突都会被拒绝。
安装单个远程资源:
import { installAgentResource } from '@gt-fe/eap-sdk';
await installAgentResource({
root: process.cwd(),
kind: 'tool',
code: 'search-tool',
version: '1.2.0',
token: process.env.EAP_TOKEN,
});按名称和精确版本安装当前项目中的本地资源:
import { installLocalAgentResource } from '@gt-fe/eap-sdk';
await installLocalAgentResource({
root: process.cwd(),
kind: 'tool',
code: 'echo-tool',
version: '1.0.0',
});按名称卸载当前项目中的本地或 Registry 资源:
import { uninstallAgentResource } from '@gt-fe/eap-sdk';
await uninstallAgentResource({
root: process.cwd(),
code: 'echo-tool',
});恢复全部锁定资源并刷新本地资源记录:
import { installAgentDependencies } from '@gt-fe/eap-sdk';
const result = await installAgentDependencies({ root: process.cwd() });
console.log(result.restoredRegistryResources, result.refreshedLocalResources);只有安装 API 会访问平台。服务启动和打包默认离线;远程缓存缺失时应先执行安装,而不是在 Runtime 启动后动态拉取。
Registry Tool/Skill 安装会按 code 和 version 查询 Portal 资源详情,并通过其中的 source_url 下载 ZIP 制品。制品会解压到 .eap/remote/tools/<code>/<version>/ 或 .eap/remote/skills/<code>/<version>/;开发锁不保存资源摘要。
agent.manifest.json 只使用 toolRefs、skillRefs 和 subagentRefs 声明依赖;其中 subagentRefs 使用 { code, version },不会触发 Tool/Skill ZIP 下载。
Skill 包使用 SKILL.md/skill.md frontmatter 提供身份。Registry Skill 的平台 Tool 引用会规范化后存入 eap.lock.yaml.resources.skills[].toolRefs,不会写回 Skill 源目录;本地 Skill 不会因任意 frontmatter 自动安装 Tool。
- Agent 已有同名 Tool 时,以 Agent 的版本为准,Skill 不会覆盖它。
- Agent 没有同名 Tool 时,Registry Skill 会按平台声明的版本安装 Registry Tool;本地 Skill 不会从其
toolRefs推导或安装 Tool。 toolRefs[].toolId是平台 Tool code;ZIP 内的scripts、metadata和旧引用不会被用来推导 Registry 依赖。
卸载 Tool 前 SDK 会检查当前 Agent 已声明的 Skill 依赖。仍被 Skill 引用时会拒绝卸载,并列出 Skill 版本;请先更新 Skill 或在平台重新配置依赖,再重新安装 Skill 后卸载 Tool。
Runtime 目录物化
prepareAgentRuntime() 根据 Agent Manifest、eap.lock.yaml 和 eap.config.json 的本地资源目录生成一棵完整、干净的 Runtime 目录:
import { prepareAgentRuntime } from '@gt-fe/eap-sdk';
const prepared = await prepareAgentRuntime({ root: process.cwd() });
console.log(prepared.runtimeRoot);资源映射规则:
| 来源 | Runtime 目标目录 |
|---|---|
| Registry Toolset | agents/<agentCode>/<version>/preinstall/tools/<toolsetCode>/ |
| Registry Skill | agents/<agentCode>/<version>/preinstall/skills/<skillCode>/ |
| 本地 Tool | agents/<agentCode>/<version>/preinstall/tools/<toolCode>/ |
| 本地 Skill | agents/<agentCode>/<version>/preinstall/skills/<skillCode>/ |
| localToolDirectories 的直接子目录 | agents/<agentCode>/<version>/preinstall/tools/<子目录名>/ |
| localSkillDirectories 的直接子目录 | agents/<agentCode>/<version>/preinstall/skills/<子目录名>/ |
配置目录可省略或使用空数组;模板默认是 localToolDirectories: ["./tools"] 和 localSkillDirectories: ["./skills"]。相对路径基于项目根,绝对路径原样使用。扫描只认直接子目录根部的 toolset.manifest.json 或 SKILL.md / skill.md,不解析入口内容、不核对 code/version,也不要求锁文件记录;无效父目录和无入口文件的子目录直接跳过。同名资源按配置顺序由后者覆盖,配置目录资源覆盖同名锁定资源。
物化器还会:
- 复制根级 Agent Manifest、Graph、
eap.config.json和eap.lock.yaml。 - dev/package/standalone 都从实际入口文件计算资源摘要。
- 生成
dependencies.lock、snapshot.json和.ready。 - 把 Registry 与本地 Tool/Skill 都复制到该 Agent 的
preinstall/;不生成开发者分层或shared/资源目录。 - 排除
.git、.eap、node_modules、.env*、coverage 和临时文件。 - 拒绝符号链接和越界路径。
- 通过临时目录加原子替换,避免 Runtime 看到半成品。
物化器不创建 Runtime、不启动 HTTP 服务、不访问平台,也不负责压缩包。
摘要字段的输入和格式见 dev-tools SHA-256 摘要约定。
Agent API
prepareAgentRuntime() 和 createAgent() 是两个明确分工的步骤。前者校验项目并生成 Runtime,后者只加载已物化目录。SDK 只提供进程内 API,不启动 HTTP server、不注册路由,也不提供 HTTP middleware 或鉴权。
import { createAgent, prepareAgentRuntime } from '@gt-fe/eap-sdk';
const prepared = await prepareAgentRuntime({ root: process.cwd() });
const agent = await createAgent({
runtimeRoot: prepared.runtimeRoot,
deploymentContext: 'server',
embeddedConfig: { credentials: { provider: credentialProvider } },
});
const result = await agent.invoke('汇总这份报告');
for await (const event of agent.stream('列出支撑数据')) {
console.log(event.type, event.data);
}HTTP/SSE 协议映射属于宿主项目。宿主可将 invoke、stream、sessions、messages 和 resources
映射为自己的受保护路由,但不得把 HTTP server、route 或 controller 加入 SDK。
默认行为:
prepareAgentRuntime()支持通过outputRoot或EAP_RUNTIME_ROOT指定输出目录;未指定时默认使用dist/.eap/runtime。CLI 和模板会显式选择各自的.eap/runtime或dist/.eap/runtime。createAgent()只从准备好的runtimeRoot读取 Tool/Skill 定义,不发现源项目、不解析锁文件、不执行物化。EAP_PREINSTALL_ROOT始终指向当前runtimeRoot,不是项目源目录。eap chat/eap dev传入sessionPersistence: true,使用 Runtimedevprofile,会话与消息写入 Runtime 根目录旁的默认 sessions 目录。- Runtime
testprofile 为 Redis+PostgreSQL,不再表示内存。createAgent()默认使用testprofile;需要连续对话时显式设置sessionPersistence: true。
需要注入自定义 Runtime 时,使用 runtimeFactory(prepared, environment)。不要传入已经构造完成、并绑定了其他 GraphLoader 根目录的 Runtime。
内嵌配置与编排
EmbeddedSdkConfig 是当前宿主/Agent 的显式依赖快照。server 模式必须提供
credentials.provider 或已认证 Runtime adapter;SDK 不读取 CLI 全局 config、当前 CLI 用户会话或环境
变量 Token。开发态可以使用 developmentToken。资源 manager 也由宿主注入,SDK 不维护资源数据库,也
不写 CLI manifest 或 lockfile。
Agent.graph 只操作当前 runtimeRoot 内的 Graph 文件。写入返回 pending revision,不会自动替换
Runtime:
await agent.graph.update((graph) => ({
...graph,
description: '运行时调整后的流程',
}));
await agent.config.apply();这类修改属于当前运行实例的物化目录状态。再次执行 prepareAgentRuntime() 会以源项目的
graph.json、Manifest 和锁文件重新生成 Runtime,可能覆盖运行时编排;需要持久化的改动应同时
写回源文件,再重新物化。Runtime 本身不会实时监听文件。apply() / reload() 会切换 Runtime,
可能中断正在执行的请求;新 Runtime 创建失败时继续使用旧实例。
agent.sessions 提供 create/get/list/archive;当前 Runtime 不支持 restore,调用时稳定返回
not_supported。Session 删除不属于 SDK 用户面。agent.messages.list() 使用 limit/offset 分页。
agent.events.subscribe() 和 stream(..., { onEvent }) 收到权威 Runtime SSEEvent,SDK 不存储、
查询、回放或删除 Trace。
内嵌 Agent API
可以使用现有 eap package 命令,或在自定义构建脚本中调用 packageStandaloneAgentProject(),
生成宿主需要的 Runtime 目录:
eap package --target standalone --output ./dist/.eap/runtime该模式复用项目校验、资源解析、Runtime 物化和摘要校验,但不生成 TAR.GZ,也不复制项目的
package.json。输出目录结构为
dist/.eap/runtime/agents/<code>/<version>/,其中包含 agent.manifest.json、graph.json、
eap.config.json、eap.lock.yaml、dependencies.lock、snapshot.json 和 .ready。
已由构建工具打包的入口可以直接消费该目录,并在同一个入口中编排 Agent:
import { createAgent } from '@gt-fe/eap-sdk';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const agent = await createAgent({
// 生产入口位于 dist/index.js 时,Runtime 位于 dist/.eap/runtime。
runtimeRoot: resolve(projectRoot, 'dist/.eap/runtime'),
embeddedConfig: { credentials: { provider: credentialProvider } },
});
await agent.graph.update((current) => ({
...current,
description: '运行时编排后的 Graph',
}));
await agent.config.apply();
const result = await agent.invoke('分析这份输入');
for await (const event of agent.stream('继续说明')) console.log(event);createAgent() 只校验并读取已物化 Runtime,不会重新发现源项目或执行物化。
默认的 eap package 行为不变,仍然生成可交付的 TAR.GZ 部署包。
模板开发调试使用同一个 index.ts:先执行 build-runtime 物化项目根 .eap/runtime,再以
dev 上下文创建 Agent;模板生产构建默认物化到 dist/.eap/runtime,由 dist/index.js 相对读取
./.eap/runtime。这两套路径由模板自己的 .env.local / .env.production 和构建脚本控制,
不会改变 CLI 的 .eap/runtime 约定。修改 graph.json、Agent Manifest 或本地 Tool/Skill 后重新
运行即可。调试 Registry 资源前先执行 eap install,运行时不会动态下载资源。
如果调试 SDK 源码本身,在 dev-tools 仓库中运行 pnpm --filter @gt-fe/eap-sdk dev,同时让宿主
项目通过 workspace、file: 或等价的本地依赖引用该 SDK。发布或验证独立服务时,仍使用
createAgent({ runtimeRoot, embeddedConfig }) 和 Runtime 物化脚本;HTTP 由宿主项目自行提供。
打包与验包
packageAgentProject() 会独立生成 package staging Runtime 树,不复用宿主的 Runtime 输出目录:
import { packageAgentProject, readAgentPackage } from '@gt-fe/eap-sdk';
const artifact = await packageAgentProject({
root: process.cwd(),
});
const verified = readAgentPackage(artifact.archivePath);
console.log(verified.manifest.agents[0], verified.digest);默认输出:
.eap/package/eap-agent-project-<code>-<version>.tar.gz
.eap/package/eap-agent-project-<code>-<version>.tar.gz.sha256部署包只包含:
- 物化后的 Agent 版本目录内容,直接展开到包根目录(例如
agent.manifest.json、graph.json、eap.config.json、eap.lock.yaml、preinstall/)。 - 根目录的包文件索引
eap-package.json。
部署包不会包含 .eap/remote、会话、checkpoint、staging 名称或其他开发缓存;eap.config.json 和 eap.lock.yaml 作为 Runtime 输入随包交付。readAgentPackage() 会校验 eap-package.json 的所有文件大小和摘要,并要求包内恰好有一个 Agent。
项目配置映射
eap.config.json 由 EapProjectConfigSchema 校验。SDK 在 Runtime 构造前完成以下主要映射:
顶层 version 是 SDK package version;配置版本不匹配时项目校验、服务创建和打包都会失败。
| 项目配置或输入 | Runtime 环境变量 |
|---|---|
| platform.portalUrl | EAP_PLATFORM_ENDPOINT |
| platform.foundationServiceUrl | FOUNDATION_SERVICE_URL |
| runtime.deploymentContext | EAP_DEPLOYMENT_CONTEXT |
| runtime.governance.enabled | GOVERNANCE_DISABLED |
| runtime.storage | EAP_RUNTIME_STORAGE_PROFILE、EAP_CHECKPOINT_DIR |
| runtime.tools | EAP_TOOL_EXECUTION_MODE、EAP_TOOL_GATEWAY_TRANSPORT |
| 准备好的 Runtime 目录 | EAP_PREINSTALL_ROOT |
| 当前用户 Token | EAP_DELEGATION_TOKEN |
显式环境变量优先于大多数项目配置;EAP_PREINSTALL_ROOT 始终使用本次物化得到的目录。
内置模板
SDK 与 CLI 使用同一套根级单 Agent 项目约定。内置模板包括:
simple-flow:固定顺序工作流。single-agent-with-tools:单 Agent + ReAct Tool 调用。plan-and-execute:规划后逐步执行。dag-workflow:并行扇出后合并。agent-api-orchestration:面向前端智能体页面的 Agent API 服务。
工作流语义由 graph.json 表达,agent.manifest.json 只保存身份和依赖。包含 Tool 的模板自带本地、已锁定的 echo-tool,校验和打包不依赖 Registry 缓存。
