网易首页 > 网易号 > 正文 申请入驻

打造自己的 Claude Code:LangGraph 搭建一个极简的 AI 编码助手

0
分享至

实践是最好的学习方式。为了深入理解 LangGraph 和模型上下文协议(MCP)服务器的生态,我们来从零开始构建一个 CLI 编码代理。我们的目标是,抛开 Claude Code 那些花里胡哨的功能,看看最基础的编码代理能做到什么程度。



那些商业编码代理往往会添加各种专有的"秘密配方"——特殊的上下文管理、精心设计的提示策略、优化过的工具选择算法。这些技术细节被包装得严严实实,很难搞清楚哪些是必需的,但对于学习来说,那些只是锦上添花。我们这篇文章的目标是验证一个问题:用最简单的方式让 LLM 在无限循环里不断调用工具,这样的"裸机"代理到底行不行?那些复杂的技术栈是真的必要吗,还是过度设计了?

核心功能设计

这个代理的设计理念就是极简但实用。整个系统由一个交互式状态图驱动,信息流向很清晰:用户输入 → 模型响应 → 工具调用 → 回到用户,形成持续的对话循环。本地功能实现了文件读取器和 pytest 的封装用于单元测试。MCP 集成覆盖了几个关键场景:Desktop Commander 负责文件系统操作,Pydantic AI 的沙箱 Python MCP 跑在 Deno Docker 容器里,DuckDuckGo 提供网络搜索,还有官方的 GitHub MCP。为了提升可观测性,还加入了丰富的终端界面和 Mermaid 工作流可视化,可以清楚地看到代理的思考和执行过程。

下面是几个使用示例:





通过 Desktop Commander MCP 的 read_file 工具读取 TypeScript 文件并展示内容



利用 DuckDuckGo 的 MCP 执行网络搜索

快速上手

环境准备很简单,只需要对 Docker 和命令行有基本了解就够了。启动主代理的命令:

uv run main.py

如果要用沙箱 Python 执行功能,需要先构建 Deno MCP 的 Docker 镜像:

docker build -t deno-docker:latest -f ./mcps/deno/Dockerfile .

启动后可以试试这些指令来体验功能:

  • "Show me the content of main.py"
  • "What tools do you have?"
  • "Read requirements.txt"

状态持久化与调试

集成了 langgraph-checkpoint-sqlite 来跟踪对话历史,方便调试。这个基于 SQLite 的检查点机制很适合本地实验场景。可以直接从终端查看代理状态:

sqlite3 checkpoints.db "SELECT * from writes LIMIT 2"
sqlite3 checkpoints.db "SELECT * from checkpoints LIMIT 2"

Pytest 集成

传统做法是写完代码手动跑测试,而现在代理会自动执行这个流程。体验提升非常明显:只需要说"X 功能有问题",代理就会跑测试套件,定位失败的测试用例,分析错误信息,然后给出针对性的修复方案。这彻底省掉了盯着测试日志发呆或者把终端输出复制到 ChatGPT 的繁琐操作,代理拿到的上下文信息足够精确,诊断效率大幅提高。

代码实现

这套代码基于 LangChain 框架,使用 Claude 3 Sonnet 作为核心模型来处理代码库的维护和开发任务。整个系统采用 StateGraph 工作流,包含三个关键节点:user_input、model_response 和 tool_use。



流程在节点间流转,模型响应决定下一步是调用工具还是回到用户输入环节。AgentState 负责维护状态,跟踪完整的消息历史。

核心工作流的实现代码:

# Key workflow setup from the Agent class
def __init__(self):
self.workflow = StateGraph(AgentState)
# Register the three main nodes
self.workflow.add_node("user_input", self.user_input)
self.workflow.add_node("model_response", self.model_response)
self.workflow.add_node("tool_use", self.tool_use)
# Define the flow
self.workflow.set_entry_point("user_input")
self.workflow.add_edge("user_input", "model_response")
self.workflow.add_edge("tool_use", "model_response")
# Conditional routing based on tool usage
self.workflow.add_conditional_edges(
"model_response",
self.check_tool_use,
{
"tool_use": "tool_use",
"user_input": "user_input",
},
)

代理同时加载本地工具(比如单元测试)和运行在 Docker 容器里的 MCP 工具。工具设计上返回结构化的 ToolMessages,让 StateGraph 能够正确路由响应回模型。这些工具支持运行 Python 代码、搜索 DuckDuckGo、与 GitHub 交互等操作。状态在交互间通过 SQLite 检查点机制保持。

LangGraph 的状态架构解析

StateGraph 工作流机制值得单独拿出来细说,因为它是整个代理模式的基础支撑。LangGraph 的 StateGraph 实现了带持久化状态管理的有向图工作流。架构分解如下:

状态管理

class AgentState(BaseModel):
messages: Annotated[Sequence[BaseMessage], add_messages]

AgentState 类基于 Pydantic 的 BaseModel,维护完整对话历史,在图遍历过程中追踪所有消息类型(系统消息、用户消息、助手消息和工具消息)。

图结构设计

工作流由三个节点构成有向图:

  1. 用户输入节点:入口点,收集用户输入
  2. 模型响应节点:用 Claude 处理输入并决策下一步行动
  3. 工具使用节点:响应模型请求执行具体工具

图的配置代码:

# Core graph structure
workflow = StateGraph(AgentState)
# Node registration
workflow.add_node("user_input", self.user_input)
workflow.add_node("model_response", self.model_response)
workflow.add_node("tool_use", self.tool_use)
# Edge connections
workflow.set_entry_point("user_input")
workflow.add_edge("user_input", "model_response")
workflow.add_edge("tool_use", "model_response")

流程控制逻辑

图通过 check_tool_use 实现条件路由:

  1. user_input → model_response(固定路径)
  2. model_response → tool_use(存在工具调用时)
  3. model_response → user_input(无工具调用时)
  4. tool_use → model_response(固定路径)

持久化机制

通过 AsyncSqliteSaver 使用 SQLite 做检查点:

db_path = os.path.join(os.getcwd(), "checkpoints.db")
self._checkpointer_ctx = AsyncSqliteSaver.from_conn_string(db_path)
self.checkpointer = await self._checkpointer_ctx.__aenter__()
self.agent = self.workflow.compile(checkpointer=self.checkpointer)

这套机制让对话状态能跨会话保持遇到中断也能恢复。整个工作流构成一个持续循环,代理可以处理用户输入、生成响应、按需调用工具,在整个交互过程中保持上下文连贯性。

MCP 服务器的模块化实践

MCP 的配置用到了 LangChain 的 mcp-adapters 库,调用 get_tools 方法。某些工具需要在系统提示词里补充描述信息,确保检索准确性。把 MCP 服务器打包成容器解决了环境冲突和依赖管理,用户直接跑容器就行,不用折腾安装配置。

Desktop Commander MCP提供的能力和 Claude Code 基本重合:完整的文件系统操作、代码编辑、审计日志。通过 Docker bind mount 配置把访问范围限制在测试文件夹,保持严格隔离。这种方式让实验变得安全,不用担心搞坏实际文件系统。

Pydantic AI 的 run-python MCP基于 Deno 容器创建沙箱 Python 执行环境。Deno 在 WebAssembly 沙箱里跑 Pyodide,阻止 LLM 在系统上执行危险代码或任意操作。虽然本地安装 Deno 也相对安全,但这会让本地环境变得臃肿。

DuckDuckGo MCP提供互联网搜索能力,需要实时信息检索时调用。

官方 GitHub MCP负责代码仓库搜索和管理功能。

实践中的几个关键问题

安全性和可配置性。对代理的访问权限必须有精细控制。可以给 MCPs 做 Docker 化并设置特定权限——比如 GitHub MCP 用只读标志运行来保护仓库。文件系统访问权限需要有简单的开关机制。,用 gh CLI 工具替代 GitHub MCP 可能更合理,能减少 token 消耗,和 Desktop Commander MCP 的终端访问配合也更流畅。随着 Claude Skills 推出和 CLI 工具链成熟,现在有更好的方案来防止上下文污染且保持功能完整。

工具过载是个要注意的问题。MCPs 加载所有工具及其描述至少两次:初始化代理时一次,每次用户查询时又一次。如果各种 MCPs 加起来有 40 多个工具,LLM 上下文很快就被塞满了。必须仔细检查每个 MCP 的工具命名,避免不同来源的函数名冲突。

MCP 资源使用是事件驱动的。MCPs 按需启动,资源消耗呈现尖峰特征,但在 MacBook Pro 上不算过分。编码代理需要从 MCP 客户端调用工具时,会用指定命令生成 MCP 进程——通常是 docker run,也可能是 npx 或 Python 命令。容器运行时长刚好够执行工具调用,然后自行终止和清理,释放 CPU 资源给下一个操作。这种按需架构让代理保持轻量,同时能访问丰富的工具生态。

MCP 分发方式。很多 MCPs 提供预配置的 Docker 镜像,可以快速集成到编码代理里,方便维护隔离性。不过很多 MCPs 也有 Python 库版本,想要更紧密的集成且不需要额外安全层的话可以本地安装。

langchain-mcp 还不错。用 langchain-mcp-adapters 库可以把 MCPs 桥接到 LangGraph,和 FastMCP 库的类似功能差不多水平。但它提供了平滑的接口,把 MCP 工具转换成 LangChain/LangGraph 兼容的工具,改动代码不多。

工具调用前的用户许可机制需要完善。代理执行工具不会提前征求许可,感觉风险挺大。可以在工具调用前加入人机交互环节能解决这个问题,但代价是会打断代理的执行流程。

后续改进方向

几个增强功能值得考虑。跨个人笔记的综合 RAG 工具——覆盖 Notion、Obsidian、文本文件、markdown——能让代理访问多年积累的知识和研究资料。加入 Confluence MCP 或内部文档 CLI 可以快速搜索公司特定的实践规范。如前面提到的,换成 gh CLI 替代 GitHub MCP 能节省 token。最后在每次工具调用前实现人机交互中断会增加关键的安全层,不过希望做成可配置的,避免在可信操作时频繁打断代理。

本文代码

https://avoid.overfit.cn/post/790f9ab797bc4cf8bdfeb0c7ac58ae83

Lorre Atlan, PhD

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
美股三大指数高开,美光、阿斯麦、博通大涨;重要锂矿供应国停止出口,锂矿股也大涨!加密货币大幅反弹|美股开盘

美股三大指数高开,美光、阿斯麦、博通大涨;重要锂矿供应国停止出口,锂矿股也大涨!加密货币大幅反弹|美股开盘

每日经济新闻
2026-02-25 23:22:05
晒晒从挪威房东身上学到的“装修妙招”,这几处装修,真该普及!

晒晒从挪威房东身上学到的“装修妙招”,这几处装修,真该普及!

装修秀
2026-02-25 11:40:05
1972年,何香凝临终恳求不火化遗体,周恩来含泪答应:不烧,不烧

1972年,何香凝临终恳求不火化遗体,周恩来含泪答应:不烧,不烧

大运河时空
2026-02-25 09:05:03
奥运冠军“拉拉链露胸”,让耐克绷不住了!

奥运冠军“拉拉链露胸”,让耐克绷不住了!

品牌营销报
2026-02-23 11:31:10
0-3惨败止步八强!陈熠/黄友政单局一度落后8分 于子洋首败来了

0-3惨败止步八强!陈熠/黄友政单局一度落后8分 于子洋首败来了

颜小白的篮球梦
2026-02-25 18:41:22
被对手贴脸挑衅,伊万-托尼:我这辈子都没闻过这么臭的口气

被对手贴脸挑衅,伊万-托尼:我这辈子都没闻过这么臭的口气

懂球帝
2026-02-25 12:49:05
你啥时候意识到钱的重要性?网友:钱能解决85%以上的鸡毛蒜皮事

你啥时候意识到钱的重要性?网友:钱能解决85%以上的鸡毛蒜皮事

带你感受人间冷暖
2026-02-23 01:22:30
万斯称美国已掌握证据表明伊朗试图重建核计划

万斯称美国已掌握证据表明伊朗试图重建核计划

每日经济新闻
2026-02-26 08:48:05
平顶山事件二次通报!真相竟是先打其他3人再暴打15岁女生!

平顶山事件二次通报!真相竟是先打其他3人再暴打15岁女生!

魔都囡
2026-02-25 10:57:52
8岁高考760分,智商230超过爱因斯坦,神童陶哲轩如今怎么样了?

8岁高考760分,智商230超过爱因斯坦,神童陶哲轩如今怎么样了?

户外阿毽
2026-02-26 06:16:12
看一次心动一次!大幂幂,永远的神

看一次心动一次!大幂幂,永远的神

阿废冷眼观察所
2026-02-25 11:49:20
潘春春:从陕北放羊娃到“中国波霸”的逆袭人生

潘春春:从陕北放羊娃到“中国波霸”的逆袭人生

小熊侃史
2026-02-15 07:30:14
贺子珍抱着外孙孔继宁的合影,照片中贺子珍笑得合不拢嘴

贺子珍抱着外孙孔继宁的合影,照片中贺子珍笑得合不拢嘴

大运河时空
2026-02-25 07:25:03
畸形审美?这4位男演员长相平平,却总当主角演帅哥,实在不理解

畸形审美?这4位男演员长相平平,却总当主角演帅哥,实在不理解

泪满过眼
2026-02-25 05:03:57
碰瓷!某企拿专利5天向宇树科技索赔8000万,最高法怒批;刘强东拟花50亿进入游艇行业,要让普通人也能买得起;小米起诉自媒体获赔500万元

碰瓷!某企拿专利5天向宇树科技索赔8000万,最高法怒批;刘强东拟花50亿进入游艇行业,要让普通人也能买得起;小米起诉自媒体获赔500万元

雷峰网
2026-02-25 10:54:12
孩子走丢到小卖铺求助,老板好心给其父母打电话,却被5人按倒

孩子走丢到小卖铺求助,老板好心给其父母打电话,却被5人按倒

另子维爱读史
2026-02-25 23:35:20
瓜子被点名!医生提醒:高血脂还常吃瓜子,很快或迎来3个后果

瓜子被点名!医生提醒:高血脂还常吃瓜子,很快或迎来3个后果

荆医生科普
2026-02-25 18:25:49
史上最乱伦成语“上蒸下报”

史上最乱伦成语“上蒸下报”

华人星光
2026-02-21 11:24:05
你永远想不到医院的八卦能有多炸裂?一件提神醒脑,两件直接撂倒

你永远想不到医院的八卦能有多炸裂?一件提神醒脑,两件直接撂倒

另子维爱读史
2026-01-22 18:21:09
党主席干不过地头蛇,郑丽文干不过“南霸天”

党主席干不过地头蛇,郑丽文干不过“南霸天”

雪中风车
2026-02-25 20:54:12
2026-02-26 09:23:00
deephub incentive-icons
deephub
CV NLP和数据挖掘知识
1931文章数 1456关注度
往期回顾 全部

科技要闻

“机器人只跳舞,没什么用”

头条要闻

中方对日方出口管制措施落地后 高市早苗表态了

头条要闻

中方对日方出口管制措施落地后 高市早苗表态了

体育要闻

勇士爆冷惜败鹈鹕 梅尔顿28分赛季新高

娱乐要闻

黄晓明新恋情!与小22岁美女同游新加坡

财经要闻

短剧市场风云突变!有人投百万赔得精光

汽车要闻

750km超长续航 2026款小鹏X9纯电版将于3月2日上市

态度原创

游戏
数码
本地
公开课
军事航空

《FF7重制版》NS2版克劳德头发有锯齿 官方回应

数码要闻

Steam客户端获Beta测试版更新,改善硬件调查对多显卡系统识别

本地新闻

津南好·四时总相宜

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

美政府给新伊核协议设限内容遭披露

无障碍浏览 进入关怀版