Skip to content

第 1 章 · Flue 概述与 Harness 理念

本章目标:理解从"裸 LLM API 调用"到"自主 Agent"的架构演进,弄清 Harness(马具架)到底是什么,掌握 Flue 的核心特性全景。

1.1 从裸 API 到自主 Agent 的三代演进

第一代:裸 LLM API 调用。 你把提示词发给模型、拿回一段文本。它能写诗、能翻译,但每一步都要人来驱动——它不会自己查数据库、不会自己重试、也没有记忆。

typescript
// 第一代:一次请求一次响应,模型只能"说话",不能"做事"
const response = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    model: 'claude-sonnet-4-6',
    max_tokens: 1024,
    messages: [{ role: 'user', content: '帮我看看 issue #42 是什么问题' }],
  }),
});
// 模型只能回答"我无法访问你的 GitHub"——它没有任何行动能力

第二代:脚本化工作流。 你在代码里写死步骤:先调摘要接口、再调分类接口、最后写库。可靠但僵硬——任何计划外的输入都会让流程崩掉。

第三代:自主 Agent。 Claude Code、Codex 这类产品证明了一件事:给模型一个目标而不是一串步骤,让它自主决定调用哪些工具、循环迭代直到完成——它能完成远超脚本的复杂任务。

1.2 Harness:让模型真正能干活的那套"马具"

一匹好马没有马具拉不动车;一个强模型没有 Harness 也干不了活。Harness 就是围绕 LLM 的那层运行时基础设施

组成部分作用
会话(Session)让对话有持久状态,跨轮次记住上下文
工具(Tools)让模型能调用你的应用代码、影响外部系统
技能(Skills)按需加载的领域知识,教它"怎么做某类事"
沙箱(Sandbox)安全的文件与命令执行环境
循环控制处理工具调用→结果回传→继续推理的循环

一句话理解

LLM 是发动机,Harness 是整车——方向盘、油门、刹车、仪表盘。Flue 要做的就是把造车这件事标准化。

1.3 Flue 是什么

Flue 是 Astro 团队打造的开源 Agent Harness 框架。它的核心洞察是:用 React 的心智模型来写 Agent——Agent 就是一个函数,能力通过 Hook 组合进来:

typescript
// 一个完整的 Flue Agent 长这样——是不是很像 React 组件?
'use agent';
import { useModel, useSandbox, useSkill, useTool } from '@flue/runtime';
import { local } from '@flue/runtime/node';
import triage from '../skills/triage/SKILL.md';
import verify from '../skills/verify/SKILL.md';
import { openIssue, searchCode } from '../tools/github.ts';

// Agent 即函数:函数体声明能力,返回值就是任务指令
export function Triage() {
  useModel('anthropic/claude-sonnet-4-6'); // 选模型
  useSandbox(local());                     // 给它本地沙箱
  useSkill(triage);                        // 挂载分诊技能
  useSkill(verify);                        // 挂载验证技能
  useTool(openIssue);                      // 挂载 GitHub 工具
  useTool(searchCode);

  // 返回值成为 agent 的 system instructions(系统指令)
  return `
分诊一个 bug 报告:复现问题、定位根因、
判断该行为是否符合预期,并尝试修复。`;
}

1.4 核心特性总览

特性说明对应 Hook / 包
Agents自主完成目标的智能体,跨对话保持上下文'use agent' 函数
Models接入任意 Pi 支持的 Provider(Anthropic/OpenAI/DeepSeek 等)useModel()
Tools类型安全的应用代码调用defineTool() + useTool()
Skills开放 Agent Skills 格式的可复用技能包useSkill()
Subagents专家子代理委派useSubagent()
Sandboxes本地/远程容器执行环境useSandbox()
Durability崩溃与重启后恢复任务进度内置持久化
ChannelsSlack/Teams/Discord/GitHub 等事件接入src/channels/
MCP连接开放 MCP 工具生态useMcpConnection()
ObservabilityOpenTelemetry/Sentry 等遥测导出@flue/opentelemetry

部署同样灵活:Node.js、Cloudflare Workers、GitHub Actions、GitLab CI/CD、Render 都是一等公民。

1.5 技术栈与包结构

Flue 构建在 Pi(Earendil Works 的 agent 运行时)之上,复用其全部 Provider 支持。核心包分工明确:

text
@flue/runtime        # 核心:harness、sessions、tools、sandbox
@flue/vite           # Vite 插件:vite dev / vite build 构建
@flue/cli            # flue 命令行:本地运行、项目初始化
@flue/sdk            # 客户端 SDK:消费已部署 agent 的对话
@flue/opentelemetry  # OpenTelemetry 追踪适配器
@flue/postgres       # Postgres 持久化适配器
typescript
// 典型的开发依赖安装
// npm install @flue/runtime @flue/cli
// 部署时追加:
// npm install @flue/vite hono vite

// flue.config.ts —— 项目级配置,target 决定构建目标
import { defineConfig } from '@flue/runtime/config';

export default defineConfig({
  target: 'node', // 或 'cloudflare'
});
typescript
// 部署形态下的最小服务端入口(第 2 章详解)
// src/app.ts —— 把 Triage agent 挂到 HTTP 路由
import { createAgentRouter } from '@flue/runtime/routing';
import { Hono } from 'hono';
import { Triage } from './agents/triage.ts';

const app = new Hono();
app.route('/agents/triage', createAgentRouter(Triage));
export default app;

版本要求

Flue 要求 Node.js ≥ 22.19.0。动手前先 node --version 确认。

本章小结

  • Agent 演进三阶段:裸 API → 脚本工作流 → 自主 Agent;
  • Harness 是围绕 LLM 的会话、工具、技能、沙箱等运行时基础设施;
  • Flue 用 React 式心智模型写 Agent:函数即 Agent,Hook 即能力;
  • 核心包是 @flue/runtime,构建走 Vite,部署支持 Node 与 Cloudflare。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 裸 LLM API 调用最大的局限是什么?

2. Flue 中 Agent 函数的返回值是什么?

3. Flue 的核心运行时包是哪一个?

4. 下列哪一项不属于 Harness 的职责范围?

🛠️ 动手实践

  1. 用自己的话向同事解释"Harness 为什么不能省略":如果只给你裸 API,让模型帮你统计仓库 star 数缺了哪几块能力?
  2. 浏览 https://github.com/withastro/flue 的 packages 目录,列出六个核心包各自的一句话职责。
  3. 对照 1.4 的特性表,想想你手头哪个重复劳动最适合交给一个自主 Agent,写下它的目标和需要的工具清单。

概念清楚了?下一章我们搭建项目并跑通第一个 Agent