AI Agent 这个词 2026 年听了太多遍,但真正动手写过一个的人并不多。这篇文章不讲概念,带你用 LangChain + Claude 从零搭一个能用的智能客服 Agent——能查订单状态、处理退换货申请、遇到解决不了的问题自动转人工。
完整代码约 200 行,Python 环境即可运行。
准备环境:API Key 与依赖安装 开始前需要两个东西:Claude API Key 和 Python 3.10+。
1 pip install langchain langchain-anthropic python-dotenv
在项目根目录创建 .env 文件:
1 ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxx
如果你是第一次接触 Claude API,可以参考之前写的 Ollama 本地部署指南 ,里面讲了 API Key 获取和本地模型的成本对比,本地模型也能跑 Agent,但 Claude 在工具调用能力上目前最强。
设计 Agent 的工具集 Agent 和普通 Chatbot 的关键区别是——它能调用工具。我们的智能客服需要三个工具:
查询订单 ——根据订单号查状态申请退换货 ——创建退换货工单转人工 ——把对话上下文打包给人工客服先定义工具函数。新建 tools.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 from langchain.tools import toolfrom typing import Optional ORDERS = { "ORD001" : {"status" : "已发货" , "item" : "机械键盘" , "eta" : "5月28日" }, "ORD002" : {"status" : "处理中" , "item" : "显示器支架" , "eta" : "待确认" }, "ORD003" : {"status" : "已签收" , "item" : "Type-C 拓展坞" , "eta" : None }, } @tool def query_order (order_id: str ) -> str : """根据订单号查询订单状态。order_id 格式如 ORD001""" order = ORDERS.get(order_id.upper()) if not order: return f"未找到订单 {order_id} ,请核对订单号后重试。" status_text = f"订单 {order_id} :{order['item' ]} ,状态:{order['status' ]} " if order['eta' ]: status_text += f",预计送达:{order['eta' ]} " return status_text @tool def request_return (order_id: str , reason: Optional [str ] = None ) -> str : """为用户创建退换货申请。需要订单号和退换原因""" order = ORDERS.get(order_id.upper()) if not order: return f"未找到订单 {order_id} ,无法创建退换货申请。" if order['status' ] == '已签收' : reason_text = f"(原因:{reason} )" if reason else "" return f"退换货申请已提交{reason_text} 。工单号 RTN-{order_id} ,客服将在 24 小时内联系您确认退货地址。" return f"订单 {order_id} 当前状态为「{order['status' ]} 」,暂不支持退换货。请收到商品后再申请。" @tool def escalate_to_human (summary: str ) -> str : """当 AI 无法解决用户问题时,将对话摘要转接给人工客服""" return f"已为您转接人工客服。工单号 CS-{hash (summary) % 10000 :04d} ,预计等待 2-3 分钟。对话摘要:{summary[:100 ]} "
三个工具各有分工:查订单只读,退换货会创建工单,转人工是兜底。LangChain 的 @tool 装饰器把普通函数包装成 Agent 可调用的工具,函数的 docstring 会自动成为工具描述——Agent 靠这段文字判断什么时候该用什么工具。
构建 Agent 核心逻辑 新建 agent.py,把工具注册到 Agent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import osfrom dotenv import load_dotenvfrom langchain_anthropic import ChatAnthropicfrom langchain.agents import AgentExecutor, create_tool_calling_agentfrom langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom tools import query_order, request_return, escalate_to_humanload_dotenv() llm = ChatAnthropic( model="claude-sonnet-4-6" , temperature=0.3 , max_tokens=1024 , ) tools = [query_order, request_return, escalate_to_human] system_prompt = """你是一个专业的电商智能客服助手。请遵循以下规则: 1. 用中文回复,语气友好专业 2. 用户询问订单时,先调用 query_order 查询,再回复 3. 用户要求退换货时,先确认订单状态,符合条件再调用 request_return 4. 遇到无法解决的问题(如投诉、退款争议、技术故障),调用 escalate_to_human 转人工 5. 不要编造订单信息,一切以工具返回的数据为准 6. 回复简洁,控制在 150 字以内 """ prompt = ChatPromptTemplate.from_messages([ ("system" , system_prompt), MessagesPlaceholder(variable_name="chat_history" ), ("human" , "{input}" ), MessagesPlaceholder(variable_name="agent_scratchpad" ), ]) agent = create_tool_calling_agent(llm, tools, prompt) agent_executor = AgentExecutor( agent=agent, tools=tools, verbose=True , handle_parsing_errors=True , )
这里有几个设计选择值得解释:
temperature=0.3——客服场景不能太有创意,要保持回答一致性verbose=True——开发阶段打开,能看到 Agent 每一步的推理和工具调用handle_parsing_errors=True——防止 Claude 返回格式异常导致 Agent 崩溃这和 Claude Code 自定义规则与自动化工作流 的思路一致——通过 system prompt 约束行为边界,让 AI 在给定框架内发挥,而不是放任自由发挥。
运行与交互 最后写一个简单的命令行交互入口 main.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from langchain_core.messages import HumanMessage, AIMessagefrom agent import agent_executordef chat (): print ("🤖 智能客服已上线,输入 'quit' 退出\n" ) history = [] while True : user_input = input ("👤 您: " ) if user_input.lower() == 'quit' : print ("👋 感谢咨询,再见!" ) break result = agent_executor.invoke({ "input" : user_input, "chat_history" : history, }) reply = result["output" ] print (f"🤖 客服: {reply} \n" ) history.append(HumanMessage(content=user_input)) history.append(AIMessage(content=reply)) if __name__ == "__main__" : chat()
运行 python main.py,试试这些对话:
1 2 3 4 5 6 7 8 9 👤 您: 帮我查一下 ORD001 的订单状态 🤖 客服: 您的订单 ORD001(机械键盘)目前已发货,预计5月28日送达。 👤 您: 我想退货 🤖 客服: 好的,ORD001 还未签收,暂时无法申请退换货。建议您收到商品后如果不满意再联系我。 👤 您: 我收到的键盘有质量问题,我要投诉 🤖 客服: 非常抱歉给您带来不便!已为您转接人工客服处理投诉。 工单号 CS-3847,预计等待 2-3 分钟。
进阶优化方向 这个 Demo 能跑起来,但离生产环境还有距离。如果要继续完善,几个方向值得考虑:
接入真实数据源 。把 ORDERS 字典换成真实的数据库查询——LangChain 支持 SQLDatabaseToolkit,可以直接连 MySQL/PostgreSQL 执行 SQL。Agent 拿到 schema 后会自动生成查询语句,不需要你手写 SQL。
增加多轮记忆持久化 。目前对话历史存在内存里,服务重启就丢失。LangChain 内置了多种 Memory 方案——ConversationBufferMemory 适合短对话,ConversationSummaryMemory 会把长对话压缩成摘要,节省 token。生产环境推荐用 Redis 做持久化存储。
接入多渠道 。客服 Agent 的核心逻辑写好之后,前面接什么渠道都可以——微信公众号、企业微信、网页聊天窗口。架构上把 Agent 的 invoke() 包一层 API,各渠道统一调用同一个入口。
RAG 知识库增强 。如果你的客服需要回答产品规格、退换货政策这类问题,可以把FAQ 文档向量化存入向量数据库。用户提问时先检索相关文档片段,再交给 Agent 回答。这比把全部 FAQ 塞进 system prompt 高效得多——关于 Prompt 工程的具体技巧,可以参考 从入门到进阶的完整指南 。
如果你对这个 Agent 的进阶版本(接入数据库 + 知识库 + 钉钉/飞书)感兴趣,可以在评论区告诉我,下篇接着写。