入门 📋 6 个步骤 第 419 / 470 篇

用 Flue 2.0 写一个 TypeScript Agent:Agent Hooks 与崩溃可恢复实战

Astro 团队开源的 Flue 2.0 上手:用 React 风格 Hooks 写 Agent,加持久状态跨重启不丢,挂 MCP 工具与沙箱,并用 Vite 构建部署。

2026.09.13· 24 分钟阅读· 约 1877 字· 🧩 Flue 2.0 / 🟦 TypeScript

TypeScript 生态里做 Agent,过去要么自己拼 SDK,要么接受一套静态配置式的框架。2026 年 9 月,Astro 团队开源了 Flue 2.0:一个用 React 风格 Hooks 写 Agent 的 TypeScript 框架,主张把 Agent 写成函数、把能力写成 Hook,并默认带上「崩溃可恢复」的持久化。这篇教程带你从空目录跑通一个能记状态、能挂 MCP 工具、能部署上线的 Agent。

🎯 适合人群:有 JavaScript / TypeScript 基础、想用一套统一写法做 Agent 的前后端开发者。需要 Node 20+ 与一个模型 API Key。不需要 Python 环境。

先理解:Agent Hooks 是什么思路

传统 Agent SDK 把 Agent 当成一个静态对象:一次性声明模型、工具、系统提示,运行期间不再变化。Flue 2.0 反过来,把 Agent 写成一个函数,函数体里调用 Hook 来组合能力:

export function Assistant() {
  const [count, setCount] = usePersistentState('count', 0);
  useAgentStart(() => setCount((n) => n + 1));
  useModel('moonshot/kimi-k2');
  return `You are a helpful assistant. This conversation has ${count} messages.`;
}

这个写法带来四种传统框架不好表达的模式:动态升级能力(任务变难时换更大的模型)、有状态流程(用持久状态记录多步进度)、条件工具(按运行时条件挂不同工具)、自定义 Hook(把可复用能力打包成可分享单元)。框架内置 16 个 Hook,常用的有 useModel()、useTool()、useSkill()、useSandbox()。

Hook作用
useModel()指定本阶段使用的模型与提供方
useTool()注册一个可被模型调用的工具
useSkill()挂载一份可复用的技能说明或流程
useSandbox()给 Agent 一个能跑命令、改文件的安全环境
usePersistentState()崩溃、重启、重新部署后依然存在的状态

Step 1:初始化项目与安装依赖

1 两个包就能起步
# 新建目录并初始化
mkdir my-flue-agent && cd my-flue-agent
npm init -y

# 装运行时与 CLI
npm install @flue/runtime @flue/cli

# 确认 CLI 可用
npx flue --help

Flue 2.0 属于较新的开源项目,版本迭代较快。安装后请记录 package.json 里两个包的实际版本号,并在官方文档确认 Hook 名称与参数签名。本教程示例来自官方公开说明,若与最新文档不一致,以官方文档为准。

Step 2:写一个最小 Agent

2 一个文件、一个函数、一句指令

新建 src/agents/assistant.ts。文件开头的 'use agent' 是框架指令,用来标记这个模块是一个 Agent 定义:

'use agent';
import { useModel } from '@flue/runtime';

export function Assistant() {
  useModel('anthropic/claude-haiku-4-5');
  return 'You are a helpful assistant. Keep replies short.';
}

函数返回的字符串就是系统提示。注意它可以直接引用外部变量,这让「提示词随状态变化」变成了很自然的事,而不是拼字符串的苦力活。

💡 模型标识采用 提供方/模型名 的形式,底层由 Pi 提供多模型接入(覆盖 Anthropic、OpenAI、Moonshot 等)。具体可用标识请查官方文档的模型列表,不要凭记忆写。

Step 3:本地跑起来

3 用 CLI 直接对话
npx flue run src/agents/assistant.ts --message "Say hello"

看到模型回复就算跑通了。这一步的价值在于:它把「框架是否装对」「模型 Key 是否可用」「Agent 定义是否合法」三件事一次性验证完,后面再出问题就不用怀疑环境。

API Key 只放环境变量。不要把 Key 写进 .ts 文件或提交到 Git。本地用 .env 并加进 .gitignore,部署时用平台的环境变量配置项注入。

Step 4:加持久状态,让流程跨重启不丢

4 usePersistentState 记录多步进度

这是 Flue 2.0 和多数轻量框架拉开差距的地方:会话被记录在持久流里,运行时重启后会自动恢复,不需要你自己写恢复逻辑。下面这个「GitHub Issue 分诊」Agent 用持久状态记住走到哪一步:

export function IssueTriageAgent({ id }) {
  useSandbox(local());
  const [step, setStep] = usePersistentState('step', 'reproduce');

  if (step === 'reproduce') {
    useModel('anthropic/sonnet-5-0');
    useSkill(reproChecklist);
    useTool({ name: 'submit_repro', run: () => setStep('diagnose') });
  }
  if (step === 'diagnose') {
    useModel('anthropic/fable-5-0');
    useSkill(debuggingGuide);
    useTool({ name: 'submit_diagnosis', run: () => setStep('report') });
  }
  if (step === 'report') {
    useModel('anthropic/sonnet-5-0');
    useTool(postGitHubComment);
  }

  return `Follow the workflow to triage GitHub issue ${id}.`;
}

这段代码里有三个值得借鉴的设计:按阶段换模型(复现阶段用推理更强的模型,报告阶段换更快的)、按阶段换技能(每一步只加载当下需要的说明,控制上下文长度)、用工具推进状态(submit_repro 的副作用就是把状态推到下一步)。

💡 「按阶段换模型」是省钱又提质的小技巧。复现、诊断这类需要深度推理的阶段用强模型;写评论、整理格式这类确定性工作换轻量模型,成本能明显下降。

Step 5:挂 MCP 工具与沙箱

5 复用已有的 MCP 生态

Flue 支持从任意 Model Context Protocol 服务器挂载工具,也支持给 Agent 一个沙箱来执行命令、编辑文件。这意味着你在别处已经写好的 MCP Server 可以直接复用,不必为框架重写一遍。

export function OpsAssistant() {
  useModel('anthropic/claude-haiku-4-5');
  // 从 MCP 服务器挂载工具(具体 API 以官方文档为准)
  useMcp('filesystem', { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', './data'] });
  useSandbox(local());   // 给 Agent 一个可执行命令的环境
  return 'You are an ops assistant. Use the filesystem tools to inspect ./data before answering.';
}

沙箱 + 文件系统工具是高风险组合。给 Agent 的命令执行能力必须限制在专用目录,生产环境建议跑在容器或独立主机里,并明确网络出口策略。不要把它指向你的代码仓库根目录或家目录。

Step 6:构建与部署

6 Vite 构建,Hono 路由

Flue 用 Vite 做构建、Hono 做路由,接进现有工程只需要加一个插件:

// vite.config.ts
import { flue } from '@flue/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [flue()],
});

部署目标覆盖 Cloudflare Workers、Node.js、Docker、AWS、Vercel、Railway;渠道侧可接 Slack、Discord、GitHub、Telegram、WhatsApp、Microsoft Teams 等 20 多个平台;存储侧支持 PostgreSQL、Redis、MongoDB、MySQL、Supabase;可观测性对接 OpenTelemetry、Braintrust、Sentry。

💡 选择存储时要和「持久状态」对齐。框架承诺崩溃后能恢复,前提是状态有地方落。生产环境请把持久化后端配好,别用内存态跑关键流程。

常见问题 FAQ

Q1:Flue 和其他 TypeScript Agent 框架怎么选?

判断标准可以简化为三条:是否需要崩溃恢复(长流程、关键任务)、是否需要运行期动态换能力(按阶段换模型或工具)、是否希望用熟悉的 React 心智模型写 Agent。三条里中两条以上,Flue 的写法会明显省事;如果只是一次性问答,用更轻的 SDK 就够了。

Q2:必须用 Astro 吗?

不需要。Flue 与 Astro 同源但独立,构建走 Vite,路由走 Hono,可以接进任意前端工程或纯 Node 服务。

Q3:Hooks 在函数体里调用,会不会有 React 那套调用顺序限制?

写法上确实借鉴了 Hooks 的组合方式,但 Agent 的执行模型与 React 渲染不同。建议保持「同一阶段内 Hook 调用顺序稳定」的习惯,避免在条件分支里随机增删 Hook,这样行为最可预测。框架的精确语义请以官方文档为准。

Q4:能接本地模型吗?

可以走 OpenAI 兼容端点或 Ollama 这类本地推理服务。目前官方及行业暂未披露更多细节,后续将持续跟进迭代动态。

← 返回教程中心