Flue 2.0 现已正式发布。我们围绕全新的基于 Hook 的 API 重构了 Agent 框架,解锁了一种全新的动态 Agent 能力,可以随时间演进其功能。
Agent Hook 是 Flue 2.0 的全新基础。Hook 让你构建的动态 Agent 能够管理自身状态、监听 Agent 生命周期事件,甚至在运行时动态附加不同的资源和能力来增强自身。
Hook 使用 TypeScript 编写,API 形式非常熟悉:
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.`;
}
借助动态 Agent,能力和指令可以随着对话的发展而增长和演进。一个客服 Agent 可以遵循多步工作流,在客户验证通过后获得新的工具,或者在任务变难时切换到更强的模型。我们构建 Flue 2.0 是因为我们需要在 Agent 中实现非平凡的功能,而现有的 Harness(运行时环境)和框架都没有好的方式来实现它们。
Flue 2.0 包含:
- 16 个内置 Hook ——
useSkill()、useTool()、useSubagent()等。 - 自定义 Hook —— 将能力打包为可组合、可共享的单元。
- 全新 CLI —— 本地 Agent 可在终端和 CI 中通过
flue run运行。 - 全新 Vite 架构 —— 托管 Agent 现在直接使用 Vite 构建。
- 内置无状态 MCP —— 将 MCP 服务器的工具挂载到你的 Agent 中。
- 200+ 修复和改进 —— Flue 2.0 是我们的首个稳定版本。
立即将下面的提示词传递给你的编码 Agent 来体验 Flue 2.0,它将帮你搭建第一个 Flue 项目:
Read https://flueframework.cn/start.md then help create my first agent...
更喜欢自己动手?请阅读入门指南。从 Flue 1.0 Beta 升级现有项目?迁移指南将引导你完成整个过程。
Agent Hook
在最初的 Flue 1.0 API 中,我采用了与其他所有 Agent 框架和 SDK 相同的静态方法来构建 Agent 架构。OpenAI SDK、Anthropic SDK、Cursor SDK、Eve、Mastra 等都将“Agent 定义”视为某种静态的、类似配置的东西,预先定义好然后在构建时锁定:
// Flue 1.0 API
export default defineAgent(() => ({
model: 'moonshot/kimi-k2',
tools: [replyToIssue],
skills: [triage, verify],
sandbox: local(),
instructions,
}));
在 Flue 1.0 Beta 期间,我们与真实开发者一起深度使用了这个 API。结果出人意料:静态 Agent 方法对简单用例效果很好,但对于更复杂、非平凡的 Agent 和多步工作流,就开始捉襟见肘了。
我们开始思考:如果 Flue 1.0 存在这个问题,那么有多少其他流行的 Agent 框架和 SDK 也同样存在这个问题?
我们认定这是一个值得解决的问题,而且现在正是做出破坏性变更的最佳时机 —— 趁我们还处于早期阶段。我们尝试了很多不同的方法,最终一个熟悉的设计模式逐渐浮现:
// Flue 2.0 API
export function IssueTriageAgent() {
useModel('moonshot/kimi-k2');
useTool(replyToIssue);
useSkill(triage);
useSkill(verify);
useSandbox(local());
return instructions;
}
我上周开玩笑地将其称为“Agent 版的 React?”,灵感来源不言而喻。但我也认为这低估了我们自然而然走到这一步的程度。React Hook 被发明出来解决的同样问题,也适用于 Agent:如何在最低、最根本的层面组合功能?如何使其自然、富有表现力且易于维护?
Agent Hook 为托管 Agent 和工作流开启了全新的可能性。
假设你想让 Agent 能够按需升级其初始模型或 Sandbox。在 Flue 1.0 和其他流行的 Agent Harness 中,这并非易事。而在 Flue 2.0 中,只需几行代码:
export function CompanySlackAgent() {
// 为每个 Agent 附加持久化数据,存储在你的数据库中。
const [isEnhanced, setEnhanced] = usePersistentState('isEnhanced', false);
// 赋予 Agent 自我升级的能力。
useTool({ name: 'enhance', description: '...', run: () => setEnhanced(true) });
// 按需附加新能力。
if (isEnhanced) {
useModel('anthropic/fable-5-0');
useSandbox(daytona());
useTool(/* ... */);
useSkill(/* ... */);
useSubagent(/* ... */);
} else {
useModel('moonshot/kimi-k2');
}
// 返回你的 Agent 指令。Flue 处理其余一切。
return `You are a helpful assistant.`;
}
或者你想在 Agent 中表示一个类似状态机的工作流,引导 Agent 完成复杂的多步流程。使用静态 Agent,你没有好的方式来跟踪工作流中的当前步骤,或者根据当前步骤选择性地提供工具。
在 Flue 2.0 中,工作流就是持久化状态加上条件工具。为每个步骤赋予其专属的工具和 Skill,让 Agent 自行推进。下面是之前同一个分类 Agent,已扩展为完整的工作流:
export function IssueTriageAgent({ id }) {
useSandbox(local());
// 持久化记录 Agent 当前所处的工作流步骤。
const [step, setStep] = usePersistentState('step', 'reproduce');
// 每个步骤附加自己的工具和 Skill。
if (step === 'reproduce') {
useModel('anthropic/sonnet-5-0');
useSkill(reproChecklist);
useTool({ name: 'submit_repro', description: '...', run: () => setStep('diagnose') });
}
if (step === 'diagnose') {
useModel('anthropic/fable-5-0');
useSkill(debuggingGuide);
useTool({ name: 'submit_diagnosis', description: '...', run: () => setStep('report') });
}
if (step === 'report') {
useModel('anthropic/sonnet-5-0');
useTool(postGitHubComment);
}
return `Follow the workflow to triage GitHub issue ${id}: reproduce -> diagnose -> report.`;
}
内置 Hook 提供了增强 Agent 新能力和资源的功能,如 useTool()、useSandbox() 和 useMcpConnection()。Hook 还提供持久化状态(usePersistentState())、生命周期事件(useAgentStart())等。
就像 React Hook 一样,它们可以很好地组合在一起。你可以构建自己的自定义 Hook,在你的代码库、公司内或通过 npm 与全世界共享。
export function useLinear(apiKey) {
useMcpConnection({
name: 'linear',
url: 'https://mcp.linear.app/mcp',
auth: apiKey,
});
}
export function ProjectAssistant() {
useLinear(process.env.LINEAR_API_KEY);
useGitHub(process.env.GITHUB_API_KEY);
useBrowser();
return 'Help your team manage their work.';
}
请阅读 Agent Hook 指南开始使用 Hook 构建,或在 API 参考文档中探索所有内置 Hook。
2.0 的其他更新
此版本还包含一系列其他变更和功能,旨在简化使用 Flue 构建 Agent 的体验。亮点如下:
托管 Agent 使用 Vite 构建。 flue dev 和 flue build CLI 命令已移除:Flue 应用现在是一个普通的 Vite 项目,在 vite.config.ts 中配置 flue() 插件,在 app.ts 中通过 Hono 应用显式挂载 Agent 路由。vite dev 运行开发服务器,vite build 生成可部署到 Node.js 或 Cloudflare(通过官方 @cloudflare/vite-plugin)的产物,flue init 搭建整个配置。这是本版本的一个主题:凡是生态系统已有更好方案的地方,Flue 就删除自己的接口 —— Vite 负责构建,Hono 负责路由,Pi 负责 Provider(服务提供商)。
MCP 支持已内置。 新的 useMcpConnection() Hook 可将远程 MCP 服务器的工具直接挂载到你的 Agent 中。连接是无状态的(在 Cloudflare Workers 上运行良好),可以标记为可选,这样当服务器不稳定时会优雅降级而不是导致运行失败,并且 —— 因为连接只是一个 Hook —— 可以有条件地附加或像其他任何东西一样打包成自定义 Hook。
Workflow 和 Action 已简化。 defineWorkflow() 已移除,因为持久性使其变得多余:Agent 接受的每条消息都会精确结算一次,即使经历崩溃、重启和重新部署。工作流现在只是运行 Agent 的任何脚本 —— CI 任务中的 flue run、Node.js 脚本中的 init() 句柄,或平台工作流引擎中的一个步骤(Cloudflare Workflows、Inngest、Temporal)。对于 Agent 内需要检查点的副作用,工具可以启用 durable: true 并通过 step.do() 记录进度。Workflow 指南涵盖了所有模式。
全新的会话级 SDK。 每个对话都有一个 URL,新的 @flue/sdk 客户端精确封装一个对话:send() 发送消息、read() 读取已结算的回复、observe() 实时观察更新、abort() 中止工作。消息现在携带带类型的 purpose 和 display 元数据,客户端无需猜测即可区分用户聊天和内部活动。在前端,@flue/react 的 useFlueAgent({ url }) 将同一个对话流式传输到你的 UI 中。
Cloudflare 零配置追踪。 将 Agent 部署到 Cloudflare,启用 Workers Traces,无需任何埋点代码即可追踪每个对话的内容、元数据、Token 成本等。查看我们的生态系统,接入你已有的任何其他可观测性体系。
立即体验 Flue 2.0
理解 Flue 最好的方式就是用它来构建。请阅读完整的入门指南和迁移指南,或将下面的提示词交给你的编码 Agent 来搭建你的第一个项目:
Read https://flueframework.cn/start.md then help create my first agent...
想要支持这个项目? 在 GitHub 上给我们 Star,这是表达支持和帮助 Flue 成长最简单的方式。
想要了解最新动态? 关注 @flueai 获取更多技巧和开发更新。