第1篇:Vibe Coding时代:LangChain 与 LangGraph 全链路方案实战,解决 AI Agent 失控、状态丢失与流程不可维护问题
第1篇Vibe Coding时代LangChain 与 LangGraph 全链路方案实战解决 AI Agent 失控、状态丢失与流程不可维护问题一、问题场景Vibe Coding 写得很爽但 Agent 一上线就失控了最近团队内部在做一个 AI 编程助手原型目标很简单用户输入一个开发需求系统自动完成需求理解 → 技术方案拆解 → 代码生成 → 代码审查 → 最终输出。一开始我直接用 LangChain 写了一个线性 Chainprompt|llm|output_parser本地 Demo 看起来很顺用户输入“帮我写一个 FastAPI 登录接口”LLM 返回代码再接一个审查 Prompt最后输出优化建议但是一接入真实业务问题马上暴露出来。用户需求并不总是清晰的模型生成代码也不一定一次通过审查节点可能要求重新生成某些场景还需要读取文件、调用工具、执行测试、保存状态。最后原本看起来优雅的 Chain 慢慢变成了下面这种代码ifneed_clarify:ask_user()else:codegenerate_code()ifreview_failed:coderegenerate_code()ifneed_tool:tool_resultcall_tool()一开始还能接受写到第 5 个节点后就开始混乱写到第 10 个节点后基本没人敢改。这篇文章要解决的就是这个真实问题在 Vibe Coding 时代如何用 LangChain LangGraph 搭建一个可维护、可追踪、可扩展的 AI Coding Agent 全链路方案。二、真实问题为什么单纯使用 LangChain Chain 不够LangChain 很适合封装模型调用比如Prompt 模板LLM 调用Output ParserTool 调用RAG 检索多模型适配但是复杂 Agent 不是简单的“输入 → 输出”。真实的 AI Coding Agent 至少有这些流程用户需求 ↓ 需求理解 ↓ 任务拆解 ↓ 代码生成 ↓ 代码审查 ↓ 是否通过 ├── 通过输出最终结果 └── 不通过回到代码生成如果继续用普通 Chain 写主要会遇到三个问题。三、问题一流程不可控最开始我写过这种代码requirement_resultrequirement_chain.invoke(user_input)plan_resultplan_chain.invoke(requirement_result)code_resultcode_chain.invoke(plan_result)review_resultreview_chain.invoke(code_result)这类代码有一个特点顺序流程很清楚但一旦出现分支、循环、重试就很快失控。比如代码审查不通过时你需要重新生成代码ifREJECTEDinreview_result:code_resultcode_chain.invoke(plan_result)如果第二次还不通过呢ifREJECTEDinreview_result:code_resultcode_chain.invoke(plan_result)review_resultreview_chain.invoke(code_result)ifREJECTEDinreview_result:code_resultcode_chain.invoke(plan_result)这还只是一个审查重试。如果再加入需求不明确时追问用户代码生成后执行测试测试失败后回到代码修复超过重试次数后交给人工确认每一步都要保存状态代码会迅速变成一坨不可维护的流程胶水。四、问题二状态容易丢失Agent 不像普通接口。普通接口只关心这一次请求的输入输出。但 Agent 需要记住中间状态比如用户原始需求需求分析结果任务拆解结果已生成代码审查意见当前重试次数当前执行节点错误信息工具调用结果如果这些状态都靠变量传递很容易出现上下文丢失。例如codegenerate_code(requirement)reviewreview_code(code)codegenerate_code(requirement)第二次生成代码时如果没有把第一次审查意见传进去模型就不知道为什么要改。正确做法应该是codegenerate_code(requirementrequirement,review_feedbackreview)节点越多状态字段越多靠人工维护变量传递会越来越危险。五、问题三调试困难线性 Chain 出问题通常还能靠打印日志解决print(result)但是复杂 Agent 出问题时你要回答的是这些问题当前执行到了哪个节点为什么进入了 retry 分支为什么没有进入 final 分支哪个节点修改了状态审查结果是什么重试了几次哪次输出开始跑偏是否出现了无限循环如果没有一个明确的流程图和状态对象排查起来非常痛苦。这也是为什么 LangGraph 更适合复杂 Agent。六、解决方案总览LangChain 做能力LangGraph 管流程我的工程经验是LangChain 负责“能力封装”LangGraph 负责“流程编排”。可以这样理解LangChain - Prompt - LLM - Parser - Tool - RAG LangGraph - State - Node - Edge - Conditional Edge - Retry - Human-in-the-loop - Checkpoint本文会实现一个最小但完整的 Vibe Coding Agent用户需求 ↓ 需求分析节点 analyze ↓ 任务拆解节点 plan ↓ 代码生成节点 code ↓ 代码审查节点 review ↓ 条件判断 ├── 审查通过final └── 审查失败回到 code七、最终项目结构适合收藏建议项目结构如下vibe-coding-agent/ ├── app.py ├── graph.py ├── state.py ├── chains.py ├── config.py ├── requirements.txt ├── .env └── README.md这个结构有一个好处chains.py只管模型能力graph.py只管流程编排state.py只管状态定义app.py只管启动入口不要把 Prompt、LLM、流程判断、状态字段全部塞到一个main.py里。这类代码短期写得快后期一定很难维护。八、环境准备创建项目mkdirvibe-coding-agentcdvibe-coding-agent python-mvenv .venvWindows 激活.venv\Scripts\activatemacOS / Linux 激活source.venv/bin/activate创建requirements.txtlangchain langchain-openai langgraph python-dotenv安装依赖pipinstall-rrequirements.txt创建.envOPENAI_API_KEY你的_API_KEY OPENAI_MODELgpt-4o-mini九、定义 StateAgent 的状态中心创建state.pyfromtypingimportTypedDict,ListclassCodingState(TypedDict):user_requirement:stranalyzed_requirement:strtask_plan:strgenerated_code:strreview_result:strfinal_answer:strretry_count:interrors:List[str]字段说明字段作用user_requirement用户原始需求analyzed_requirement需求分析结果task_plan开发计划generated_code生成的代码review_result审查结果final_answer最终输出retry_count重试次数errors错误记录踩坑记录我一开始为了省事直接用了普通字典state{}后面节点一多问题就来了state[review_result]state[review_reuslt]一个单词拼错运行时才报错。所以建议一开始就用TypedDict把状态结构固定下来。Agent 项目里状态结构比 Prompt 更重要。Prompt 可以迭代但状态设计乱了后期重构成本很高。十、封装配置读取创建config.pyimportosfromdotenvimportload_dotenv load_dotenv()defget_model_name()-str:returnos.getenv(OPENAI_MODEL,gpt-4o-mini)defget_openai_api_key()-str:api_keyos.getenv(OPENAI_API_KEY)ifnotapi_key:raiseValueError(请先在 .env 文件中配置 OPENAI_API_KEY)returnapi_key十一、封装 LangChain 能力创建chains.pyfromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromconfigimportget_model_name llmChatOpenAI(modelget_model_name(),temperature0.2,)parserStrOutputParser()defanalyze_requirement(user_requirement:str)-str:promptChatPromptTemplate.from_messages([(system,你是一名资深全栈工程师擅长分析开发需求。请把用户需求分析成清晰、可实现、可落地的工程需求。),(user,用户需求如下\n{user_requirement}\n\n请输出\n1. 需求目标\n2. 技术边界\n3. 核心功能点\n4. 潜在风险点)])chainprompt|llm|parserreturnchain.invoke({user_requirement:user_requirement})defcreate_task_plan(analyzed_requirement:str)-str:promptChatPromptTemplate.from_messages([(system,你是一名软件架构师请根据需求分析拆解开发任务。),(user,需求分析如下\n{analyzed_requirement}\n\n请输出一个工程实现计划包括\n1. 推荐文件结构\n2. 核心模块说明\n3. 实现步骤\n4. 验证方式)])chainprompt|llm|parserreturnchain.invoke({analyzed_requirement:analyzed_requirement})defgenerate_code(analyzed_requirement:str,task_plan:str,review_result:str)-str:promptChatPromptTemplate.from_messages([(system,你是一名资深 Python 后端工程师请根据需求和任务计划生成可运行代码。要求代码清晰、可维护、适合真实项目使用。),(user,需求分析\n{analyzed_requirement}\n\n任务计划\n{task_plan}\n\n上一次审查意见\n{review_result}\n\n请输出完整代码并说明运行方式。)])chainprompt|llm|parserreturnchain.invoke({analyzed_requirement:analyzed_requirement,task_plan:task_plan,review_result:review_result,})defreview_code(generated_code:str)-str:promptChatPromptTemplate.from_messages([(system,你是一名严格的代码审查专家请从工程质量角度审查代码。),(user,请审查下面的代码\n{generated_code}\n\n审查维度\n1. 是否满足需求\n2. 是否存在明显 Bug\n3. 是否存在安全问题\n4. 是否可以运行\n5. 是否需要重写\n\n如果通过请明确输出APPROVED\n如果不通过请明确输出REJECTED并给出具体修改建议。)])chainprompt|llm|parserreturnchain.invoke({generated_code:generated_code})十二、构建 LangGraph 工作流创建graph.pyfromlanggraph.graphimportStateGraph,ENDfromstateimportCodingStatefromchainsimport(analyze_requirement,create_task_plan,generate_code,review_code,)MAX_RETRY2defanalyze_node(state:CodingState)-CodingState:analyzedanalyze_requirement(state[user_requirement])state[analyzed_requirement]analyzedreturnstatedefplan_node(state:CodingState)-CodingState:plancreate_task_plan(state[analyzed_requirement])state[task_plan]planreturnstatedefcode_node(state:CodingState)-CodingState:codegenerate_code(analyzed_requirementstate[analyzed_requirement],task_planstate[task_plan],review_resultstate.get(review_result,),)state[generated_code]codereturnstatedefreview_node(state:CodingState)-CodingState:reviewreview_code(state[generated_code])state[review_result]reviewreturnstatedeffinal_node(state:CodingState)-CodingState:state[final_answer](## 需求分析\n\nf{state[analyzed_requirement]}\n\n## 实现计划\n\nf{state[task_plan]}\n\n## 最终代码\n\nf{state[generated_code]}\n\n## 代码审查结果\n\nf{state[review_result]})returnstatedefshould_retry_or_finish(state:CodingState)-str:review_resultstate.get(review_result,)retry_countstate.get(retry_count,0)ifAPPROVEDinreview_result:returnfinishifretry_countMAX_RETRY:returnfinishstate[retry_count]retry_count1returnretrydefbuild_graph():workflowStateGraph(CodingState)workflow.add_node(analyze,analyze_node)workflow.add_node(plan,plan_node)workflow.add_node(code,code_node)workflow.add_node(review,review_node)workflow.add_node(final,final_node)workflow.set_entry_point(analyze)workflow.add_edge(analyze,plan)workflow.add_edge(plan,code)workflow.add_edge(code,review)workflow.add_conditional_edges(review,should_retry_or_finish,{retry:code,finish:final,})workflow.add_edge(final,END)returnworkflow.compile()十三、程序入口创建app.pyfromgraphimportbuild_graphdefmain():appbuild_graph()user_requirement 请帮我写一个 FastAPI 登录接口要求 1. 用户使用 username 和 password 登录 2. 登录成功返回 token 3. 登录失败返回 401 4. 代码要包含基本的运行方式 init_state{user_requirement:user_requirement,analyzed_requirement:,task_plan:,generated_code:,review_result:,final_answer:,retry_count:0,errors:[],}resultapp.invoke(init_state)print(result[final_answer])if__name____main__:main()运行python app.py十四、验证结果正常情况下你会看到类似结果## 需求分析 1. 需求目标 构建一个 FastAPI 登录接口支持 username 和 password 登录。 ## 实现计划 1. 创建 main.py 2. 定义用户登录模型 3. 编写登录接口 4. 添加异常处理 5. 提供运行方式 ## 最终代码 from fastapi import FastAPI, HTTPException ... ## 代码审查结果 APPROVED 代码整体满足需求可以运行。如果第一次审查不通过流程会自动回到code节点重新生成代码。十五、适合收藏开发步骤总结1. 先画流程不要急着写代码 2. 定义 State明确中间状态 3. 用 LangChain 封装模型能力 4. 用 LangGraph 编排节点 5. 用条件边处理分支 6. 对循环流程设置最大重试次数 7. 加日志和错误记录 8. 最后再考虑持久化、工具调用和人工确认十六、避坑清单问题原因解决方案Agent 无限循环没有设置最大重试次数加MAX_RETRY状态丢失State 设计不完整使用TypedDict明确字段分支判断不稳定模型输出太自由使用固定标识或 JSON代码难维护Prompt、节点、流程混在一起拆分chains.py和graph.py调试困难没有日志和状态追踪增加日志和 trace_id重试无效果没把审查意见传回生成节点generate_code接收review_result十七、总结这篇文章我们完整实现了一个 LangChain LangGraph 的 Vibe Coding Agent 原型。核心思路可以总结为一句话LangChain 负责模型能力LangGraph 负责流程控制。在真实项目中复杂 Agent 最大的问题不是“模型会不会回答”而是状态能不能保存流程能不能控制分支能不能稳定错误能不能恢复结果能不能验证后续能不能维护如果只是写一个简单问答LangChain 足够。但如果你要做的是 AI 编程助手、自动代码审查、自动测试修复、多轮任务执行那么 LangGraph 会更合适。Vibe Coding 时代开发者真正需要掌握的不是单个 Prompt而是把 Prompt、模型、工具、状态、流程、验证组合成一个可控系统。