2026/6/9 19:24:52
网站建设
项目流程
网站开发方法有哪些,黑马it培训班出来现状,常德公司网站建设,互联网服务公司实践是最好的学习方式。为了深入理解 LangGraph 和模型上下文协议#xff08;MCP#xff09;服务器的生态#xff0c;我们来从零开始构建一个 CLI 编码代理。我们的目标是#xff0c;抛开 Claude Code 那些花里胡哨的功能#xff0c;看看最基础的编码代理能做到什么程度。…实践是最好的学习方式。为了深入理解 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.pyWhat 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 2Pytest 集成传统做法是写完代码手动跑测试而现在代理会自动执行这个流程。体验提升非常明显只需要说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维护完整对话历史在图遍历过程中追踪所有消息类型系统消息、用户消息、助手消息和工具消息。图结构设计工作流由三个节点构成有向图用户输入节点入口点收集用户输入模型响应节点用 Claude 处理输入并决策下一步行动工具使用节点响应模型请求执行具体工具图的配置代码# 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 实现条件路由user_input → model_response固定路径model_response → tool_use存在工具调用时model_response → user_input无工具调用时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(checkpointerself.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 用只读标志运行来保护仓库。文件系统访问权限需要有简单的开关机制。用ghCLI 工具替代 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 可以快速搜索公司特定的实践规范。如前面提到的换成ghCLI 替代 GitHub MCP 能节省 token。最后在每次工具调用前实现人机交互中断会增加关键的安全层不过希望做成可配置的避免在可信操作时频繁打断代理。