Bun+DeepSeek:TypeScript构建你的第一个AI Agent
从 Bun 到 DeepSeek:用 TypeScript 构建你的首个 AI Agent
开篇
2026 年,AI Agent 稳坐技术圈最炙手可热的赛道。Claude Code、Cursor 以及各类自主框架,底层无一例外依赖高性能运行时。
Bun 作为 Claude Code 选定的 JS/TS 运行时,正在成为 AI Agent 开发的事实标准。
这篇内容面向具备 JS/TS 基础的开发者,核心围绕四个环节:
- 为何 AI Agent 倾向于 Bun + TypeScript 组合?
- 如何借助 Bun 调用 DeepSeek 大模型?
- 怎样从单次调用演进到多轮对话、流式输出以及 Tool Calling?
一、AI Agent 为何选定 Bun + TypeScript?
1.1 Bun 的本质是什么?
一句话总结:Bun 是比 Node.js 更快、即装即用、零配置的 JS/TS 运行时,同时内置包管理器。
| 特性 | Node.js | Bun |
|---|---|---|
| 启动速度 | 偏慢 | ⚡ 极速 |
| TypeScript 支持 | 需编译 ts → js | ✅ 原生支持,零配置 |
| 包管理器 | npm / pnpm | 内置 bun install,快 10-100 倍 |
| 内置 fetch | 需 node-fetch 扩展 | ✅ 原生支持 |
| 环境变量读取 | 需 dotenv 模块 | ✅ 原生 --env-file |
1.2 Claude Code 为何相中 Bun?
Claude Code 底层运行时正是 Bun。当你用 Claude Code 编写代码、运行测试时,背后由 Bun 驱动。原因清晰直白:
- 启动快 — Agent 需频繁启停进程,启动速度是硬性门槛。
- 原生 TS — AI Agent 项目几乎全用 TypeScript,零配置即可执行,省去编译步骤。
- 轻量级 — 资源占用低,适合大规模分布式部署。
1.3 为什么 AI Agent 必须依赖 TypeScript?
AI Agent 处理的数据结构极其复杂:消息列表、工具调用、API 响应。Ja vaScript 的弱类型会使 bug 潜伏在系统中难以察觉:
<input type="text" id="ipt"><script>const ipt = document.getElementById('ipt');ipt.addEventListener('change', function(event) { console.log(event.target.value, typeof event.target.value); // "123" + 1 = "1231"而非 124});script>
TypeScript 的静态类型检查能在编码阶段拦截约 80% 的错误:
function add(a: number, b: number): number {return a + b;}add(1, "2"); // ❌ 编译报错!类型不兼容add(1, Number("2")); // ✅ 显式类型转换
因此,所有主流 AI Agent 框架不约而同选择 TypeScript 便不足为奇。
二、环境搭建
# 安装 Bun(Windows 环境)powershell -c "irm bun.sh/install/windows | iex"# 也可通过 npm/pnpm 安装npm i -g bunpnpm i -g bun# 初始化项目bun init
项目结构:
my-ai-agent/├── .env# 环境变量(API Key)├── .gitignore# 忽略 .env 和 node_modules├── package.json├── tsconfig.json├── src/│ ├── index.ts# 入口文件│ ├── chat.ts # 对话逻辑│ ├── tools/# 工具定义│ │ └── weather.ts│ └── types.ts# 类型定义└── bun.lock
环境变量配置:
# .envDEEPSEEK_BASE_URL=https://api.deepseek.com/chat/completionsDEEPSEEK_API_KEY=sk-xxxxxxxxxxxxx
务必在 .gitignore 中添加 .env,防止密钥泄露。
三、异步编程速览
AI Agent 的核心即异步——发送请求、等待响应、处理流式数据,全部是异步操作。
Promise 三种状态
| 状态 | 含义 | 触发方式 |
|---|---|---|
pending | 进行中 | 初始状态 |
fulfilled | 已成功 | 调用 resolve(value) |
rejected | 已失败 | 调用 reject(error) |
async/await:让异步代码如同步般简洁
function sleep(t) {return new Promise((resolve) => setTimeout(resolve, t));}async function main() {console.log('--start--');await sleep(2000); // 暂停 2 秒,等待 Promise 完成console.log('--end--');}main();
await 用于暂停当前 async 函数执行,待 Promise 落定后继续。
Promise.all:并行执行多个异步任务
AI Agent 常需同时调用多个 Tool,借助 Promise.all 实现并行化:
// ❌ 串行 — 总耗时 = 2s + 3s = 5sconst weather = await getWeather('北京');const news = await getNews('科技');// ✅ 并行 — 总耗时 = max(2s, 3s) = 3sconst [weather, news] = await Promise.all([getWeather('北京'),getNews('科技')]);
四、实战:调用 DeepSeek 大模型
4.1 方式一:Bun 内置 fetch(零依赖,推荐)
// fetch-demo.ts// 运行:bun run --env-file=.env fetch-demo.tsasync function chat() {try {// 1. 环境变量校验const baseUrl = process.env.DEEPSEEK_BASE_URL;const apiKey = process.env.DEEPSEEK_API_KEY;if (!baseUrl || !apiKey) {throw new Error('请检查 .env 文件中 DEEPSEEK_BASE_URL 和 DEEPSEEK_API_KEY');}// 2. 超时控制:30 秒无响应自动取消const controller = new AbortController();const timeout = setTimeout(() => controller.abort(), 30000);const res = await fetch(baseUrl, {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': `Bearer ${apiKey}`},body: JSON.stringify({model: 'deepseek-v4-flash',messages: [{role: 'user',content: '你好,介绍一下Bun'}]}),signal: controller.signal});clearTimeout(timeout);// 3. 检查 HTTP 状态码if (!res.ok) {throw new Error(`HTTP ${res.status}: ${await res.text()}`);}// 4. 防御性取值const data = await res.json();const content = data?.choices?.[0]?.message?.content;if (!content) {console.error('响应格式异常:', JSON.stringify(data, null, 2));return;}console.log(content);} catch (err: any) {if (err.name === 'AbortError') {console.error('请求超时,请检查网络或稍后重试');} else {console.error('请求失败:', err.message);}}}chat();
为什么力荐 fetch?理由简洁:零依赖、更轻量、符合 Web 标准。
4.2 方式二:Axios(企业级方案)
若需要拦截器、自动重试、请求取消等进阶功能,Axios 是更优解:
// index.tsimport axios from "axios";import dotenv from "dotenv";dotenv.config();async function chat() {try {const baseUrl = process.env.DEEPSEEK_BASE_URL;const apiKey = process.env.DEEPSEEK_API_KEY;if (!baseUrl || !apiKey) {throw new Error('请检查 .env 文件中的 DEEPSEEK_BASE_URL 和 DEEPSEEK_API_KEY');}const res = await axios.post(baseUrl,{model: 'deepseek-v4-flash',messages: [{role: 'user',content: '你好,介绍一下Bun'}]},{headers: {'Content-Type': 'application/json','Authorization': `Bearer ${apiKey}`},timeout: 30000});const content = res.data?.choices?.[0]?.message?.content;if (!content) {console.error('响应格式异常:', JSON.stringify(res.data, null, 2));return;}console.log(content);} catch (err: any) {if (err.response) {console.error(`HTTP ${err.response.status}:`, err.response.data);} else {console.error('请求失败:', err.message);}}}chat();
bun run index.ts
五、从“能调用”到“会对话”:三个进阶能力
单次 API 调用仅是起点,真正的 AI Agent 必须具备以下三项能力:
5.1 多轮对话:维护消息列表
AI 模型天生无状态,每次请求均需携带完整历史消息:
const messages: Array<{role: string; content: string}> = [{ role: 'system', content: '你是一个友好的AI助手' },{ role: 'user', content: '你好!' },// 模型回复后,将回复也加入 messages// { role: 'assistant', content: '你好!有什么可以帮你的?' },// { role: 'user', content: '介绍一下Bun' },];
每次用户发送消息,将新条目追加到 messages 数组,再将整个数组发送给模型。多轮对话的奥妙正在于此。
5.2 流式输出(SSE)
大模型生成回复需要时间,若等待全部完成再展示,体验大打折扣。流式输出让模型边生成边推送:
const res = await fetch(url, {method: 'POST',headers: { /* ... */ },body: JSON.stringify({model: 'deepseek-v4-flash',messages: messages,stream: true // 启用流式输出})});// 逐块读取响应const reader = res.body?.getReader();const decoder = new TextDecoder();while (true) {const { done, value } = await reader!.read();if (done) break;const chunk = decoder.decode(value);const lines = chunk.split('n').filter(line => line.startsWith('data: '));for (const line of lines) {const data = line.replace('data: ', '');if (data === '[DONE]') break;const parsed = JSON.parse(data);process.stdout.write(parsed.choices[0]?.delta?.content || '');}}
5.3 Tool Calling:让 AI 拥有“动手能力”
真正的 AI Agent 不止于聊天,它能主动调用工具:
const tools = [{type: 'function',function: {name: 'get_weather',description: '获取指定城市的天气',parameters: {type: 'object',properties: {city: { type: 'string', description: '城市名称' }}}}}];
这就是 AI Agent 的核心循环:
用户输入 → 模型理解意图 → 选择工具 → 执行工具 → 将结果反馈给模型 → 继续推理
六、总结
| 知识点 | 作用 |
|---|---|
| Bun | 高性能运行时,AI Agent 的底层引擎 |
| TypeScript | 类型约束,减少 80% 运行时错误 |
| async/await | 异步编程基石,处理网络请求 |
| fetch / axios | 调用 LLM API 的两种方式 |
| 消息列表 | 多轮对话的核心数据结构 |
| 流式输出 | 提升用户体验的关键技术 |
| Tool Calling | 从“聊天机器人”进化为“AI Agent” |
Bun + TypeScript 正成为 AI Agent 开发的黄金搭档。Claude Code 选择 Bun 作为底层运行时,已充分验证这条技术路线的可行性。
现在就开始你的第一个 AI Agent 吧!
七、学习资源
运行时 & 工具
- Bun 官方文档 — 安装、API、配置全覆盖
- TypeScript 官方手册 — 类型系统深入学习
- Axios 官方文档 — HTTP 请求库进阶用法
AI & LLM
- DeepSeek 开放平台 — API 文档、模型列表、价格说明
- DeepSeek API 对话示例 — 多轮对话、流式输出、Tool Calling 官方示例
- OpenAI API 规范 — DeepSeek 兼容 OpenAI 格式,可参考其文档
AI Agent 开发
- Anthropic Claude Code — 了解 Bun 在 AI Agent 中的实际应用
- Vercel AI SDK — 前端友好的 AI 流式输出方案
- LangChain.js — TypeScript AI Agent 框架
推荐阅读
- Bun vs Node.js 性能对比 — 官方基准测试
- MDN Fetch API — Web 标准请求 API
- SSE 协议详解 — 流式输出底层原理
