01

TypeScript Agent 基元

当你向 Craft Agents 发送消息,代码里究竟发生了什么?

Craft Agents 是什么?

想象你有一个超级助手——它不仅能回答问题,还能真正帮你做事:发邮件、查数据库、连接 Slack、运行代码。这就是 Craft Agents 做的事。它是由 craft.do 团队专门为"指挥 AI Agent 干活"而打造的 TypeScript 桌面应用。

Craft Agents 使用了 Anthropic 的 Claude Agent SDK,把复杂的"让 AI 自主行动"能力打包成了一个优美的桌面应用。

🤖

多会话管理

同时运行多个 Agent 对话,每个都有独立状态和上下文,互不干扰。

🔌

零配置接入工具

告诉 Agent "连接 Linear",它自己找 API、读文档、配好认证——你不用动手。

📦

技能系统

把专门的指令打包成"技能",Agent 随时调用,就像给员工发操作手册。

代码里的"主演"——核心类型

Craft Agents 的代码就像一部剧,有几个主角。理解它们,你就能告诉 AI "把这个逻辑放到 Session 里,不要放到 Workspace 里"——这正是指挥 AI 的关键。

🏠
Workspace(工作区)

像一个独立的"工作桌",每个工作区有自己的 AI 配置、技能包和连接的工具。

💬
Session(会话)

一次完整的对话线程——从"你好"到任务完成。每个 Session 有独立的消息历史和状态。

📨
StoredMessage(消息记录)

每条消息的持久化存储,包含内容、发送者、token 用量和时间戳。

⚙️
MessagingGateway(消息网关)

整个系统的"中央调度室",负责把前端的操作指令路由到正确的处理器。

代码翻译:Session 是如何定义的

下面是 Craft Agents 里 Session 的真实定义(来自 packages/core/src/types/session.ts)。左边是代码,右边是白话解释:

CODE

export interface Session {
  id: string;
  sdkSessionId?: string;
  workspaceId: string;
  name?: string;
  status?: SessionStatus;
  isFlagged?: boolean;
  isArchived?: boolean;
}
            
PLAIN ENGLISH

定义一个"会话"长什么样——它有哪些属性

每个会话有一个唯一的 ID(比如 uuid),系统用它来找到你

SDK 内部用的 ID,第一条消息发送后才有——所以是"可选"的(?)

这个会话属于哪个工作区——每个会话必须"住"在某个工作区里

会话名字,可以不填(? 表示可选)

工作状态:todo / in_progress / done 等——用于任务管理流程

是否被用户标记了星标/红旗

是否已归档——归档后不在收件箱显示,但数据还在

💡
关键洞察:接口 vs 类

interface 只是数据的"形状说明书",不包含任何行为。当你告诉 AI "在 Session 类型里加一个 priority 字段",AI 就知道该改 interface,而不是改某个函数。

发一条消息,幕后发生了什么

你在 Craft Agents 里打了一段话按下发送——这个简单动作触发了一条完整的指令链。点击"下一条消息",跟着数据走一遍:

检验一下你的理解

你在 Craft Agents 里同时开了三个 AI 对话:分析销售数据、写市场方案、查竞品信息。这三个对话和工作区的关系是?

你想给每个 Session 加一个"优先级"字段(1=高、2=中、3=低)。你应该让 AI 修改哪里?

02

Craft 的工具系统

Agent 是怎么"连上"外部世界的——从 MCP 到自定义 API

AI 为什么需要"工具"?

把 Claude 想象成一位知识渊博的顾问——但他被关在一个没有网络、没有电话的房间里。他知道该怎么查销售数据,但他进不了你的数据库。工具就是给他开的那扇门。

1

Claude 决定需要查销售数据

2

调用 get_sales 工具

3

工具真正连接数据库,拿到结果

4

结果返回给 Claude,继续分析

🔑
为什么这对你重要

每一个外部集成(Slack、数据库、文件系统)都是一个"工具"。当 AI 说"我没有访问权限",通常是工具没有配置好——而不是 AI 坏了。理解这个区别,能帮你快速定位问题。

MCP——工具的"通用插口"

Craft Agents 支持 MCP(Model Context Protocol)。MCP 就像给 AI 工具定义了一种"通用 USB 接口"——任何工具只要实现这个接口,Claude 就能直接用它,不需要为每个工具单独写适配代码。

Craft Agents 运行时

⚙️
Electron Main
🔌
Session MCP Server
🔀
MessagingGateway

外部 MCP 工具

📄
Craft MCP (32+ tools)
💻
Local Stdio MCP
🌐
REST API Sources
点击任意组件,了解它的作用

代码翻译:Session MCP Server 的工具注册

Craft Agents 内置了一个特殊的 MCP 服务——session-mcp-server,它让 Agent 能感知到自己所在的会话上下文。下面是它如何注册一个工具(来自 packages/session-mcp-server/src/index.ts):

CODE

const server = new McpServer({
  name: "craft-session",
  version: "1.0.0"
});

server.registerTool(
  "get_session_info",
  { description: "Get current session metadata" },
  async () => ({ content: sessionData })
);
            
PLAIN ENGLISH

创建一个新的 MCP 服务实例,给它起个名字

服务叫 "craft-session"——Claude 会通过这个名字认识它

版本号,方便以后升级时区分新旧版本

服务创建完毕

向这个服务注册一个工具(就像在菜单上加一道菜)

工具名字叫 "get_session_info"——Claude 决定要用它时会叫这个名字

描述:获取当前会话的元数据——Claude 靠这段描述理解何时调用这个工具

工具的实际执行逻辑:返回 sessionData 里的数据

工具调用的完整数据流

当 Claude 决定调用一个工具,数据是这样在系统里流动的:

🤖
Claude API
🔀
Gateway
🔌
MCP Tool
点击"下一步"开始

思考一下

你给 Agent 添加了一个叫 search_crm 的工具,但 Claude 从不主动使用它。最可能的原因是什么?

你的团队有一个内部开发的报表工具,现在想让 Craft Agents 里的 Claude 也能调用它。最快的方式是?

03

Agent 组合模式

技能、工作区和自动化——如何把 Agent 组合成更强大的系统

技能包:给 Agent 的"操作手册"

想象你雇了一个新员工,第一天上班。你不会让他什么都靠猜——你会给他一本操作手册,写着"接到客户投诉时,先查订单状态,再用这个模板回复"。Craft Agents 的技能(Skills)就是这个操作手册。

1
技能 = 一段系统提示词(System Prompt)

技能本质上是存储在工作区里的特殊指令,告诉 Agent 在特定场景下如何行动、使用什么语气、遵循哪些规则。

2
用 @ 符号即时调用

对话中输入 @销售分析技能,这个技能的所有指令就立刻生效——就算是进行中的对话也能切换,不需要重开会话。

3
技能可以携带工具

每个技能可以绑定特定的 MCP 工具集。激活"数据分析技能",自动附带数据库查询工具和可视化工具。

代码翻译:MessagingGateway 如何路由指令

整个 Craft Agents 的核心是 MessagingGateway。它采用了一种叫 命令模式(Command Pattern) 的架构:

CODE

export class Router {
  private handlers = new Map<
    string,
    CommandHandler
  >();

  register(type: string, handler: CommandHandler) {
    this.handlers.set(type, handler);
  }

  async dispatch(cmd: Command) {
    const handler = this.handlers.get(cmd.type);
    return handler?.execute(cmd);
  }
}
            
PLAIN ENGLISH

定义一个"路由器"类,类似快递公司的分拣系统

内部维护一张"处理器清单"——命令类型 → 谁来处理它

清单是个 Map:key=命令名称,value=处理这种命令的函数

register 方法:向清单里新增一种命令的处理器

就像在快递分拣台登记:"北京的件,交给张三处理"

dispatch 方法:收到一个命令,查清单,找到对应处理器

从清单里取出这个命令类型的处理器

调用处理器的 execute 方法;如果没找到处理器,什么都不做(?. 是安全调用)

💡
为什么用命令模式?

这让系统极度可扩展——要加新功能,只需要 register 一个新的处理器,不需要修改 Router 本身。这是软件工程里的"开闭原则":对扩展开放,对修改关闭。

自动化:让 Agent 在后台自主运行

Craft Agents 最强大的功能之一是自动化(Automations)——基于事件触发的 Agent 任务,不需要你手动开启。这就像给 Agent 设置了一套巡逻规则:

on:label_change 当工作项标签从"待处理"变为"进行中"时,自动创建 Agent 会话,开始执行相关任务
on:schedule 按时间表触发——比如每周一早上 9 点,自动拉取上周数据并生成周报草稿
on:tool_use 当某个工具被使用时触发——比如每次查询数据库后,自动记录到审计日志
on:session_complete 会话完成时触发——把结果自动同步到 Craft 文档或 Notion 页面

应用思考

你的团队用 Craft Agents 处理客户支持。每次对话开始,Claude 都需要了解:公司的退款政策、常见问题库、回复语气要求。你最应该怎么做?

你想每周五下午自动生成一份"本周 AI 工具使用报告"发给管理层。在 Craft Agents 架构里,最合适的实现方式是?

04

生产部署

把 Craft Agents 跑起来——从本地开发到 Docker 生产环境

两种运行模式

Craft Agents 有两种运行形态,适合不同场景。就像同一款软件,可以安装到个人电脑上用,也可以部署到公司服务器上让全团队访问:

💻

Electron 桌面应用

个人使用。所有数据存在本地,MCP 工具以子进程方式运行。适合个人效率工具场景。

🐳

Docker Server 模式

团队共享。通过 HTTP 提供服务,WebUI 连接服务端,多人可同时访问同一个 Agent 服务。

🔍
Monorepo 结构意味着什么

Craft Agents 采用 Monorepo 结构,apps/ 目录放可运行的应用,packages/ 目录放共享的代码库。两个应用(electron 和 server)共享同一套核心业务逻辑——改一处,两边都受益。

项目结构地图

理解这个目录结构,你就能告诉 AI"去 packages/messaging-gateway 里修改路由逻辑",而不是让它到处乱找:

craft-agents-oss/ 整个项目根目录
apps/ 可运行的完整应用
electron/桌面客户端(Electron + React)
webui/Web 界面(当后端是 Server 模式时使用)
cli/命令行工具
packages/ 共享的核心代码包
core/类型定义和工具函数(Session、Workspace、Message)
messaging-gateway/命令路由中心——所有操作的入口
server-core/HTTP 服务端核心逻辑
session-mcp-server/让 Agent 感知会话上下文的 MCP 服务
session-tools-core/内置工具函数库
Dockerfile.serverServer 模式的 Docker 构建配置
package.jsonMonorepo 根配置,使用 Bun 管理

代码翻译:Server 启动逻辑

下面是 Craft Agents 在 Server 模式下的启动流程(来自 packages/server-core/src/bootstrap/):

CODE

export async function bootstrap(config: ServerConfig) {
  const gateway = await createGateway(config);
  const transport = new HttpTransport(gateway);
  await transport.listen(config.port);
  return { gateway, transport };
}
            
PLAIN ENGLISH

bootstrap 函数:启动整个服务的入口,像开店前的"开业准备"

先创建 MessagingGateway——注册所有命令处理器,准备好"收件室"

创建 HTTP 传输层——把 Gateway 包装成一个 HTTP 服务,这样浏览器可以连进来

开始监听指定端口,等待外部请求。就像挂出"营业中"牌子

返回 gateway 和 transport 的引用,以便后续可以关闭或查询状态

综合考验

你发现 Craft Agents 里的"工作区切换"逻辑有个 bug,在 electron 版和 server 版里都会复现。你应该去哪里修复它?

你要在 Docker 生产环境部署 Craft Agents,需要配置 ANTHROPIC_API_KEY。最安全的做法是?

🎉
你已经掌握了 Craft Agents 的核心架构!

现在你知道 Session/Workspace 的边界、工具系统的工作原理、技能和自动化的价值,以及如何告诉 AI 在正确的地方做正确的修改。这就是 AI 原生开发者的技术底气。