Flue 技术解读:把大模型装进 Agent Harness
Flue 不是一个聊天 App,也不是 Astro 的页面框架插件。它是一个用 TypeScript 构建 AI Agent 的底层框架,核心目标是把模型、工具、技能、文件系统、沙箱、持久化会话和部署入口装配成一个可运行的 agent。
一、Flue 到底是做什么的?
如果只用一句话概括:Flue 是一个 TypeScript Agent Harness 框架,用来构建可部署、可恢复、能调用工具和进入工作区执行任务的 AI Agent。 它把开发者平时零散拼起来的 LLM 调用、工具函数、上下文、沙箱、会话存储、HTTP 路由和部署目标,收进一个统一的工程模型里。
这和普通的“调一次模型拿一次回答”不一样。Flue 更关注的是让模型在一个持续上下文里工作:它可以先读文件,再调用工具,再根据结果继续行动,必要时把一部分任务交给子 agent,最后把结果返回给你的应用。
它本身没有聊天界面。你用它写 agent,再把 agent 接进自己的网站、Webhook、后台任务或 CI。
Agent、工具、workflow、路由和部署配置都以 TypeScript 为主,适合直接嵌入 Web 应用和服务端工程。
模型只负责生成和推理;harness 提供记忆、工具、文件系统、命令执行、沙箱和恢复机制。
二、用户如何使用 Flue?
Flue 的“用户”需要分成两类:开发者和最终用户。开发者直接使用 Flue 写 agent;最终用户通常并不知道 Flue 的存在,而是通过产品里的聊天框、按钮、Webhook、队列任务或 CI 流程间接触发 agent。
开发者的最小使用路径
官方快速开始给出的路径非常直接:安装 runtime 和 CLI,初始化目标环境,写一个 agent 文件,然后在本地连接它。
npm install @flue/runtime
npm install --save-dev @flue/cli
npx flue init --target node
# 然后创建一个 agent,例如 agents/hello-world.ts
npx flue connect hello-world local
一个最小 agent 长什么样?
最小版本只需要模型和指令。文件名会成为 agent 名称,运行时会发现并加载它。
import { createAgent } from '@flue/runtime';
export default createAgent(() => ({
model: 'anthropic/claude-sonnet-4-6',
instructions: 'Tell a funny "hello world" engineering joke.',
}));
稍微像生产系统一点的 agent
真实项目通常会加上工具、技能、工作目录和沙箱。下面这个伪例子表达的是 Flue 的工程思路:让 agent 在一个受控环境里完成“代码仓库审查”。
import { createAgent } from '@flue/runtime';
import { local } from '@flue/runtime/node';
import reviewChecklist from '../skills/review-checklist/SKILL.md' with { type: 'skill' };
import { repositoryTools } from '../shared/repository-tools.ts';
export default createAgent(() => ({
model: 'anthropic/claude-sonnet-4-6',
instructions: 'Review the change and report findings supported by evidence.',
cwd: '/srv/repositories/catalog-service',
tools: repositoryTools,
skills: [reviewChecklist],
sandbox: local(),
}));
npx flue connect。更常见的方式是:客服系统把 ticket id 映射成 agent id,GitHub webhook 把 issue 评论 dispatch 给 agent,后台 job 启动 workflow,或者你的 Web UI 把用户消息 POST 到 /agents/<name>/<id>。
三、它的原理:Agent = LLM + Harness
Flue 官方文档给出的核心心智模型是:agent 不是“一个聪明 prompt”,而是运行在 harness 里的大语言模型。模型单独存在时,只能接收上下文并生成文本;harness 则给它工作环境、可调用能力和恢复机制。
模型读取当前上下文,决定回答、调用工具、读写文件、运行命令或委派子 agent。
工具是带 schema 的函数,例如查订单、建工单、读取业务数据。参数会校验,真正权限由应用控制。
技能提供可复用说明和步骤,例如审查清单、调试流程、领域知识,不等同于执行代码。
沙箱决定 agent 能看到哪些文件、能不能执行命令、是否直接访问宿主机或远程隔离环境。
继续型 agent 需要会话历史、输入队列和事件流。中断后能否恢复,取决于目标环境和数据库适配器。
Flue 支持 Node.js、Cloudflare 等目标。应用负责认证、授权、触发入口和外部副作用治理。
工具为什么不是“随便给模型一个 API key”?
Flue 的工具通过 defineTool(...) 定义,包含名称、描述、参数 schema 和 execute 函数。模型只能选择参数;真正使用哪个用户、哪个仓库、哪个 ticket、哪组凭据,应该由你的应用在工具闭包或 agent id 里绑定。
import { defineTool } from '@flue/runtime';
import * as v from 'valibot';
export const lookupOrderStatus = defineTool({
name: 'lookup_order_status',
description: 'Look up the current fulfillment status for one order ID.',
parameters: v.object({
orderId: v.string(),
}),
execute: async ({ orderId }) => {
return await orders.getStatus(orderId);
},
});
沙箱承担什么职责?
| 沙箱类型 | 适合场景 | 关键边界 |
|---|---|---|
| Virtual sandbox | 默认轻量工作区,适合应用主动提供输入文件、让 agent 处理后取回输出。 | 内存型工作区,不等同于完整 Linux 环境,也不是持久文件系统。 |
| Local sandbox | 可信开发工具、一次性 CI runner、需要直接操作宿主 checkout 的任务。 | 不是隔离边界。模型驱动的文件和命令访问会触达宿主机。 |
| Remote sandbox | 不可信请求、多租户任务、需要独立生命周期和 Linux 工具链的编码任务。 | 工作区、凭据、网络、生命周期仍需应用或平台策略管理。 |
持久化执行解决什么问题?
Agent 一旦能调用外部工具,就会遇到“执行到一半服务重启”的问题。简单重放可能导致重复发消息、重复建工单或重复付款。Flue 的 durable agent 思路是把 session history、输入队列和事件记录下来,在恢复时尽量保守地判断:能确认没执行过才重试,已经完成的结果要保留,结果不确定的外部动作不能盲目再跑一遍。
Cloudflare 目标会利用 Durable Object 和 SQLite 提供更强的默认恢复能力;Node.js 目标默认以内存为主,如果要跨重启保存状态,需要配置数据库适配器。这个设计很重要,因为它把“会话可恢复”和“文件工作区可恢复”拆成了两个不同问题。
四、什么时候适合用 Flue?
Flue 适合那些“模型不能只回答,还要持续行动”的场景。换句话说,如果你的需求需要上下文、工具、文件、命令、恢复和部署入口一起工作,Flue 的抽象就开始有价值。
| 场景 | 是否适合 | 原因 |
|---|---|---|
| 客服 ticket 助手 | 适合 | 每个 ticket 可以映射为一个 agent id,工具按 ticket 范围授权,会话能持续跟进。 |
| GitHub issue triage | 适合 | 需要读仓库、运行命令、调用 GitHub API、记录过程,并处理异步 webhook。 |
| 一次性文本摘要 | 不一定需要 | 如果只是单次模型调用,普通 SDK 或轻量 workflow 足够。 |
| 多租户自动编码平台 | 谨慎适合 | 需要 remote sandbox、严格授权、配额、审计、幂等和资源生命周期管理。 |
| 公司内部 agent 平台 | 适合 | Flue 的 headless API 可以接入内部系统,把不同 agent 变成统一运行模型。 |
工程实践建议
不要先写万能工具。先决定一个 agent 实例代表哪个用户、ticket、仓库或租户。
让工具执行明确动作,例如“查询当前 ticket 的订单”,而不是暴露任意数据库查询。
本地沙箱适合可信工作流;多租户和外部输入应优先考虑远程隔离环境。
凡是会发消息、创建记录、扣款或修改状态的工具,都应该有应用侧幂等键和审计记录。
- createAgent
- defineTool
- skills
- subagents
- virtual sandbox
- local()
- dispatch()
- durable session
- Node.js target
- Cloudflare target
五、和“普通 LLM 应用”的差异
普通 LLM 应用往往是“用户输入 → 模型输出”。Flue 的重点则是“应用输入 → agent 进入上下文 → 根据环境行动 → 把过程和结果沉淀回来”。这个差异会影响你如何设计系统。
| 维度 | 普通 LLM 调用 | Flue 式 Agent |
|---|---|---|
| 控制方式 | 开发者硬编码步骤,模型主要负责生成。 | 开发者定义边界和能力,模型在循环里决定路径。 |
| 上下文 | 通常由一次请求携带,结束后丢失或手动保存。 | agent instance 有持续会话,可以被后续输入重新打开。 |
| 行动能力 | 少量函数调用,通常围绕单个请求。 | 工具、文件、命令、技能和子 agent 一起构成工作环境。 |
| 失败恢复 | 由应用自己处理,容易出现重复副作用。 | 框架提供 durable agent 机制,但应用仍需处理外部幂等。 |
六、参考资料
本文基于官方仓库和文档梳理,并结合 agent harness 工程实践做了解读。
一句话结论
Flue 的真正价值不是“帮你更方便地调模型”,而是把模型放进一个有工具、有边界、有状态、有恢复能力的运行环境里。对开发者来说,你写的不是一步步脚本,而是一个 agent 能安全工作的舞台。