Agent 学习项目实战清单
项目主线
不要做一堆互不相关 demo。所有项目都围绕一个最终作品累积:
Personal Knowledge Agent:基于 Obsidian 的个人知识库 Agent。
flowchart TD
P0["P0 LLM Chat API"] --> P1["P1 Tool Calling"]
P1 --> P2["P2 Obsidian RAG"]
P2 --> P3["P3 Notes MCP Server"]
P3 --> P4["P4 Learning Planner"]
P4 --> P5["P5 Trace / Eval"]
P5 --> Final["Personal Knowledge Agent"]
项目能力堆叠
P0 Chat API
P1 Tool Calling
P2 Obsidian RAG
P3 Notes MCP
P4 Planner Agent
P5 Trace/Eval
项目分级
等级 项目 学到什么 可展示产物 P0 LLM Chat API 模型调用、流式输出、日志 后端 API + 简单 UI/CLI P1 Tool Calling Demo schema、参数校验、权限 3 个本地工具 P2 Obsidian RAG 私有知识检索、引用、拒答 基于笔记问答 P3 Notes MCP Server MCP 协议、能力发现、只读资源 可被 Agent 调用的 MCP P4 学习计划 Agent workflow、状态机、任务追踪 自动生成周计划和任务 P5 Agent Observability trace、eval、debug report 可复盘的 Agent 控制台
主项目纵向切片
不要按“先写完模型层、再写完工具层、再写完 RAG 层”的方式推进。更稳的做法是每一轮都交付一个能从输入跑到证据和 trace 的纵向切片。
flowchart TD
S0["Chat"] --> S1["Tool"]
S1 --> S2["RAG"]
S2 --> S3["MCP"]
S3 --> S4["Planner"]
S4 --> S5["Eval"]
S5 --> PKA["PKA"]
切片 用户能做什么 后端必须打通 必留证据 S0 Chat 问一个普通 AI 工程问题 ChatController -> ChatService -> ModelGatewayrequest、model、latency、token、error S1 Tool 让模型调用只读工具 ToolRegistry -> Permission -> ToolExecutortool name、args、permission、result S2 RAG 基于指定笔记回答并引用 Indexer -> Retriever -> ContextBuilderquery、chunkId、score、sourcePath S3 MCP 让外部 Agent 读取笔记能力 McpServer -> NotesToolAdapter -> NoteIndexserver、remote tool、transport、timeout S4 Planner 生成一周学习任务并追踪状态 WorkflowEngine -> TaskStore -> MemoryStorestate、task、source note、review S5 Eval 改 prompt 后知道是否退化 EvalRunner -> Judge -> DebugReportcase、expected、actual、pass/fail
纵向切片的价值是:每一步都能演示,每一步都能失败复盘,每一步都能继续扩展。横向堆模块很容易看起来“架构完整”,但用户问题进来后跑不通。
后端模块边界
模块 职责 不该做的事 Java 后端类比 APIHTTP/CLI 输入输出、鉴权、参数 DTO 拼 prompt、直接调模型 Controller application编排一次用户任务 读写底层文件细节 Application Service agent-runtime状态机、停止条件、tool loop 关心具体笔记存储格式 Orchestrator model-gateway模型适配、流式解析、usage 写业务规则 Third-party Client tooling工具注册、schema、权限、审计 绕过 runtime 私自执行 Service + AOP knowledgeMarkdown 切块、索引、检索、引用 决定最终回答风格 Search Service mcp把能力包装成 MCP tools/resources 绕过本地权限策略 External API Adapter memory长期偏好、项目状态、复盘结论 保存全文聊天垃圾 Domain Store eval-trace评测、trace、debug report 只存普通日志 Observability
判断边界是否清楚:删掉某个模块的实现细节,其他模块仍然知道“怎么调用它、得到什么结果、失败怎么看”。如果必须读完整源码才能知道模块怎么用,边界还没立住。
最小交付包
作品集不是只放代码仓库。每个阶段都应该有可检查交付包:
交付包 内容 合格标准 运行入口 README、环境变量、启动命令、示例请求 另一台机器能按步骤跑起来 API 契约 endpoint、request、response、错误码 不看源码也知道怎么调用 数据模型 trace、task、memory、chunk、eval case 字段 字段能解释来源和用途 演示脚本 3-5 个固定问题或命令 能稳定复现核心能力 失败样例 资料不足、工具参数错、权限拒绝 系统能拒绝或降级 复盘报告 一次成功和一次失败的 trace 能定位是检索、工具、模型还是记忆问题 限制说明 暂不支持什么、为什么 不夸大能力
当前 demo 对照
demo 目录已经覆盖了第一个可运行纵向切片,不再只是空壳工程。
交付项 当前实现 还缺什么 运行入口 demo/README.md、Maven 命令、smoke-test.ps1固定端口配置和打包启动脚本 API 契约 /API/chat、/API/notes/search、/API/traces/{traceId}统一错误码和 OpenAPI 描述 数据模型 ChatRequest、AgentResponse、SourceSnippet、TraceRecordsession、userId、chunkId、score detail 演示脚本 smoke-test.ps1 打 search/chat/trace加入拒答样例和性能阈值 固定评测 eval-cases.json + eval-test.ps1增加 forbidden terms、source path、latency 工具层 ToolService + tool-test.ps1加权限确认、超时、审计字段、写工具确认 MCP transport McpService + /mcp + mcp-test.ps1加 session、resources、prompts、streamable HTTP 细节 Memory store MemoryService + /API/memories + memory-test.ps1加撤销、冲突合并、按 traceId 回溯 失败样例 service/eval test 覆盖无来源拒答 HTTP 层错误码测试 复盘报告 TraceService 保存阶段 steps 并追加到 data/traces.jsonl;DebugReportService 输出失败归因trace 查询过滤、聚合报告、OpenTelemetry 限制说明 README 写明不含 LLM/vector/完整生产 MCP/任意文件写入工具 每次新增能力后同步更新
迭代节奏与质量红线
这个项目最容易失败的方式不是技术做不出来,而是每周都“看起来做了很多”,最后没有一个可复盘的系统。迭代要按纵向切片推进,每次只扩一个能力,但必须补齐证据链。
一轮迭代 必须做 不做什么 结束证据 需求收敛 写清用户能做什么、输入输出是什么 不先堆架构图 1 个用户故事 + 1 个失败故事 接口落地 定 endpoint/tool schema/request/response 不让模型输出自由文本当协议 curl/PowerShell 脚本可复现 核心链路 从入口跑到模型/检索/工具/存储 不横向铺太多模块 trace 里能看到每个阶段 失败样例 固定至少 2 个失败场景 不只测 happy path 错参、无证据、越权至少覆盖一种 Eval 回归 把本轮能力写进 eval case 不靠主观体验判断 pass/fail + reason 可读 文档同步 README 写运行方式、限制和下一步 不写“后续优化”空话 另一个人能按步骤跑起来
质量红线:
红线 为什么 没有 trace 的能力不算完成 Agent 错误通常跨模型、检索、工具和状态机,最终答案无法定位根因 没有失败样例的能力不算稳定 只跑 happy path 会掩盖权限、拒答、解析和边界问题 没有 eval 的 prompt 改动不算改进 prompt 可能让一个样例变好,同时让另一个样例退化 没有字段解释的数据模型不算可维护 后续自己都不知道 score、source、confidence 的语义 没有限制说明的 demo 不适合放作品集 作品集看重工程判断,不是夸大能力
每周最小交付格式:
交付项 最低要求 代码 一个纵向链路可运行,不要求功能大 脚本 至少一个成功脚本、一个失败脚本 Trace 成功和失败各保留一条可读记录 Eval 至少新增或更新 3 条固定 case 笔记 写清本轮解决的问题、失败原因、下一轮该补什么
P0:LLM Chat API
目标
做一个可维护的模型调用后端,而不是 SDK demo。
功能
功能 说明 验收 /chat普通问答 返回结构化 JSON /chat/stream流式输出 前端/CLI 能逐字显示 模型配置 model、temperature、system prompt 配置不写死 错误归一 key 错、超时、限流 返回可读错误 调用日志 latency、token、prompt version 可查每次请求
最小类结构
代码块 JAVA · 8 行 收起 展开
final class ChatController {
private final ChatService chatService; // 接收 HTTP 请求,不写模型细节
}
final class ChatService {
private final ModelGateway modelGateway; // 统一封装不同模型供应商
private final ChatTraceRepository traceRepository; // 保存请求、耗时、token、错误
}
目标
让模型调用真实后端能力,但所有执行都由服务端控制。
工具清单
Tool 参数 返回 风险 get_current_time无 当前时间 低 search_local_noteskeyword, limit笔记路径列表 低 create_todo_drafttitle, source待办草稿 中
调用链
工具调用项目链路
User
Agent API
LLM
tool_call
Executor
校验
Store
tool_result
final
验收
工具参数错时不会执行。
危险工具需要确认。
每次工具调用有 trace。
工具失败后模型能解释失败并给下一步。
P2:Obsidian RAG
目标
让 Agent 基于 F:\2. ObsidianNotes 回答,并且必须带来源。
MVP 范围
范围 先做 暂不做 文件类型 .md图片、音频、复杂 PDF 目录 技术栈/AI Agent全库无差别索引 检索 BM25 + vector 复杂知识图谱 输出 带引用回答 长篇报告自动生成 更新 hash 增量索引 实时文件监听
验收问题
问题 期望 MCP 是什么 引用 01-MCP专题学习笔记 RAG 的失败模式有哪些 引用 02-RAG与Agent工程 Java 后端怎么转 Agent 引用 00-Java后端转Agent学习路线 一个不存在的笔记内容 明确说资料不足
P3:Notes MCP Server
目标
把笔记能力暴露给其他 Agent 客户端。
flowchart TD
Client[MCP Client] --> Server[Notes MCP Server]
Server --> Search[search_notes]
Server --> Read[read_note]
Server --> Recent[recent_notes]
Server --> Map[get_ai_agent_map]
Search --> Index[(Note Index)]
Read --> Files[Markdown Files]
工具规格
Tool 参数 说明 验收 list_note_roots无 列出白名单根目录 不暴露全盘 search_noteskeyword, limit搜索笔记 返回路径和标题 read_notepath, max_chars读取笔记 越权路径被拒绝 recent_notesdays, limit最近修改 限制数量 get_ai_agent_map无 返回本目录地图 可作为 Agent 入口
当前 demo 的 MCP 落地边界
项 当前状态 说明 transport 已有 /mcp HTTP JSON-RPC 入口 教学用最小入口,不含生产 session 管理 handshake 已有 initialize 返回稳定协议版本 2025-11-25 和 tools capability tools discovery 已有 tools/list 由 ToolService.definitions() 映射成 MCP tool schema tools call 已有 tools/call 成功返回 structuredContent,工具失败返回 isError=true read boundary 已有 read_note 复用 NoteReadService,不能读取 notesRoot 外或 ignored paper 原文resources/prompts 未实现 后续再把目录地图、单篇笔记、提示模板拆成 MCP resources/prompts
当前 demo 的 Memory 落地边界
项 当前状态 说明 store 已有 MemoryService 追加写入 data/memories.jsonl,不修改 Obsidian 原笔记 schema 已有 MemoryWriteRequest / MemoryRecord 字段包含 type/content/source/confidence/createdAt HTTP 已有 /API/memories POST 写入,GET 按 type/q/limit 查询 tool 已有 write_memory/list_memories MCP tools/list 能标出 write_memory 非 read-only 未实现 撤销、冲突合并、版本、引用 trace 后续进入生产化 memory 设计
当前 demo 的 Trace 落地边界
项 当前状态 说明 store 已有 TraceService 内存索引 + 追加写入 data/traces.jsonl HTTP 已有 /API/traces/{traceId} 根据 traceId 查询一次请求复盘 tool 已有 get_trace Tool/MCP 能读取同一份 trace script 已有 trace-test.ps1 验证 chat -> HTTP trace -> tool -> MCP debug report 已有 DebugReportService 把 trace 转成 status/issue/failedPhase/sourceCount/recommendations script 已有 debug-test.ps1 验证拒答 trace -> HTTP debug -> tool -> MCP 未实现 trace 查询过滤、聚合报告、OpenTelemetry 后续进入生产化 observability
P4:学习计划 Agent
目标
从“问答”升级为“规划 + 执行追踪”。
Planner Loop
目标、资料、诊断、计划、任务、复盘形成闭环。
Goal
Notes
Diagnose
Plan
Tasks
Track
Review
Adjust
状态表
字段 作用 goal_id长期目标 ID phase当前学习阶段 week_no第几周 task_title具体任务 deliverable产出物 statustodo / doing / done / blocked source_notes任务来自哪些笔记 review周复盘
验收
每个任务都有可检查产出。
未完成任务能滚动到下周。
计划能引用已有笔记。
复盘能改变下一周任务,而不是固定模板。
P5:Trace / Eval / Observability
目标
能复盘 Agent 为什么这么回答、为什么调用这个工具、为什么失败。
flowchart LR
Input[User Input] --> Trace[Trace Event]
Retrieval[Retrieved Chunks] --> Trace
Tool[Tool Calls] --> Trace
Model[Model Input/Output] --> Trace
Trace --> Debug[Debug Report]
Eval[Eval Cases] --> Debug
必记字段
字段 用途 trace_id串起一次完整任务 prompt_version对比 prompt 改动 retrieved_chunks检索证据 tool_calls工具行为 model_usagetoken 和成本 final_answer给用户的答案 error_stage失败归因
项目依赖关系
graph TD
P0 --> P1
P0 --> P2
P1 --> P3
P2 --> P3
P2 --> P4
P3 --> P4
P4 --> P5
作品集规格
交付物 必须包含 README 架构图、运行方式、功能截图/说明、限制 Demo 可以问答、检索、调用工具 Trace 任意回答可复盘 Eval 至少 20 个固定问题 安全说明 工具权限、目录白名单、危险操作策略 技术总结 Java 后端如何迁移到 Agent 工程
优先级判断
当前状态 下一步 还不能稳定调模型 做 P0 能调模型但不能用工具 做 P1 能用工具但不能读笔记 做 P2 能读笔记但不能给其他 Agent 用 做 P3 能问答但不能规划 做 P4 能规划但无法复盘质量 做 P5
核心结论
这组项目不是 6 个 demo,而是一个作品从底座到产品化的 6 次迭代。