@tansr/sdk · Node.js ≥ 22.19 · ESM · TypeScript 类型 · 无 UI 框架依赖

智能体 SDK,把 Agent Harness 嵌进你的应用

Tansr AI Agent SDK 将智能体运行时交给你的产品:模型调用、工具执行、多轮上下文与权限控制共享同一内核。你负责业务、用户界面和身份体系,SDK 负责把一次提问运行到可处理的结果。

示例版本:@tansr/sdk 0.11.1(当前 npm 发布版)。安装命令固定此版本;0.12.0 尚未发布。

安装 TypeScript SDK
npm install @tansr/sdk@0.11.1

Agent Harness SDK:从模型请求到应用运行时

Agent Loop SDK 描述的是循环能力:模型请求工具,工具结果回到上下文,模型继续处理,直到完成、中断或达到运行限制。Tansr 的 Harness 还包括工具调度、权限判定、上下文压缩、会话存储接口和事件投影;不是只封装一次模型 HTTP 调用。

  1. 01接收用户输入
  2. 02调用已配置的模型
  3. 03检查权限并执行工具
  4. 04回送结果并继续循环
  5. 05完成、取消或触达限制
query(options)
单轮便捷 API:异步生成器输出事件,生成器终值携最终文本、历史与用量。适合 Node.js 脚本或单次任务。
createSession(options)
多轮会话 API:send、events、idle、interrupt、setModel 和 close,适合桌面助手与产品内对话。
runAgent(options)
低阶 API:自行提供模型客户端、工具与执行器,直接驱动内核查询。适合已有基础设施的接入方。

快速集成:安装、短期令牌、流式会话

下面以已发布的 @tansr/sdk 0.11.1 接口为基线,采用面向终端分发的平台令牌模式。SDK 运行在 Node.js 或 Electron 主进程,不是浏览器渲染进程里的全功能运行时;TypeScript 项目使用 ES2022 或更新 target。

客户端 AI 密钥保护:后端换发,终端只持短期令牌

  1. 在控制台创建应用并配置模型与能力。appkey 双头只保存在你的服务端,不打包进客户端、日志或代码仓库。
  2. 你的服务端先校验自己的登录态,从已验证会话取得稳定 endUserId,再向平台换发令牌;不信任客户端任意提交的用户标识。
  3. 回程只下发 token 和 expiresAt。令牌到期后重新经登录态换发;平台支持按用户吊销、停用应用与轮换应用密钥等止损手段。
POST /v1/app-tokens
POST {platformBaseUrl}/v1/app-tokens
x-tansr-key-id: <server-side app key id>
x-tansr-key: <server-side app key>
Content-Type: application/json

{ "endUserId": "<verified-user-id>", "ttlSeconds": 3600 }

// Forward only { token, expiresAt } to your client.

这是换发接口示意,不是完整鉴权服务。按实际网关要求补齐 TWP 请求签名,参考文档中的服务端令牌示例;TTL 支持 60–86400 秒。用户登录、令牌保管和续期由你的应用实现。

接流式事件,并明确收口会话

app.ts
import { createSession } from '@tansr/sdk';

const session = await createSession({ token, baseUrl });
const output = (async () => {
  for await (const event of session.events) {
    if (event.type === 'msg.text.delta') {
      process.stdout.write(event.text);
    }
  }
})();

session.send('帮我总结这份合同');
await session.idle();
session.send('再列出需要人工确认的问题');
await session.idle();
session.close();
await output;

示例中的 token、baseUrl、db、workspaceDir、存储目录和 UI 回调由你的应用提供。先订阅事件,再发送输入;长期对话保持会话打开,在宿主退出或用户结束会话时关闭。

把智能体能力接到真实业务

工具、MCP、Skills、文件、会话与界面沿同一运行链条组合。显式选择工具不等于获得授权,以下示例仍受应用能力和运行时权限约束。

AI 工具调用:用 defineTool 接业务函数

Function Calling 的执行端由你实现。参数声明生成模型可见 schema,handler 接入订单、工单或业务数据;租户与用户授权仍应在业务函数中校验。

app.ts
import { createSession, defineTool } from '@tansr/sdk';

const searchOrders = defineTool({
  name: 'searchOrders',
  description: '搜索当前已登录用户的订单',
  parameters: { keyword: { type: 'string' } },
  readOnly: true,
  handler: async ({ keyword }) =>
    db.searchForUser(verifiedUserId, keyword),
});

const session = await createSession({
  token, baseUrl,
  tools: { builtin: [], custom: [searchOrders] },
});

readOnly 是工具效应声明,不是绕过授权的承诺。handler 抛错会形成结构化工具错误;不要把内部密钥或敏感错误细节放进返回值。

Agent MCP 接入:stdio、HTTP 与连接管理

连接已有 MCP 服务,把目录与业务系统变成智能体工具。支持按服务器设置 toolAllowlist、按需发现与提前装载;连接生命周期可以跟随会话,也可以由应用集中持有。

app.ts
import { createMcpHost, createSession } from '@tansr/sdk';

const host = createMcpHost({
  servers: {
    local: { transport: 'stdio', command: 'node',
      args: [mcpServerEntry] },
    knowledge: { transport: 'http',
      url: 'https://mcp.example.com/mcp',
      toolAllowlist: ['search'] },
  },
});
const session = await createSession({ token, baseUrl, mcp: host });
// Reuse host across sessions; dispose when the application exits.
// await host.dispose();

白名单控制暴露的工具,不代替运行时审批。MCP 工具按第三方操作保守判定;应用需配置明确的权限规则或接 askUser。关闭会话不会替你销毁共享 host。

AI 本地文件处理与文件助手 SDK

读取、目录列举、Glob/Grep 检索以及按授权写入和编辑文件,可用于文档助手、项目分析或桌面自动化。给应用选择必要的工具,再决定哪些操作需要确认。

app.ts
const session = await createSession({
  token, baseUrl,
  cwd: workspaceDir,
  tools: { builtin: ['read', 'glob', 'grep', 'list'] },
});

write、edit、shell 可按需求显式选择,但必须先获得能力授权并通过执行权限。cwd 是工作目录,不是操作系统沙箱;宿主仍需约束进程权限与可访问数据。

Agent Skills:按需装载业务知识与流程

defineSkill 注入领域说明,dirs 装载你明确提供的 SKILL.md 目录。简要索引进入上下文,详细内容按需读取,适合把业务流程交给智能体,而不是把所有文档塞进每轮提示。

app.ts
import { createSession, defineSkill } from '@tansr/sdk';

const review = defineSkill({
  name: 'contract-review',
  description: '合同审阅流程',
  whenToUse: '用户要求检查合同风险时',
  instructions: '# 审阅步骤\n先列出事实,再标记待人工确认项。',
});
const session = await createSession({
  token, baseUrl,
  skills: { custom: [review], dirs: ['./assets/skills'] },
});

SDK 不自动扫描终端用户的技能目录。Skills 是指引与知识,不会给工具增加权限,也不保证模型输出正确。应用需启用 skills 能力。

AI 流式输出与工具调用状态展示

createSessionView 将增量文本、工具执行状态和用量事件投影为不可变界面状态,可接 React 或其他 UI。createNarrator 可并行生成可读日志;AgentSession.events 的订阅者有独立游标。

app.ts
import { createSessionView, createNarrator } from '@tansr/sdk';

const view = createSessionView(session, {
  delivery: { text: 'stream', thinking: 'off' },
});
const unsubscribe = view.subscribe(state => render(state));
const narrator = createNarrator(session.events, {
  verbosity: 'normal', onLine: line => logger.info(line),
});

view.appendUserMessage(text);
session.send(text);
// Host teardown: unsubscribe(); view.dispose(); narrator.dispose();

在发送前挂好需要的订阅者,避免晚订阅时误期待历史重放。用户消息由宿主显式追加到视图。关闭 thinking 展示不等于停止模型生成或计量思考 Token。

Electron AI 集成:主进程运行,IPC 传状态

桌面应用 AI SDK 的接入点是 Electron 主进程。主进程持令牌、运行会话和工具,renderer 接收投影状态;通过受控 preload 桥发送用户输入和确认结果。

main.ts
// Electron main process: window is your BrowserWindow.
const session = await createSession({ token, baseUrl });
const view = createSessionView(session);
const unsubscribe = view.subscribe(state => {
  window.webContents.send('agent:state', state);
});
// Handle input via a narrow IPC/preload bridge.
// Validate the sender and input before session.send(text).

在文档中查看 Electron 主进程、preload 和权限桥示例。Electron 需要匹配 SDK 的 Node 运行要求(样板采用 Electron ≥39);不要向 renderer 暴露 appkey、通用文件系统或任意执行接口。

多轮对话、会话存储与恢复

Agent 会话管理可从内存起步,再注入 SessionStore。createFileSessionStore 提供文件存储实现;也可以实现自己的存储接口。恢复历史与继续保存是两个明确选项。

app.ts
import { createFileSessionStore, createSession } from '@tansr/sdk';

const store = createFileSessionStore({ dir: userDataDir });
const session = await createSession({ token, baseUrl, store });
session.send('记住这次任务的要求');
await session.idle();
const sessionId = session.sessionId;
session.close();

const resumed = await createSession({
  token, baseUrl,
  resume: { sessionId, store },
  store, // Continue persisting the resumed conversation.
});

没有注入 store 或回调时,会话默认保存在内存。也可用 initialMessages / onHistoryCommit 对接已有数据库;meta.rewritten=true 时须替换已存历史,不可只追加尾部。存储访问控制、加密与保留期由宿主负责。

上下文压缩与可恢复快照

运行时在已知模型上下文窗口时支持自动压缩,也提供手动 compact、checkpoint 与 restore。长期任务可保存上下文检查点,恢复或分支继续处理。

app.ts
// A store with checkpoints has been wired into session.
await session.idle();
const mark = await session.checkpoint({ label: 'before-summary' });
const result = await session.compact({
  instructions: '保留任务约束和未完成事项',
});
if (result.status === 'compacted') {
  console.log(result.compactionId);
}
const restored = await session.restore(mark.checkpointId);
console.log(restored.status);

压缩是有损摘要,不承诺永久记住全部细节;快照恢复只恢复上下文,不撤销已经发生的文件写入、网络请求或外部业务动作。关键事实应写入你的可信业务存储。

多模型接入与会话中切换

平台令牌模式从应用授权目录取得模型,按可用别名切换后续轮次。Node.js 服务还可选本地配置托管模式;测试与特殊集成可成对注入 client 和 model。

app.ts
const session = await createSession({ token, baseUrl });
// Use an alias/handle available in this app's authorized bundle.
session.setModel('main');
session.send('按新选择的模型继续处理');

不是任意填一个厂商模型名就能调用。setModel 对后续轮生效,不重写正在执行的请求;可用输入能力、上下文窗口与输出能力随所选模型而定。

系统媒体工具:图像、视频、语音与搜索

imageGen、videoGen、speechToText 和 textToSpeech 已进入内核工具面,新集成通过 tools.builtin 选择。SDK 令牌模式使用平台提供方,工具与能力授权仍分别检查。

app.ts
const session = await createSession({
  token, baseUrl,
  tools: { builtin: [
    'imageGen', 'videoGen', 'speechToText', 'textToSpeech',
  ] },
});

媒体工具需要显式选择,不默认进入每轮工具集;还需平台通道、授权模型与能力位。tools.platform 仅为兼容别名。webSearch 也写入 builtin,并需工具位与平台检索通道双重授权;SDK 不提供其 BYO 后端。

Agent 权限控制与 AI 工具调用审批

能力开关决定应用能装配什么,运行时规则决定这一调用能否执行。askUser 把需要人工确认的调用交给你的界面;在平台令牌模式,还可结合已任命裁决人的判断。

app.ts
const session = await createSession({
  token, baseUrl,
  permission: {
    rules: {
      deny: ['Shell'],
      ask: ['Write', 'Edit', 'mcp__knowledge__*'],
    },
    askUser: async (call, signal) => {
      const approved = await confirmTool(call.name, call.args, signal);
      return approved ? 'allow' : 'deny';
    },
  },
});

需要 ask 但未接确认回调时不会默认执行。0.11.1 中显式 permission.mode 与已任命裁决人会发生装配冲突,因此示例省略 mode;不能依赖尚未发布的 0.12.0 兼容行为。审批不是操作系统隔离,也不替代业务授权。

密钥、应用能力与执行权限各有边界

应用控制台是授权来源

令牌模式的模型、工具能力和治理配置来自所属应用。系统工具选择与平台授权分组是不同维度:媒体工具通过内置工具入口选择,授权仍取决于平台能力配置。显式选择未授权工具会产生装配错误;具体支持范围以应用配置和所用 SDK 版本为准。

权限覆盖具体调用

文件操作、自定义函数和 MCP 调用仍经过运行时判定。工具只读声明、MCP 白名单、用户确认与业务数据权限作用不同,不能彼此代替。对外发消息、写数据库或资金操作尤其需要应用自己的授权与确认。

终端没有上游模型密钥

平台令牌模式中,上游厂商凭据保存在平台,appkey 保存在开发者后端,终端持短期 app_user 令牌。令牌仍是敏感凭据;登录校验、令牌续期和客户端存储安全由你的产品承担。

AI 用量统计、Token 计量与按用户对账

界面里的实时用量

cost.usage.updated 事件提供模型请求后的用量更新,SessionView 可将其聚合展示。它用于产品内反馈;最终结算与价格以服务端记录为准。

终端用户只查询自己的计数

GET /v1/my-usage 使用短期令牌,限定所属 endUserId,响应不含金额。客户端不能靠更换查询用户标识读取他人的用量。

开发者负责用户收费体验

/v1/app-usage/by-end-user 是开发者按终端用户对账的金额面,不应原样代理给终端。套餐、模型/媒体用量与开发者向自己用户收取的费用需要分别说明;终端用户收费与产品内价格由你的业务实现。

usage.ts
for await (const event of session.events) {
  if (event.type === 'cost.usage.updated') {
    updateUsage(event);
  }
}
// Subscribe before sending prompts; keep financial reconciliation server-side.