欢迎光临
我们一直在努力

给后端开发者的AI Agent项目:2000行Java从零实现,面试能讲30分钟,一个仿claude code项目

文章目录

    • 一、这是什么
    • 二、为什么这个项目能帮你找实习
      • 面试官想看什么
      • 简历上可以怎么写
    • 三、面试能聊的技术亮点
      • 亮点 1:Agent 主循环——while(true) 而不是框架黑盒
      • 亮点 2:手写 MCP 协议——150 行,零 SDK
      • 亮点 3:三层上下文压缩——比"扔给 LLM 摘要"高一个维度
      • 亮点 4:Subagent 隔离——在定义层切断递归
      • 亮点 5:Prompt Caching——靠架构不靠 API
    • 四、学这个项目的路线
      • 第一周:跑起来,看懂主循环
      • 第二周:改一个工具
      • 第三周:准备面试话术
      • 第四周:写进简历,开始投
    • 五、和其他学习项目比
    • 六、项目还有这些细节
    • 总结

GitHub 仓库: https://github.com/cookie250825/mvp-claude-code

⭐ 觉得有用就 Star 一下,找实习时这就是你的项目经验。


今年 Java 后端的实习岗位,JD 里开始出现这些词了:大模型应用、Agent 开发、MCP 协议、LangChain。

你简历上写什么?“精通 Spring Boot、熟悉 Redis”——面试官一天看 50 份这样的简历。

我写了一个项目,专门给后端开发者的:纯 Java,2000 行代码,从零实现一个 AI 编程助手。 和 Claude Code 一样的架构,但每一行代码都是你自己能看懂、能讲清的。

不是套壳,不是调 API 玩具。是一个完整的 Agent 引擎——面试能讲 30 分钟的那种。


一、这是什么

你在终端里敲一行字:

> 帮我在 src 目录下找到所有用到 ThreadPoolExecutor 的地方,看看有没有忘记关的

它就去读文件、搜索代码、执行命令,几轮工具调用之后给你答案。像一个真正的工程师坐在键盘前面。

架构图和 Claude Code 完全一致:

#mermaid-svg-5sKVYbK9l3mYRABU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5sKVYbK9l3mYRABU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5sKVYbK9l3mYRABU .error-icon{fill:#552222;}#mermaid-svg-5sKVYbK9l3mYRABU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5sKVYbK9l3mYRABU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5sKVYbK9l3mYRABU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5sKVYbK9l3mYRABU .marker.cross{stroke:#333333;}#mermaid-svg-5sKVYbK9l3mYRABU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5sKVYbK9l3mYRABU p{margin:0;}#mermaid-svg-5sKVYbK9l3mYRABU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-5sKVYbK9l3mYRABU .cluster-label text{fill:#333;}#mermaid-svg-5sKVYbK9l3mYRABU .cluster-label span{color:#333;}#mermaid-svg-5sKVYbK9l3mYRABU .cluster-label span p{background-color:transparent;}#mermaid-svg-5sKVYbK9l3mYRABU .label text,#mermaid-svg-5sKVYbK9l3mYRABU span{fill:#333;color:#333;}#mermaid-svg-5sKVYbK9l3mYRABU .node rect,#mermaid-svg-5sKVYbK9l3mYRABU .node circle,#mermaid-svg-5sKVYbK9l3mYRABU .node ellipse,#mermaid-svg-5sKVYbK9l3mYRABU .node polygon,#mermaid-svg-5sKVYbK9l3mYRABU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5sKVYbK9l3mYRABU .rough-node .label text,#mermaid-svg-5sKVYbK9l3mYRABU .node .label text,#mermaid-svg-5sKVYbK9l3mYRABU .image-shape .label,#mermaid-svg-5sKVYbK9l3mYRABU .icon-shape .label{text-anchor:middle;}#mermaid-svg-5sKVYbK9l3mYRABU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5sKVYbK9l3mYRABU .rough-node .label,#mermaid-svg-5sKVYbK9l3mYRABU .node .label,#mermaid-svg-5sKVYbK9l3mYRABU .image-shape .label,#mermaid-svg-5sKVYbK9l3mYRABU .icon-shape .label{text-align:center;}#mermaid-svg-5sKVYbK9l3mYRABU .node.clickable{cursor:pointer;}#mermaid-svg-5sKVYbK9l3mYRABU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5sKVYbK9l3mYRABU .arrowheadPath{fill:#333333;}#mermaid-svg-5sKVYbK9l3mYRABU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5sKVYbK9l3mYRABU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5sKVYbK9l3mYRABU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5sKVYbK9l3mYRABU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5sKVYbK9l3mYRABU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5sKVYbK9l3mYRABU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5sKVYbK9l3mYRABU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5sKVYbK9l3mYRABU .cluster text{fill:#333;}#mermaid-svg-5sKVYbK9l3mYRABU .cluster span{color:#333;}#mermaid-svg-5sKVYbK9l3mYRABU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5sKVYbK9l3mYRABU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5sKVYbK9l3mYRABU rect.text{fill:none;stroke-width:0;}#mermaid-svg-5sKVYbK9l3mYRABU .icon-shape,#mermaid-svg-5sKVYbK9l3mYRABU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5sKVYbK9l3mYRABU .icon-shape p,#mermaid-svg-5sKVYbK9l3mYRABU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5sKVYbK9l3mYRABU .icon-shape rect,#mermaid-svg-5sKVYbK9l3mYRABU .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5sKVYbK9l3mYRABU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5sKVYbK9l3mYRABU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5sKVYbK9l3mYRABU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

纯文本

含工具调用

批准

file/bash/search

task

MCP

用户输入

AgentLoop.process

BackgroundManager.drain\\n后台任务通知注入

microCompact\\n旧工具输出裁剪

token > 阈值?

LLM 摘要压缩

ContextBuilder.build\\n可缓存前缀 + 动态历史

AIService.streamingChat\\n流式输出 token

流式输出 ✅

ToolExecutionConfirmation\\n用户确认 y/n/a

ToolDispatcher 路由

工具类型

内置工具

SubagentRunner\\n独立上下文 + 防递归

MCPClient\\nJSON-RPC over stdio

ToolResult 写回 history

下轮循环

关键数字: 2000 行 Java、7 个 Maven 依赖、零 Spring Boot、零数据库。整个项目就是一个 jar 包,跑起来就行。


二、为什么这个项目能帮你找实习

面试官想看什么

后端实习面试,面试官心里有三个问题:

  • 你能不能独立看懂一个系统?(代码阅读能力)
  • 你对自己的代码能不能讲清楚为什么这样写?(工程判断力)
  • 除了 CRUD,你还了解什么?(技术广度)
  • 这个项目帮你同时回答这三个问题。

    简历上可以怎么写

    MVP Claude Code(开源) — 核心开发者

    • 用 Java 从零实现类 Claude Code 的 AI 编程助手,2000+ 行代码
    • 手写 MCP 协议客户端(JSON-RPC over stdio),零 SDK 依赖,支持接入外部工具生态
    • 设计三层上下文压缩策略(Micro/Auto/Manual),解决 LLM 长对话 token 爆炸问题
    • 实现 Subagent 子任务隔离机制,在工具定义层切断递归
    • 技术栈:Java 17、LangChain4j、DeepSeek API、Picocli、Jackson

    五条就够。 每一条都是面试官能追问的点——追问了你都能接住,这就是好简历。


    三、面试能聊的技术亮点

    下面这五个点,每个面试都能讲 5-10 分钟。我写项目时专门留了"面试话术"——docs/HARNESS_DESIGN.md 里每个组件都有。

    亮点 1:Agent 主循环——while(true) 而不是框架黑盒

    大部分 AI 项目靠 LangChain 的 AgentExecutor,几行配置跑起来,但面试一问细节就崩。

    我是手写的:

    for (int round = 1; round <= MAX_ROUNDS; round++) {
    // 1. 排空后台任务通知
    // 2. microCompact — 零成本裁剪旧工具输出
    // 3. autoCompact — token 超阈值时 LLM 摘要
    // 4. 流式调用 LLM
    // 5. 工具调用?→ 确认 → 执行 → 写回结果
    // 6. 纯文本?→ 返回给用户
    }

    面试官追问"为什么不用 AiServices"时,你能讲出可控性——框架是黑盒,手写循环让你在每一步都能插入自己的逻辑。

    亮点 2:手写 MCP 协议——150 行,零 SDK

    MCP(Model Context Protocol)是今年最热的 Agent 协议。大部分项目直接用 MCP SDK,这没问题,但面试没得聊。

    我自己实现了完整的 JSON-RPC 握手:

    // 标准 MCP 握手流程
    send(initialize) → 声明协议版本和客户端能力
    recv() → 获取服务端能力
    send(initialized) → 握手完成通知
    send(tools/list) → 拉取工具列表(含 JSON Schema
    send(tools/call) → 调用具体工具

    用的全是 JDK 标准库——ProcessBuilder 管理子进程,BufferedReader/Writer 处理 stdio 通信。面试官问 MCP,你能从握手讲到子进程管理,10 分钟起步。

    亮点 3:三层上下文压缩——比"扔给 LLM 摘要"高一个维度

    LLM 的上下文窗口是有限的,对话长了怎么办?大部分方案就是"调 LLM 做个摘要"。

    我设计了三层递进策略:

    层触发策略API 成本
    Micro 每轮 工具输出 >2000 字符 → 截到 500
    Auto token > 阈值 LLM 摘要 + 保留最近 10 条 一次 LLM 调用
    Manual 用户命令 全量压缩 一次 LLM 调用

    Micro 层是零成本的——大文件读出来几千字,又不是每轮都需要,截断保留前 500 字就够了。Auto 层才是 LLM 语义理解真正需要介入的场景。

    面试话术: “多数上下文方案只有一层——要么滑动窗口丢消息,要么 LLM 摘要。我设计了三层递进,成本递增、按需触发。Micro 层零成本解决 80% 问题。”

    亮点 4:Subagent 隔离——在定义层切断递归

    Claude Code 有子 Agent,我的项目也有。子 Agent 的核心问题是怎么防止无限递归——子 Agent 里不能再创建孙 Agent 去干同一个活。

    我的做法是在工具定义层切断:

    父 Agent: Tools{file, bash, search, task} ← 有 task 工具
    子 Agent: Tools{file, bash, search} ← 没有 task 工具

    子 Agent 的工具列表里压根没有 task,LLM 不知道有这个工具就不可能调用。这不是在执行层拦截,是在能力层截断。

    面试话术: “防递归不是加个 if 判断,而是在工具定义层切断。子 Agent 的 ToolSpec 列表里没有 task,LLM 的推理链路里永远不可能产生子 Agent 调用。”

    亮点 5:Prompt Caching——靠架构不靠 API

    每次调用 LLM,System Prompt 和工具定义占了上下文的前几千 token。对话越长,这部分重复发送越多次。

    我把请求拆成了两层:

    ChatRequest = [System Prompt + Memory + 工具声明] + [对话历史]
    ← 构造时固定,跨请求复用 → ← 每次拼接 →

    前缀在构造时计算一次,后续每次 build() 复用同一个对象引用。LLM API 网关会逐字节比较相邻请求的公共前缀——前缀越稳定,缓存命中率越高。

    不需要一行 cache_control API 调用,纯粹靠结构设计。


    四、学这个项目的路线

    如果你是大三/大四,Java 基础还行但没做过 AI 项目,建议这么走:

    第一周:跑起来,看懂主循环

    git clone https://github.com/cookie250825/mvp-claude-code.git
    cd mvp-claude-code
    cp config.yaml.example config.yaml
    # 编辑 config.yaml 填上 DeepSeek API Key
    mvn package -DskipTests
    java -jar target/mvp-claude-code-1.0-SNAPSHOT.jar -i

    然后对着 AgentLoop.java(80 行)看:用户输入进来后,每一步发生了什么。

    第二周:改一个工具

    给它加一个工具,比如 TimeTool——问 AI “几点了” 能回答当前时间。走通 “定义工具 → 注册到 Registry → LLM 调用 → 执行 → 写回结果” 的完整链路。

    第三周:准备面试话术

    docs/HARNESS_DESIGN.md 里有 10 个组件的设计思路 + 面试话术。选 3 个你最熟的,能讲 5 分钟以上就行——面试不是背八股,是讲你做过的东西。

    第四周:写进简历,开始投

    简历上放 4-5 条项目经验(参考上面第二节的模板),GitHub 链接放上去。面试官开始问 AI Agent,你就从 while(true) 循环开始讲。


    五、和其他学习项目比

    Spring Boot 商城调 API 的 ChatBotMVP Claude Code
    代码量 5000+ 200 2000
    能讲多久 “我写了很多 CRUD” “我调了 OpenAI SDK” 30 分钟,逐层拆解
    涉及概念 MyBatis、Redis Agent 循环 / MCP / 压缩 / 子 Agent / 缓存
    面试区分度 低,人人都有 极低 高,面试官没见过

    Spring Boot 商城是好项目,但那是"我会 Java"的证明。MVP Claude Code 是"我理解 AI Agent 架构"的证明。两个放一起,简历就完整了。


    六、项目还有这些细节

    聊聊你可能关心的:

    为什么用 DeepSeek 不是 Claude? 便宜。DeepSeek 的 API 和 OpenAI 完全兼容,langchain4j-open-ai 模块直接对接。改两行配置就能换成任何一个 OpenAI 兼容的服务。

    流式输出怎么做? 用 CompletableFuture 桥接异步和同步——流式 API 是异步的(onNext 实时打印 token),但 while(true) 循环需要等 AI 响应完才能继续。future.get() 阻塞等待,拿到完整响应后继续。

    工具执行前怎么确认? 交互模式下弹 y/n/a 选择——y 执行这次、n 跳过、a 全部批准不再询问。用户拒绝后写入 history,LLM 看到后会自己调整策略,不会傻傻重试。

    CHANGELOG 有完整迭代记录。 从 v1.0(核心引擎)到 v1.3(流式 + 确认 + 缓存),每个版本做了什么、为什么做,都在 CHANGELOG.md 里——这是"我有工程迭代能力"的证明。


    总结

  • 给后端开发的 AI Agent 项目,2000 行 Java,7 个依赖,不藏复杂度
  • 5 个面试能深讲的亮点:while(true) 循环、手写 MCP、三层压缩、Subagent 隔离、架构化缓存
  • 四周学习路线:跑起来 → 改工具 → 准备话术 → 写简历
  • 和商城项目互补,一个证明广度,一个证明深度
  • 完整的工程记录:设计文档 + CHANGELOG + 踩坑记录,面试官会看

  • GitHub: https://github.com/cookie250825/mvp-claude-code

    ⭐ 有用就 Star,找实习加油。

    赞(0)
    未经允许不得转载:171主机测评 » 给后端开发者的AI Agent项目:2000行Java从零实现,面试能讲30分钟,一个仿claude code项目
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址