项目实战清单 · AI Agent

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

项目分级

等级项目学到什么可展示产物
P0LLM Chat API模型调用、流式输出、日志后端 API + 简单 UI/CLI
P1Tool Calling Demoschema、参数校验、权限3 个本地工具
P2Obsidian RAG私有知识检索、引用、拒答基于笔记问答
P3Notes MCP ServerMCP 协议、能力发现、只读资源可被 Agent 调用的 MCP
P4学习计划 Agentworkflow、状态机、任务追踪自动生成周计划和任务
P5Agent Observabilitytrace、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 描述
数据模型ChatRequestAgentResponseSourceSnippetTraceRecordsession、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 transportMcpService + /mcp + mcp-test.ps1加 session、resources、prompts、streamable HTTP 细节
Memory storeMemoryService + /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 可能让一个样例变好,同时让另一个样例退化
没有字段解释的数据模型不算可维护后续自己都不知道 scoresourceconfidence 的语义
没有限制说明的 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、错误
}

P1:Tool Calling Demo

目标

让模型调用真实后端能力,但所有执行都由服务端控制。

工具清单

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/listToolService.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/memoriesPOST 写入,GET 按 type/q/limit 查询
tool已有 write_memory/list_memoriesMCP tools/list 能标出 write_memory 非 read-only
未实现撤销、冲突合并、版本、引用 trace后续进入生产化 memory 设计

当前 demo 的 Trace 落地边界

当前状态说明
store已有 TraceService内存索引 + 追加写入 data/traces.jsonl
HTTP已有 /API/traces/{traceId}根据 traceId 查询一次请求复盘
tool已有 get_traceTool/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 次迭代。