🚀 前端工程师如何构建 AI Harness(架构 + 代码设计 + 落地实践)
一篇写给“已经开始做 AI,但不想停留在 Demo 阶段”的前端工程师
一、问题背景:为什么你需要 AI Harness?
很多团队在接入 AI 后,很快会遇到这些问题:
- ❓ prompt 改了一点,效果变差但不知道为什么
- ❓ 不同模型表现不一致,无法稳定
- ❓ AI 输出偶尔离谱,但无法复现
- ❓ 每次优化都像“玄学调参”
- ❓ 没有办法做回归测试
这些问题的本质只有一个:
❗你在“用 AI”,但没有“工程化 AI”
二、什么是 AI Harness?
一句话定义:
AI Harness = 让 AI 从“能用”变成“可控、可测、可观测、可回归”的工程系统
从 Prompt 到 Harness
随着 AI 处理任务复杂度的增加,工程重点经历了三个阶段的演进:
| 阶段 | 核心关注点 | 隐喻 | 解决的问题 |
|---|---|---|---|
| Prompt Engineering (2023) | 说什么 | 指令 | 如何通过提示词让 AI 交付单次结果。 |
| Context Engineering (2025) | 知道什么 | 信息 | 如何通过 RAG 和动态上下文构建让 AI 获得所需信息。 |
| Harness Engineering (2026) | 在什么环境做事 | 环境/闭环 | 如何构建约束、反馈与控制系统,让 Agent Reliable 执行任务。 |
前端视角怎么理解这套东西
你别把它想成什么“AI 基础设施平台”。
你直接类比成前端工程就明白了:
| AI Harness | 前端类比 |
|---|---|
| Prompt Builder | 请求参数构造器 / 表单 schema |
| Model Router | 接口网关 / BFF 路由 |
| Tool Calling | 前端调用后端 API / SDK |
| Output Parser | 响应适配层 |
| Eval Harness | 单测 + E2E + 回归测试 |
| Observability | 埋点 + 性能监控 + 错误监控 |
| Prompt Versioning | 配置中心 / feature flag |
所以本质上它不是新物种。
它只是把你熟悉的那套工程化思维,迁移到 AI 这边。
一个直观类比
| AI 组件 | 类比 |
|---|---|
| LLM | 发动机 |
| AI Harness | 方向盘 + 仪表盘 + 测试系统 |
为什么它重要?
现实一点说:
- 模型能力:越来越接近
- 工程能力:差距巨大
👉 真正的壁垒在这里:
谁能稳定地“用好 AI”,而不是谁能调用 API
三、整体架构(前端可落地版)
┌──────────────────────────────────────────────┐
│ Frontend App │
│ Chat / Admin / SaaS / Tooling UI │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ AI Service Layer │
│ prompt / model / tool / parser / retry │
└──────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────┐ ┌─────────────┐ ┌──────────────┐
│ LLM APIs │ │ Tool System │ │ Eval System │
└───────────┘ └─────────────┘ └──────────────┘
│ │ │
└──────┬────────┴───────┬───────┘
▼ ▼
┌──────────────────────────────────────────────┐
│ Observability Layer │
│ trace / logs / token / latency │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Regression Harness │
│ dataset / scoring / CI │
└──────────────────────────────────────────────┘
最适合前端落地的 5 层架构
1. UI 层
负责:
- 聊天界面
- 表单输入
- 工具执行结果展示
- 流式输出渲染
- 中断、重试、追问
典型职责
type ChatMessage = {
id: string
role: 'user' | 'assistant' | 'tool'
content: string
status?: 'streaming' | 'done' | 'error'
}
前端别碰太多模型细节,UI 层只管:
- 发请求
- 展示 token stream
- 渲染结构化结果
2. AI Service 层
这是核心。
负责:
- prompt 拼装
- system prompt 管理
- few-shot 注入
- 模型选择
- tool call 编排
- response 结构化解析
- 重试与兜底
这一层就是 Harness 的大脑
比如:
const result = await aiService.run({
scene: 'bug-fix',
userInput,
context,
tools: ['searchDocs', 'runTests', 'createPatch'],
})
你可以把它理解成:
AI Service = BFF for LLM
非常适合前端工程师切进去。
3. Tool 层
负责:
- 调业务 API
- 查知识库
- 调 MCP
- 触发测试
- 跑 lint
- 查日志
- 发通知
工具层原则
每个工具都要:
- 输入清晰
- 输出稳定
- 可单独测试
- 可 mock
例如:
export interface AITool<Input, Output> {
name: string
description: string
schema: ZodSchema<Input>
execute(input: Input): Promise<Output>
}
示例工具:
export const searchDocsTool: AITool<
{ query: string },
{ hits: Array<{ title: string; snippet: string }> }
> = {
name: 'searchDocs',
description: 'Search internal docs',
schema: z.object({
query: z.string(),
}),
async execute(input) {
return searchDocs(input.query)
},
}
4. Observability 层
这是很多人最容易漏的。
没这个,你的 AI 项目迟早变成玄学现场。
你至少要记录:
- 用户输入
- prompt 最终版
- 模型名
- 工具调用链
- 每次工具入参/出参
- token 消耗
- latency
- 错误栈
- 最终输出
- 用户反馈
结构示例
type AITrace = {
traceId: string
scene: string
model: string
promptVersion: string
input: unknown
finalPrompt: string
toolCalls: Array<{
name: string
args: unknown
result: unknown
duration: number
}>
output: unknown
tokens?: {
input: number
output: number
}
latency: number
success: boolean
error?: string
}
这玩意儿不是锦上添花。
这玩意儿是你排查问题时唯一的救命绳。
否则你只能对着一个离谱回答发呆: “它昨天还挺聪明的啊。”
5. Eval / Regression 层
这层决定你是不是在认真做工程。
负责:
- 维护测试集
- 对 prompt / 模型 / tool 策略做 AB 对比
- 自动打分
- CI 回归验证
最小可用形式
你先别追求 fancy 平台,最开始直接用 JSON 就行:
[ { "id": "case-001", "scene": "faq", "input": "退款规则是什么?", "expected": { "mustInclude": ["7天", "原路退回"],
"mustNotInclude": ["无法退款"]
}
},
{
"id": "case-002",
"scene": "bug-fix",
"input": "修复 React useEffect 重复请求问题",
"expected": {
"mustInclude": ["依赖数组", "cleanup"]
}
}
]
然后写个 runner:
for (const testCase of cases) {
const result = await aiService.run({
scene: testCase.scene,
userInput: testCase.input,
})
const passed = evaluate(result.text, testCase.expected)
console.log(testCase.id, passed ? 'PASS' : 'FAIL')
}
这就是最小版 harness。
别小看它,很多团队连这个都没有,优化 prompt 全靠拍脑袋。
四、核心设计思想(非常关键)
在实现之前,先明确几个核心原则:
1️⃣ Scene(场景驱动)
👉 不要把 AI 当成一个“万能函数”
错误写法:
runAI("帮我干点事")
正确方式:
runAI({
scene: "bug-fix",
input,
})
👉 每个场景:
- prompt 不同
- 工具不同
- 模型不同
- 输出结构不同
2️⃣ 工具优先,而不是 prompt 堆砌
很多人会这样做:
请你分析问题,如果需要可以假设...
👉 这是不稳定的
正确方式:
你可以使用以下工具:
- searchDocs
- runTests
- queryAPI
👉 本质:
用工具约束模型,而不是靠 prompt 想象
3️⃣ 可观测性优先
如果你没有记录:
- prompt
- tool 调用
- 输出
👉 你就无法 debug
4️⃣ Eval 驱动优化
不要这样:
“我感觉这个 prompt 更好了”
要这样:
旧版本:78% pass
新版本:85% pass
五、分层设计(5 层)
1️⃣ UI 层
职责:
- 输入 / 展示
- 流式渲染
- 中断 / 重试
type ChatMessage = {
id: string
role: 'user' | 'assistant'
content: string
status?: 'streaming' | 'done'
}
2️⃣ AI Service 层(核心)
👉 相当于 AI 的 BFF
负责:
- prompt 构建
- model routing
- tool orchestration
- output parsing
- retry / fallback
核心调用方式
const result = await runAI({
scene: 'bug-fix',
userInput,
context,
})
3️⃣ Tool 层
标准定义
export interface AITool<Input, Output> {
name: string
description: string
schema: ZodSchema<Input>
execute(input: Input): Promise<Output>
}
示例工具
export const searchDocsTool: AITool<
{ query: string },
{ results: string[] }
> = {
name: 'searchDocs',
description: 'Search internal docs',
schema: z.object({
query: z.string(),
}),
async execute(input) {
return searchDocs(input.query)
},
}
Tool Registry
const tools = {
searchDocs: searchDocsTool,
runTests: runTestsTool,
}
4️⃣ Observability 层
为什么必须有?
否则你会遇到:
- “昨天还好好的”
- “偶现 bug”
- “不知道模型为什么这么答”
Trace 结构
type AITrace = {
traceId: string
scene: string
model: string
prompt: string
toolCalls: Array<{
name: string
args: unknown
result: unknown
duration: number
}>
output: unknown
latency: number
success: boolean
}
5️⃣ Eval / Regression 层
示例数据集
[ { "id": "faq-1", "input": "退款规则是什么?", "expected": { "mustInclude": ["7天", "原路退回"]
}
}
]
Runner
for (const testCase of dataset) {
const result = await runAI({
scene: 'faq',
userInput: testCase.input,
})
const passed = evaluate(result, testCase.expected)
}
六、核心代码结构(推荐)
src/
├── ai/
│ ├── core/
│ │ ├── ai-service.ts
│ │ ├── model-router.ts
│ │ ├── prompt-builder.ts
│ │ ├── output-parser.ts
│ │ └── trace.ts
│ │
│ ├── scenes/
│ │ ├── bug-fix.scene.ts
│ │ ├── faq.scene.ts
│ │
│ ├── tools/
│ │ ├── search-docs.tool.ts
│ │ ├── run-tests.tool.ts
│ │
│ ├── eval/
│ │ ├── datasets/
│ │ ├── run-eval.ts
│ │
│ └── adapters/
│ ├── openai.adapter.ts
│
├── server/
│ └── api/
│
└── apps/
└── chat/
七、Scene 抽象(关键)
export interface AIScene {
name: string
tools?: string[]
model?: string
buildPrompt(input): Promise<string>
parseOutput(raw: string): unknown
}
示例:Bug Fix
export const bugFixScene: AIScene = {
name: 'bug-fix',
tools: ['searchDocs', 'runTests'],
async buildPrompt({ userInput }) {
return `
You are a senior frontend engineer.
Analyze the bug and return JSON:
{
"rootCause": "",
"fixPlan": []
}
Bug:
${userInput}
`
},
parseOutput(raw) {
return JSON.parse(raw)
},
}
八、AI Service 实现(核心)
export async function runAI(params) {
const scene = getScene(params.scene)
const model = resolveModel(scene.name)
const prompt = await scene.buildPrompt(params)
const result = await callModel({
model,
prompt,
tools: scene.tools,
})
return scene.parseOutput(result)
}
九、推荐落地场景(非常现实)
你不是做算法的,你是前端。
所以别一上来搞“通用智能平台”。那玩意儿最后容易做成 PPT。
你先做下面三个最有价值的。
场景 1:前端 FAQ / 文档问答 Harness
适合公司内部知识库、组件库、接入文档、接口文档。
价值
- 新人问答
- 减少重复沟通
- 提高 API 接入效率
结构
用户问题
-> 检索文档
-> 拼 prompt
-> 模型回答
-> 引用来源
-> 记录问答效果
工具
- searchDocs
- getComponentProps
- searchAPI
场景 2:AI Code Review Harness
适合:
- PR 描述总结
- 风险点识别
- 规范检查
- 测试建议生成
输入
- diff
- 文件路径
- lint 结果
- 业务上下文
输出
- 风险等级
- 问题清单
- 修改建议
- 是否建议人工复审
这玩意儿很适合你这种有工程经验的人,因为它不是纯聊天,而是工程闭环。
场景 3:AI 修 Bug Harness
这个最值得你搞。
流程图
用户提 Bug
↓
读取报错日志 / 页面信息 / 相关代码
↓
检索相似问题 / 内部文档
↓
模型分析 root cause
↓
生成修复建议
↓
调用测试工具验证
↓
输出 patch / PR 建议
工具建议
- searchErrorDocs
- searchGitHistory
- runUnitTests
- runE2E
- createPatch
- notifyOwner
这就是你之前提的那种“AI 修 bug Agent”的工程底座。
不是嘴上 Agent,是真能跑。
十、MVP 落地建议
别上来就要大而全。
你先做一个 MVP Harness,结构如下:
1. 一个 chat 页面
2. 一个 aiService
3. 两三个工具
4. 一个 trace 日志表
5. 一份 eval 数据集
6. 一个 npm script 跑回归
MVP 目录
src/ai/
├── ai-service.ts
├── prompts.ts
├── tools.ts
├── eval.ts
└── traces.ts
MVP 能力
- 支持一个场景:比如“文档问答”
- 支持一个模型
- 支持两个工具:检索文档、查接口
- 支持记录日志
- 支持 20 条测试用例跑回归
做到这一步,你已经超过一堆“只会喊 AI 赋能”的团队了。
十一、常见坑
1. 不要把 prompt 写死在组件里
错误示范:
const prompt = `你是一个AI助手...`
这会导致后面:
- 版本不可控
- 场景难拆
- 无法评估
- 到处复制屎山
prompt 必须模块化管理。
2. 不要让工具输出不稳定
模型最怕吃脏数据。
工具输出最好结构化:
{
success: true,
data: {...},
error: null
}
而不是今天返字符串,明天返数组,后天返祖。
3. 不要没有 trace
没有 trace 的 AI 项目,相当于:
- 前端没 sourcemap
- 后端没日志
- 运维没监控
出问题全靠烧香。
4. 不要没有 eval 就改 prompt
你觉得回答更好了,不代表真更好了。
很多 prompt 优化,本质上只是:
- 你今天看顺眼了
- 它恰好答对了
- 样本太少
必须有固定测试集。
5. 不要一开始追求“全自动 Agent”
这条很重要。
很多人一上来就想:
- 自动修 bug
- 自动发 PR
- 自动上线
- 自动通知群里
最后效果往往是:
自动给你整出事故。
正确顺序是:
问答 -> 建议 -> 半自动执行 -> 全自动闭环
先让 AI 当副驾,别急着把方向盘给它。
十二、总结
对于前端工程师来说:
👉 AI Harness 是一个非常好的切入点
因为它结合了:
- 工程能力
- 架构能力
- 系统设计
- AI 应用能力
🔚 最后一句
未来 AI 的差距不在于:
谁会用 AI
而在于:
谁能把 AI 稳定地用在真实业务中
如果你看到这里,说明你已经不是在“用 AI”了。
你是在构建 AI 系统。