メインコンテンツまでスキップ

如何扩展 Agent 引擎

本文提供三种常见扩展场景的实操指南:添加新工具、添加新引擎、创建 Agent 配置文件。

指南 1:添加新工具

为 TinyElf 引擎添加一个新的工具。

步骤

1. 实现 ITool 接口

packages/desktop/app/main/services/agent-core/engine/tinyelf/tools/ 目录下创建新文件:

// MyNewTool.ts
import type { ITool } from './ToolInterface';

export class MyNewTool implements ITool {
readonly name = 'MyNewTool';
readonly description = '工具的功能描述(LLM 会读到这段描述来决定是否使用)';
readonly parameters = {
type: 'object',
properties: {
input: {
type: 'string',
description: '输入参数的描述',
},
optional_param: {
type: 'number',
description: '可选参数',
},
},
required: ['input'],
};

constructor(private workspacePath: string) {}

async execute(params: Record<string, unknown>): Promise<string> {
const input = String(params.input);
// 实现工具逻辑
return `执行结果: ${input}`;
}
}

关键要求:

  • name 必须唯一
  • description 要让 LLM 理解何时使用此工具
  • parameters 使用标准 JSON Schema 格式
  • execute 返回字符串结果(超过 50KB 会被自动截断)
  • 错误时返回以 Error 开头的字符串或抛出异常

2. 在 ToolRegistryBuilder 中注册

编辑 TinyElfToolRegistryBuilder.ts

import { MyNewTool } from './tools/MyNewTool';

export async function buildToolRegistry(...): Promise<ToolRegistryBuildResult> {
// ...已有工具注册代码...

// 注册新工具
toolRegistry.register(new MyNewTool(projectPath));

// ...
}

3. 确定敏感度分类

如果工具是只读的安全工具,在 TinyElfAgentLoop.ts 中添加到安全工具集合:

private static readonly SAFE_TOOLS = new Set([
'Read', 'ListDir', 'Glob', 'Grep',
'WebSearch', 'WebFetch',
'list_skills', 'read_skill',
'Notify', 'SessionsYield', 'SessionsHistory',
'MyNewTool', // 添加到安全集合
]);

不添加则默认为敏感工具(需要用户确认)。

4. 配置工具继承(可选)

如果子 Agent 应该继承此工具,在 TinyElfToolRegistryBuilder.ts 中:

const inheritableToolNames = new Set([
'list_skills', 'read_skill', 'slash_command',
'MyNewTool', // 添加到可继承集合
]);

修改清单

文件操作说明
tinyelf/tools/MyNewTool.ts新建工具实现
tinyelf/TinyElfToolRegistryBuilder.ts修改注册工具
tinyelf/TinyElfAgentLoop.ts修改敏感度分类(可选)
tinyelf/TinyElfToolRegistryBuilder.ts修改工具继承(可选)

指南 2:添加新引擎

为 Elftia 添加一个新的 Agent 引擎类型。

步骤

1. 添加 EngineType

packages/desktop/app/shared/contracts/elftia-agent-types.ts 中:

export type EngineType =
| 'tinyelf'
| 'claude-sdk'
| 'cli'
| 'chat'
| 'st-chat'
| 'api'
| 'my-engine'; // 新增

2. 实现 IEngine 接口

packages/desktop/app/main/services/agent-core/engine/ 目录下创建新文件:

// MyEngine.ts
import type { EngineType } from '@shared/contracts/elftia-agent-types';
import type { EngineSessionContext, IEngine } from './types';

export class MyEngine implements IEngine {
readonly engineType: EngineType = 'my-engine';

private activeSessions = new Map<string, { cancel: () => void }>();

async startSession(ctx: EngineSessionContext): Promise<void> {
const { dbSessionId, sender, prompt } = ctx;

// 1. 保存用户消息
// 2. 发送 IPC 事件
sender.send('agent:event', {
type: 'userMessage',
sessionId: dbSessionId,
message: { id: '...', role: 'user', content: prompt },
});

// 3. 执行引擎逻辑(通常异步)
const controller = new AbortController();
this.activeSessions.set(dbSessionId, {
cancel: () => controller.abort(),
});

try {
// ...引擎核心逻辑...

sender.send('agent:event', {
type: 'complete',
sessionId: dbSessionId,
});
} finally {
this.activeSessions.delete(dbSessionId);
}
}

async resumeSession(ctx: EngineSessionContext): Promise<void> {
// 与 startSession 类似,但加载历史消息
await this.startSession(ctx);
}

async interrupt(dbSessionId: string): Promise<boolean> {
const session = this.activeSessions.get(dbSessionId);
if (session) {
session.cancel();
this.activeSessions.delete(dbSessionId);
return true;
}
return false;
}

isActive(dbSessionId: string): boolean {
return this.activeSessions.has(dbSessionId);
}
}

3. 注册到 EngineDispatcher

packages/desktop/app/main/index.ts 中:

import { MyEngine } from './services/agent-core/engine/MyEngine';

const dispatcher = new EngineDispatcher();
// ...已有引擎注册...
dispatcher.registerEngine(new MyEngine());

4. 在 index.ts 中导出

packages/desktop/app/main/services/agent-core/engine/index.ts 中:

export { MyEngine } from './MyEngine';

5. 添加 i18n 键(可选)

如果需要在 UI 中显示引擎名称,添加国际化键:

{
"backendMyEngine": "My Engine",
"backendMyEngineDesc": "My custom engine description"
}

修改清单

文件操作说明
@shared/contracts/elftia-agent-types.ts修改添加 EngineType
services/agent-core/engine/MyEngine.ts新建引擎实现
services/agent-core/engine/index.ts修改导出新引擎
main/index.ts修改注册到 EngineDispatcher
i18n 文件修改添加显示名称(可选)

指南 3:创建 Agent 配置

创建一个可在 TinyElf 引擎中使用的 Agent 配置文件。

Agent 配置格式

---
name: Agent 名称
description: Agent 描述
model: main
permissionMode: default
tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
skills:
- code-standards
---

系统提示正文(Markdown 格式)

## 指令

1. 第一步
2. 第二步

AgentConfig 类型

interface AgentConfig {
name: string;
description: string;
tools?: string[]; // 工具白名单
model?: ModelAlias | string; // 模型选择
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';
skills?: string[]; // 技能列表
systemPrompt: string; // 正文内容
}

type ModelAlias = 'main' | 'background' | 'inherit' | 'sonnet' | 'opus' | 'haiku';

模型别名解析

function resolveModelAlias(
alias: string,
parentModel: string,
backgroundModel?: string,
): string;
别名解析结果
main / inherit返回 parentModel
background返回 backgroundModel(回退到 parentModel)
sonnet将 parentModel 中的 opus/haiku 替换为 sonnet
opus替换为 opus
haiku替换为 haiku
其他作为具体模型 ID 使用

Agent 发现

AgentsLoader 从以下位置发现 Agent 配置:

class AgentsLoader {
constructor(
projectPath: string, // .claude/agents/*.md
personalDir: string, // ~/.claude/agents/*.md
);
listAgents(): AgentInfo[];
loadAgent(name: string): AgentConfig | null;
}

发现优先级: 项目级 > 个人级 > 内置

Agent 使用场景

作为子 Agent 被 spawn

spawn_agent(prompt: "审查这段代码", agent: "code-reviewer")

SpawnTool 会通过 AgentsLoader.loadAgent() 加载 Agent 配置,设置系统提示、工具限制和权限模式。

在 Agent 面板中选择

前端通过 AgentsLoader.listAgents() 列出所有可用 Agent,用户选择后通过 agentId 参数传递给引擎。

修改清单

文件操作说明
.claude/agents/<name>.md新建Agent 配置文件

无需修改代码。配置文件放置在正确路径后,AgentsLoader 会自动发现。

通用注意事项

测试

所有工具和引擎都应该有对应的测试:

  • 工具测试:tinyelf/tools/__tests__/
  • 引擎测试:agent-core/engine/__tests__/
  • 安全测试:platform/security/__tests__/

索引更新

新增模块后,更新 .claude/skills/architecture-index/SKILL.md 中的文件索引。

IPC 事件规范

所有引擎的 IPC 事件必须遵循统一格式:

sender.send('agent:event', {
type: string, // 事件类型
sessionId: string, // 会话 ID
// ...事件特定载荷
});

工具命名规范

工具类型命名格式示例
文件系统PascalCaseRead, Write, Edit
ShellPascalCaseBash
功能工具snake_casespawn_agent, list_skills
MCP 工具mcp__<server>__<tool>mcp__github__list_repos
会话工具PascalCase 前缀SessionsSpawn, SessionsList

关键文件

文件路径说明
ITool 接口tinyelf/tools/ToolInterface.ts工具基础接口
IEngine 接口agent-core/engine/types.ts引擎基础接口
EngineDispatcheragent-core/engine/EngineDispatcher.ts引擎注册中心
ToolRegistryBuildertinyelf/TinyElfToolRegistryBuilder.ts工具注册构建
AgentsLoadertinyelf/agents/AgentsLoader.tsAgent 配置加载
SkillsLoadertinyelf/skills/SkillsLoader.ts技能配置加载
EngineType 定义@shared/contracts/elftia-agent-types.ts类型定义
主入口main/index.ts引擎注册

所有路径相对于 packages/desktop/app/main/services/

相关模块

模块说明参考文档
TinyElf Agent Loop工具执行循环TinyElf 详解
工具系统工具注册和执行工具系统
安全层三层安全管道安全层
ClaudeSdkEngineSDK 引擎ClaudeSdkEngine
CliRunnerEngineCLI 引擎CliRunnerEngine