进阶第 12 章:结项 Agent 项目
业务问题
前面章节是零散知识。最后一章要完成一个完整项目,并把知识组织成面试可讲的故事。
交互图解:Agent、Harness 与插件服务全景 · 查看图解导读
核心原理
项目不是堆功能,而是证明你能处理:
- 架构分层。
- 流式状态。
- 工具调用。
- 权限和取消。
- 会话恢复。
- 错误和观测。
真实项目中的映射
项目:一个 AI 编码助手 / 客服 Agent。
核心页面:
- 会话列表。
- 聊天流。
- 工具调用卡片。
- 权限批准。
- 执行轨迹。
- 模型选择。
核心后端抽象:
- SessionLog。
- ToolRegistry。
- LlmPort。
- AgentLoop。
- PermissionPolicy。
DeepSeek Harness 对应实现
真实项目可以借鉴 DeepSeek Harness:
- 会话日志作为真相。
- 工具通过 registry 注册。
- 模型通过 adapter seam 接入。
- 前端使用 React-free 对象层和快照。
- 权限通过 pre-execute 决策。
进一步阅读:
docs/architecture.mddocs/cookbook/extension-cookbook.md
代码示例
最小 Agent 服务
ts
interface AgentServices {
log: {
append(message: { role: string; content: string }): void
all(): Array<{ role: string; content: string }>
}
tools: {
list(): Array<{ name: string; description: string }>
run(name: string, args: string): Promise<string>
}
llm: {
complete(messages: Array<{ role: string; content: string }>): Promise<{
text: string
toolCall?: { name: string; args: string }
}>
}
}
async function runAgent(services: AgentServices, task: string): Promise<string> {
services.log.append({ role: 'user', content: task })
for (let step = 0; step < 8; step += 1) {
const reply = await services.llm.complete(services.log.all())
services.log.append({ role: 'assistant', content: reply.text })
if (!reply.toolCall) return reply.text
const result = await services.tools.run(reply.toolCall.name, reply.toolCall.args)
services.log.append({ role: 'tool', content: result })
}
return 'max steps reached'
}React 页面
tsx
import { useState } from 'react'
function AgentApp({ agent }: { agent: { run(task: string): Promise<string> } }) {
const [task, setTask] = useState('')
const [answer, setAnswer] = useState('')
const [status, setStatus] = useState<'idle' | 'running' | 'done'>('idle')
async function submit() {
setStatus('running')
setAnswer('')
const result = await agent.run(task)
setAnswer(result)
setStatus('done')
}
return (
<main>
<textarea value={task} onChange={event => setTask(event.target.value)} />
<button onClick={submit} disabled={status === 'running'}>运行</button>
<pre>{answer}</pre>
</main>
)
}这个最小项目可以用 mock LLM 和本地工具运行,不需要真实 API Key。
面试追问
问:这个项目的难点是什么?
回答要点:
- 流式 token 高频更新。
- 工具调用中间状态。
- 权限和取消。
- 会话恢复和回放。
- 模型输出不可控。
问:你如何证明项目不只是 demo?
回答要点:
- 有状态机。
- 有错误处理。
- 有事件日志。
- 有测试。
- 有权限和审计。
问:如果重新设计,你会改进什么?
回答要点:
- 增强重连和去重。
- 增加压缩策略。
- 增加评估集。
- 增加 trace 和监控。
- 使用更成熟协议。
实践任务
完成一个最小 AI 编码助手 / 客服 Agent:
- 实现 SessionLog、ToolRegistry、LlmPort、AgentLoop。
- 用 mock LLM 完成一个工具调用闭环。
- 用 React 展示流式结果和工具状态。
- 写出 README、测试和面试叙事。
验收标准
- 项目能运行,不依赖真实 API Key。
- 能展示至少一次工具调用。
- 能处理取消和错误。
- 能解释架构、难点和监控方案。