Skip to content

echoVic/blade-agent-sdk

Repository files navigation

Blade Agent SDK

面向 Node.js 与 TypeScript 的 session-first Agent SDK,提供多轮会话、工具调用、MCP、权限控制、Hooks、沙箱执行和结构化输出。

特性

  • 多轮会话:send() / stream() 分离,适合 CLI、IDE 和服务端集成
  • 会话持久化:支持 resumeSession()forkSession()
  • 内置工具:文件、搜索、Shell、Web、Todo、Plan、MCP 资源工具
  • MCP:支持 stdio、SSE、HTTP 服务器,也支持 in-process MCP server
  • 权限控制:permissionMode + canUseTool
  • Hooks:在会话、权限和工具执行阶段注入自定义逻辑
  • 沙箱执行:通过 sandbox 配置约束命令执行
  • 结构化输出:支持 JSON Schema outputFormat

安装

npm install @blade-ai/agent-sdk

快速开始

import { createSession } from '@blade-ai/agent-sdk';

const session = await createSession({
  provider: {
    type: 'openai-compatible',
    apiKey: process.env.API_KEY,
  },
  model: 'gpt-4o-mini',
});

await session.send('分析这个仓库的测试结构');

for await (const msg of session.stream()) {
  if (msg.type === 'content') {
    process.stdout.write(msg.delta);
  }
}

session.close();

核心模型

Blade Agent SDK 的主入口是 Session:

  • createSession(options):创建新会话
  • resumeSession(options):恢复已有会话
  • forkSession(options):从已有会话线性分叉
  • prompt(message, options):一次性请求,内部使用临时会话

Send / Stream

await session.send('检查最近的改动是否会影响 MCP 工具刷新');

for await (const msg of session.stream({ includeThinking: true })) {
  switch (msg.type) {
    case 'turn_start':
      console.log(`turn ${msg.turn}`);
      break;
    case 'content':
      process.stdout.write(msg.delta);
      break;
    case 'tool_use':
      console.log(`\n[tool] ${msg.name}`);
      break;
    case 'tool_result':
      console.log(`\n[result] ${msg.name}`);
      break;
    case 'result':
      console.log(`\n[done] ${msg.subtype}`);
      break;
  }
}

约束:

  • 每次 stream() 之前必须先调用一次 send()
  • 同一时间只能有一个 pending message
  • stream() 会消费当前 pending message,并把结果写回会话历史

一次性 prompt

import { prompt } from '@blade-ai/agent-sdk';

const result = await prompt('总结这个项目的公开 API', {
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
});

console.log(result.result);
console.log(result.toolCalls);
console.log(result.usage);

恢复与分叉

import { forkSession, resumeSession } from '@blade-ai/agent-sdk';

const session = await resumeSession({
  sessionId: 'existing-session-id',
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
});

const forked = await forkSession({
  sessionId: 'existing-session-id',
  messageId: 'msg-123',
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
});

配置 Session

import { PermissionMode, type SessionOptions } from '@blade-ai/agent-sdk';

const options: SessionOptions = {
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
  systemPrompt: 'You are a careful coding agent.',
  maxTurns: 12,
  permissionMode: PermissionMode.DEFAULT,
  allowedTools: ['Read', 'Edit', 'Write', 'Bash'],
  cwd: process.cwd(),
  env: { CI: '1' },
};

常用字段:

  • provider / model:模型接入配置
  • systemPrompt:会话级系统提示
  • allowedTools / disallowedTools / tools:工具集控制
  • mcpServers:MCP server 配置
  • permissionMode / canUseTool:权限控制
  • hooks:会话/工具/权限阶段回调
  • sandbox:命令执行沙箱
  • outputFormat:JSON Schema 结构化输出
  • agents:命名子代理定义
  • logger:结构化日志回调

Hooks

当前 SessionOptions.hooks 支持这些事件:

  • HookEvent.SessionStart
  • HookEvent.SessionEnd
  • HookEvent.UserPromptSubmit
  • HookEvent.PermissionRequest
  • HookEvent.PreToolUse
  • HookEvent.PostToolUse
  • HookEvent.PostToolUseFailure
  • HookEvent.TaskCompleted
import { createSession, HookEvent } from '@blade-ai/agent-sdk';

const session = await createSession({
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
  hooks: {
    [HookEvent.PreToolUse]: [
      async (input) => {
        if (input.toolName === 'Bash' && String(input.toolInput).includes('rm -rf')) {
          return { action: 'abort', reason: 'Dangerous command blocked' };
        }
        return { action: 'continue' };
      },
    ],
    [HookEvent.PostToolUse]: [
      async (input) => ({
        action: 'continue',
        modifiedOutput: {
          ...((input.toolOutput as Record<string, unknown>) || {}),
          audited: true,
        },
      }),
    ],
  },
});

权限控制

import { createSession, PermissionMode, type CanUseTool } from '@blade-ai/agent-sdk';

const canUseTool: CanUseTool = async (toolName, input, options) => {
  if (options.toolKind === 'readonly') {
    return { behavior: 'allow' };
  }

  if (toolName === 'Bash' && String(input.command || '').includes('rm -rf')) {
    return { behavior: 'deny', message: 'Dangerous command blocked' };
  }

  return { behavior: 'ask' };
};

const session = await createSession({
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
  permissionMode: PermissionMode.DEFAULT,
  canUseTool,
});

MCP

连接外部 MCP 服务器

const session = await createSession({
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
  mcpServers: {
    filesystem: {
      type: 'stdio',
      command: 'npx',
      args: ['-y', '@anthropic-ai/mcp-server-filesystem', process.cwd()],
    },
  },
});

console.log(await session.mcpServerStatus());
console.log(await session.mcpListTools());

定义 in-process MCP server

import { createSdkMcpServer, tool } from '@blade-ai/agent-sdk';
import { z } from 'zod';

const greet = tool(
  'greet',
  'Greet a user by name',
  { name: z.string() },
  async ({ name }) => ({
    content: [{ type: 'text', text: `Hello, ${name}!` }],
  }),
);

const greetServer = await createSdkMcpServer({
  name: 'greetings',
  version: '1.0.0',
  tools: [greet],
});

沙箱

const session = await createSession({
  provider: { type: 'openai-compatible', apiKey: process.env.API_KEY },
  model: 'gpt-4o-mini',
  sandbox: {
    enabled: true,
    autoAllowBashIfSandboxed: true,
    excludedCommands: ['sudo'],
    network: {
      allowLocalBinding: true,
    },
  },
});

自定义工具

import { defineTool } from '@blade-ai/agent-sdk';

const echoTool = defineTool({
  name: 'Echo',
  description: 'Echoes text back to the model',
  parameters: {
    type: 'object',
    properties: {
      text: { type: 'string', description: 'Text to echo' },
    },
    required: ['text'],
  },
  execute: async (params) => ({
    success: true,
    llmContent: String(params.text),
    displayContent: String(params.text),
  }),
});

日志

SDK 不自带日志实现。你只需要实现 AgentLogger 接口:

import type { AgentLogger, LogEntry } from '@blade-ai/agent-sdk';

const logger: AgentLogger = {
  log(entry: LogEntry) {
    console.log(entry.level, entry.category, entry.message, entry.args);
  },
};

文档

About

Blade Agent SDK

Resources

Contributing

Stars

Watchers

Forks

Packages