最近在技术社区和开发者圈子里,一个看似“无厘头”的标题——“走马不观碑,佬们7月份刚刚起步还能吃上安徽板面吗”——引发了不小的讨论。乍一看,这像是一句网络黑话或内部梗,与严肃的技术话题毫不相干。但如果你是一位关注前沿技术动态,尤其是AI Agent、开源模型和开发者工具的从业者,就会立刻意识到,这背后指向的是一个非常具体且紧迫的技术现象:在技术浪潮快速迭代的今天,一个新项目或一项新技能,如果起步晚了,是否还有机会?
“走马观碑”比喻快速浏览而过目不忘,意指那些能迅速抓住趋势、抢占先机的“大佬”。而“安徽板面”在这里,则是一个隐喻,代指由特定技术红利(比如早期的大模型API、开源的Agent框架、某个爆火的开发工具)所带来的“机会窗口”和“实践成果”。整个标题的核心焦虑是:当一项技术已经火热了半年,社区生态初步形成,头部玩家已经圈地,我在7月份才决定入局,还能分到一杯羹,做出点像样的东西吗?
这种焦虑非常真实。无论是想基于Llama 3.1、DeepSeek-V3等新模型构建应用,还是想切入AI Agent、RAG(检索增强生成)等热门赛道,亦或是学习一门像Rust这样正在崛起的语言,后来者总会面临“信息过载”、“最佳实践不明”、“坑位已被占”的困境。本文将彻底拆解这个“后来者困境”,并提供一个清晰的行动框架。我们的核心判断是:“吃上板面”的关键,不在于入场时间的绝对早晚,而在于你是否能避开“观光式学习”,进行“工程化深潜”。本文将为你呈现一套从认知到实操的完整方案,告诉你如何在一个看似“成熟”的领域,找到属于自己的突破点,并产出可交付、可复现的技术成果。
1. 重新定义问题:我们到底在焦虑什么?
在深入技术细节之前,我们必须先厘清焦虑的根源。对于技术人,“起步晚”的恐惧通常来自以下几个层面:
- 信息劣势与认知负担:早期参与者经历了技术从零到一的演变,他们对每个设计决策、每次架构迭代的“为什么”有更深的体感。后来者面对的是已经相对稳定的文档、浩如烟海的博客和良莠不齐的教程,难以辨别哪些是过时的“坑”,哪些是真正的“最佳实践”。
- 生态锁定与路径依赖:一个技术栈一旦形成主流生态(如围绕LangChain的Agent工具链,或围绕Weaviate/Pinecone的向量数据库社区),后来者看似选择很多,实则很容易陷入“教科书式”的模仿,难以做出差异化创新。
- 成果比较与信心打击:当你还在搭建Hello World时,GitHub上已经充满了星光熠熠的项目,技术社区里充斥着各种“一周搞定”、“效果惊艳”的分享。这种比较极易催生“现在做还有什么用”的消极情绪。
- 机会成本的疑虑:担心投入时间学习后,技术风向又变了,或者市场已经饱和,投入没有回报。
然而,这些焦虑恰恰是“观光客”心态的产物。真正的“吃面者”,会转换视角:
- 信息劣势?这反而是优势。你可以直接站在前人的肩膀上,避开他们踩过的所有坑,直接从相对稳定的版本和共识性的最佳实践开始学习,效率更高。
- 生态锁定?成熟的生态意味着更完善的工具、更活跃的社区和更易得的解决方案。你的目标不是重新发明轮子,而是利用这些轮子,更快地造出属于自己的车,去解决一个更具体的问题。
- 成果比较?放弃与顶尖项目在“广度”和“热度”上竞争。转向“深度”和“精度”:解决一个更细分、更实际的问题,哪怕它很小。
所以,本文要解决的核心问题,从“7月起步能否赶上”,转变为“如何以后来者的身份,进行高效、有产出的技术学习与实践,并形成自己的技术护城河”。
2. 破局思维:从“走马观碑”到“定点深挖”
“走马观碑”式学习,追求的是广度、速度和信息量。但对于追赶者,这会导致知识碎片化、实践浮于表面。我们必须转向“定点深挖”模式。
“定点深挖”行动框架:
- 目标收敛:不追求掌握某个技术的全部。例如,不学“整个AI Agent”,而是学“如何用LangGraph构建一个具备特定工作流的客服助手”。
- 问题驱动:以一个具体、可验证的问题作为学习终点。例如,“为我的本地知识库实现一个基于RAG的QA系统,准确率提升到XX%”。
- 逆向学习:从你想要实现的最终效果(那碗“板面”)倒推需要哪些技术(“面粉”、“高汤”、“卤料”)。先跑通一个端到端的Demo,再回头研究每个模块的原理。
- 产出导向:学习的每个阶段,都必须有 tangible 的产出。不是读了多少篇论文,而是写出了可运行的代码、可复现的实验结果、一篇记录真实踩坑过程的博客。
接下来,我们将以当前最热门的AI Agent开发为例,完整演绎这套框架。假设你7月份才决定系统学习并构建自己的第一个AI Agent,该如何行动?
3. 环境准备:搭建可复现的“厨房”
工欲善其事,必先利其器。避免在环境问题上浪费时间是第一课。我们选择目前生态最成熟、最适合快速上手的LangChain + LangGraph + OpenAI API兼容接口作为技术栈。
为什么选这个栈?
- LangChain:提供了连接大模型、工具、数据的标准化组件,是事实上的Agent开发框架标准。
- LangGraph:用于构建有状态、多步骤的复杂工作流,比单纯的Chain更强大。
- OpenAI API兼容接口:让你可以自由切换底层模型(如GPT-4o、Claude、或本地部署的Ollama服务),不被单一供应商绑定。
基础环境配置:
# 1. 创建并进入项目目录 mkdir my-first-agent && cd my-first-agent # 2. 创建虚拟环境(以Python为例) python -m venv venv # 3. 激活虚拟环境 # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate # 4. 安装核心依赖 pip install langchain langchain-community langgraph langchain-openai # 如果你打算使用本地模型(如通过Ollama),还需要安装: # pip install ollama关键配置(.env文件):创建一个.env文件来管理敏感信息和配置,切勿将API密钥硬编码在代码中。
# .env # 使用OpenAI官方服务 OPENAI_API_KEY=sk-your-openai-api-key-here OPENAI_BASE_URL=https://api.openai.com/v1 # 默认,可省略 # 或者,使用兼容OpenAI API的第三方服务(如国内的一些平台或本地Ollama) # OPENAI_API_KEY=your-api-key # 某些服务可能不需要真实的key # OPENAI_BASE_URL=http://localhost:11434/v1 # Ollama的兼容接口地址 # OPENAI_MODEL_NAME=llama3.1:8b # 指定模型在代码中通过python-dotenv加载:
pip install python-dotenv# config.py import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的环境变量 OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1") OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini") # 设置默认模型4. 核心概念与架构:理解Agent的“骨架”与“灵魂”
在写代码前,必须理解几个核心概念,避免“照猫画虎”。
- Agent(代理):不是一个魔法黑盒。它是一个系统,由大模型(LLM)、工具(Tools)、记忆(Memory)和决策逻辑(Orchestrator)组成。其核心能力是“根据目标,自主调用工具完成任务”。
- Tool(工具):Agent的手和脚。任何可以被API、函数调用的能力,如搜索、计算、数据库查询、调用其他服务。LangChain将工具抽象为标准的
BaseTool类。 - Chain(链):一系列确定性调用(LLM、工具等)的顺序组合。适合流程固定的任务。
- Graph(图)/ StateGraph(状态图):由节点(Nodes)和边(Edges)组成,可以描述循环、条件分支等复杂、有状态的工作流。LangGraph是构建复杂Agent的推荐方式。
- State(状态):在Graph中流转的共享数据容器。它定义了每个步骤可以读取和写入哪些信息。
一个经典的Agent决策循环(ReAct模式)可以这样用Graph表示:
[开始] -> [LLM节点:分析状态,决定行动] -> [调用工具节点] -> [更新状态] -> [判断是否完成] -> (是) -> [结束] | (否) -> [返回LLM节点]理解了这个循环,你就抓住了大多数Agent的“灵魂”。
5. 实战:构建一个“旅游规划助手”Agent
我们以“定点深挖”的方式,构建一个能进行多轮对话、调用真实工具(搜索天气、查询地图)的旅游规划助手。
第一步:定义工具(Tools)工具是Agent能力的扩展。我们先模拟两个工具,避免依赖外部API密钥。
# tools/weather_tool.py from langchain.tools import BaseTool from pydantic import BaseModel, Field from typing import Optional, Type class WeatherToolInput(BaseModel): """查询天气工具的输入参数.""" location: str = Field(description="城市名称,例如:北京、上海") class WeatherTool(BaseTool): name = "get_weather" description = "获取指定城市的当前天气情况。" args_schema: Type[BaseModel] = WeatherToolInput def _run(self, location: str) -> str: # 模拟天气查询,真实场景可接入心知天气、和风天气等API weather_data = { "北京": "晴,25°C,微风", "上海": "多云,28°C,东南风3级", "杭州": "阵雨,26°C,湿度85%", } return weather_data.get(location, f"未找到{city}的天气信息。") # tools/map_tool.py from langchain.tools import BaseTool from pydantic import BaseModel, Field from typing import Type class MapToolInput(BaseModel): """查询地点信息的输入参数.""" place_name: str = Field(description="地点名称,例如:故宫、外滩") class MapTool(BaseTool): name = "search_place" description = "搜索地点信息,获取简介和开放时间。" args_schema: Type[BaseModel] = MapToolInput def _run(self, place_name: str) -> str: # 模拟地点查询 place_data = { "故宫": "北京故宫博物院,开放时间:8:30-17:00(旺季)。", "外滩": "上海外滩,万国建筑博览群,全天开放。", } return place_data.get(place_name, f"未找到{place_name}的详细信息。")第二步:定义状态(State)状态是Graph中流动的“血液”,它定义了对话的上下文。
# graph/state.py from typing import TypedDict, List, Annotated import operator class AgentState(TypedDict): """Agent的对话状态.""" messages: Annotated[List[str], operator.add]] # 关键!这是消息历史,会自动追加 user_input: str # 最新的用户输入 has_weather_info: bool # 是否已查询天气 has_place_info: bool # 是否已查询地点 plan_summary: str # 生成的规划摘要第三步:构建Graph(工作流)这是最核心的部分,我们定义Agent的思考和行为逻辑。
# graph/travel_agent_graph.py from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from config import OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL_NAME from tools.weather_tool import WeatherTool from tools.map_tool import MapTool from graph.state import AgentState # 1. 初始化LLM和工具 llm = ChatOpenAI( api_key=OPENAI_API_KEY, base_url=OPENAI_BASE_URL, model=OPENAI_MODEL_NAME, temperature=0.1, # 降低随机性,使输出更稳定 ) weather_tool = WeatherTool() map_tool = MapTool() # 2. 定义各个节点(Node) def llm_router_node(state: AgentState) -> dict: """LLM路由节点:分析用户意图,决定下一步行动。""" from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import JsonOutputParser from pydantic import BaseModel, Field class RouterDecision(BaseModel): """LLM路由决策的输出格式。""" needs_weather: bool = Field(description="是否需要查询天气") needs_place: bool = Field(description="是否需要查询地点信息") next_step: str = Field(description="下一步动作:call_weather_tool, call_map_tool, generate_plan 或 final_response") # 构建系统提示词,指导LLM做决策 prompt = ChatPromptTemplate.from_messages([ ("system", """你是一个旅游规划助手。请根据当前对话历史和用户最新输入,分析用户意图,并决定下一步需要做什么。 可用的工具:1. get_weather (查询天气)。2. search_place (查询地点)。 如果用户的问题涉及某个城市的天气,且我们还没有该信息,则需查询天气。 如果用户的问题涉及具体景点,且我们还没有该信息,则需查询地点。 如果信息已齐全,或用户要求生成规划,则生成规划。 如果只是普通聊天或信息已满足,则直接回复。 请严格按照JSON格式输出。"""), ("human", "对话历史:{history}\n\n用户最新输入:{input}") ]) # 将消息历史列表拼接成字符串 history_str = "\n".join(state['messages'][-5:]) if state['messages'] else "无" chain = prompt | llm | JsonOutputParser(pydantic_object=RouterDecision) try: decision = chain.invoke({ "history": history_str, "input": state["user_input"] }) except Exception as e: print(f"路由决策出错: {e}") decision = RouterDecision(needs_weather=False, needs_place=False, next_step="final_response") # 返回更新后的状态(包含决策结果) return { "needs_weather": decision.needs_weather, "needs_place": decision.needs_place, "next_step": decision.next_step } def call_weather_tool_node(state: AgentState) -> dict: """调用天气工具节点。""" # 简化处理:从最新用户输入中提取城市(真实项目应用NER模型) location = state["user_input"] # 简化,实际应更智能 weather_info = weather_tool.run(location) new_message = f"[系统] 已查询到{location}的天气:{weather_info}" return {"messages": [new_message], "has_weather_info": True} def call_map_tool_node(state: AgentState) -> dict: """调用地图工具节点。""" place_name = state["user_input"] # 简化 place_info = map_tool.run(place_name) new_message = f"[系统] 已查询到{place_name}的信息:{place_info}" return {"messages": [new_message], "has_place_info": True} def generate_plan_node(state: AgentState) -> dict: """生成规划摘要节点。""" from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业的旅游规划师。请根据已有的对话历史(包含天气、地点等信息),为用户生成一份简洁的旅游计划摘要。"), ("human", "对话历史:{history}") ]) history_str = "\n".join(state['messages']) chain = prompt | llm plan = chain.invoke({"history": history_str}).content return {"plan_summary": plan, "messages": [f"[系统] 已生成规划摘要。"]} def final_response_node(state: AgentState) -> dict: """最终回复节点(直接由LLM生成回复)。""" from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个友好的旅游规划助手。请根据对话历史,回应用户的最新输入。"), ("human", "历史:{history}\n\n用户:{input}") ]) history_str = "\n".join(state['messages']) chain = prompt | llm response = chain.invoke({"history": history_str, "input": state["user_input"]}).content return {"messages": [f"[助手] {response}"]} # 3. 构建Graph workflow = StateGraph(AgentState) # 添加节点 workflow.add_node("router", llm_router_node) workflow.add_node("get_weather", call_weather_tool_node) workflow.add_node("get_place", call_map_tool_node) workflow.add_node("make_plan", generate_plan_node) workflow.add_node("respond", final_response_node) # 设置入口点 workflow.set_entry_point("router") # 根据路由决策,动态连接边 def decide_next_step(state: AgentState) -> str: """根据router节点的输出,决定下一个节点。""" next_step = state.get("next_step", "respond") return next_step # 从router节点出发,根据决策连接到不同节点 workflow.add_conditional_edges( "router", decide_next_step, { "call_weather_tool": "get_weather", "call_map_tool": "get_place", "generate_plan": "make_plan", "final_response": "respond", } ) # 设置其他节点的后续流向 workflow.add_edge("get_weather", "router") # 查询完天气后,重新路由 workflow.add_edge("get_place", "router") # 查询完地点后,重新路由 workflow.add_edge("make_plan", "respond") # 生成计划后,进入最终回复 workflow.add_edge("respond", END) # 最终回复后,结束 # 编译Graph app = workflow.compile()第四步:创建主程序与Agent交互
# main.py from graph.travel_agent_graph import app from graph.state import AgentState def run_agent(): print("旅游规划助手已启动!输入 '退出' 或 'quit' 结束对话。") # 初始化状态 config = {"recursion_limit": 50} # 防止无限循环 initial_state: AgentState = { "messages": [], "user_input": "", "has_weather_info": False, "has_place_info": False, "plan_summary": "", } while True: try: user_input = input("\n你:").strip() if user_input.lower() in ['退出', 'quit', 'exit']: print("助手:再见!") break # 更新状态中的用户输入 current_state = initial_state.copy() current_state["user_input"] = user_input # 调用编译好的Graph final_state = app.invoke(current_state, config) # 打印最新的助手回复 new_messages = [msg for msg in final_state["messages"] if msg not in initial_state["messages"]] for msg in new_messages: if msg.startswith("[助手]"): print(f"\n助手:{msg[4:]}") # 如果有生成的计划,也打印出来 if final_state.get("plan_summary") and final_state["plan_summary"] != initial_state.get("plan_summary", ""): print(f"\n=== 为您生成的旅游计划摘要 ===\n{final_state['plan_summary']}\n{'='*40}") # 更新初始状态,保留对话历史 initial_state = final_state except KeyboardInterrupt: print("\n\n对话被中断。") break except Exception as e: print(f"\n系统出错:{e}") if __name__ == "__main__": run_agent()6. 运行与效果验证
- 运行程序:
python main.py - 预期交互:
旅游规划助手已启动!输入 '退出' 或 'quit' 结束对话。 你:我想去北京玩。 助手:北京是个很棒的城市!有很多历史文化古迹和现代建筑。您对哪些方面比较感兴趣呢?比如历史景点、美食还是购物? 你:天气怎么样? [系统] 已查询到北京的天气:晴,25°C,微风 助手:北京目前天气晴朗,温度25度,微风,非常适合出行。 你:介绍一下故宫。 [系统] 已查询到故宫的信息:北京故宫博物院,开放时间:8:30-17:00(旺季)。 助手:故宫是明清两代的皇家宫殿,现在作为博物院开放。旺季开放时间是早上8点半到下午5点。天气好的时候参观体验更佳。 你:帮我做个一日游计划。 [系统] 已生成规划摘要。 === 为您生成的旅游计划摘要 === 基于当前信息,为您规划北京一日游: 上午(8:30-12:00):参观故宫博物院。今日天气晴好,适宜游览。请提前预约门票。 中午(12:00-13:30):在故宫附近品尝北京烤鸭等特色美食。 下午(13:30-17:00):可前往景山公园俯瞰故宫全景,或游览北海公园。 傍晚:前往王府井或三里屯体验现代北京。 注意:故宫需按预约时间进入,请合理安排。 ======================================== 助手:以上是为您生成的一日游计划摘要,请查收。需要调整或添加其他地点吗? - 验证成功:
- Agent能理解多轮对话上下文。
- 能根据意图正确路由并调用工具(模拟)。
- 能整合信息生成初步规划。
- 状态(
has_weather_info,messages)在整个对话中正确流转。
7. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
ModuleNotFoundError: No module named 'langchain' | 依赖未安装或虚拟环境未激活。 | 1. 运行pip list | grep langchain。2. 检查命令行提示符前是否有 (venv)。 | 1. 激活虚拟环境:source venv/bin/activate(Linux/Mac) 或venv\Scripts\activate(Windows)。2. 重新安装: pip install -r requirements.txt。 |
AuthenticationError或Invalid API Key | API密钥错误、未设置或基础URL不对。 | 1. 检查.env文件中的OPENAI_API_KEY和OPENAI_BASE_URL。2. 在Python中 print(os.getenv('OPENAI_API_KEY'))验证。 | 1. 确保.env文件在项目根目录,且已加载。2. 如果使用本地Ollama, OPENAI_BASE_URL应为http://localhost:11434/v1,且Ollama服务已启动。 |
| Agent陷入循环,不停调用工具 | Graph的路由逻辑有缺陷,或LLM的决策提示词不清晰。 | 1. 打印router节点的输出decision,看next_step是否合理。2. 检查 State中是否有足够的信息让LLM判断“任务完成”。 | 1. 在提示词中明确告诉LLM在什么条件下任务算“完成”。 2. 在 State中添加明确的标志位(如task_completed),并在路由逻辑中检查。3. 设置 recursion_limit(如上文config)。 |
| 工具调用参数错误 | 工具定义的args_schema与LLM生成的参数不匹配。 | 1. 查看LangChain/LLM的完整错误日志。 2. 检查工具的 description是否足够清晰,能让LLM正确理解所需参数。 | 1. 优化工具的description,明确参数格式,如“城市名称,例如:北京”。2. 使用 Pydantic的Field(description=...)为每个参数添加详细描述。 |
| 对话历史丢失或混乱 | State中messages字段的定义或操作有误。 | 1. 检查AgentState中messages是否定义为Annotated[List[str], operator.add]。2. 确保每个节点返回更新时,正确操作 messages列表。 | 1. 使用Annotated注解是LangGraph自动追加消息的关键,务必正确。2. 在每个节点返回的字典中, messages字段应是一个新消息的列表,LangGraph会自动将其追加到历史中。 |
8. 从Demo到实战:最佳实践与工程化建议
一个能运行的Demo只是起点。要真正“吃上板面”,必须考虑工程化。
工具的真实化:将模拟工具替换为真实的API调用。使用
requests库或专门的SDK,并做好错误处理和降级。# 真实天气工具示例(使用和风天气API) import requests class RealWeatherTool(BaseTool): ... def _run(self, location: str) -> str: api_key = os.getenv("HEFENG_API_KEY") url = f"https://devapi.qweather.com/v7/weather/now?location={location}&key={api_key}" try: resp = requests.get(url, timeout=10) data = resp.json() if data['code'] == '200': now = data['now'] return f"{location}天气:{now['text']},温度{now['temp']}°C,湿度{now['humidity']}%。" else: return f"查询失败:{data['msg']}" except Exception as e: return f"网络请求出错:{e}"状态的持久化:当前的
State在内存中,重启即丢失。生产环境需要将其持久化到数据库(如SQLite、PostgreSQL)或向量数据库(如Redis)。# 简化的数据库持久化思路 import json class DatabaseStateManager: def __init__(self, db_path): self.conn = sqlite3.connect(db_path) # 创建表... def get_state(self, session_id): # 从数据库读取状态 pass def save_state(self, session_id, state): # 将state字典序列化后存入数据库 pass # 在invoke前后调用StateManagerGraph的监控与调试:LangGraph提供了可视化工具。使用
graphviz将你的工作流图导出,便于理解和沟通。from langchain_core.runnables.graph import MermaidDrawer drawer = MermaidDrawer() chart = drawer.draw(app.get_graph()) with open("travel_agent_workflow.mmd", "w") as f: f.write(chart)同时,为关键节点添加日志,记录输入输出。
提示词工程化:将提示词从代码中分离,存入文件(如
prompts/目录下的.txt或.yaml文件)。便于管理、版本控制和A/B测试。加入评估与测试:为你的Agent创建测试用例,评估其工具调用的准确率、回复的有用性等。可以使用
pytest框架。
9. 总结:后来者的“板面”在哪里?
回到最初的问题:“7月份刚刚起步还能吃上安徽板面吗?”通过上面的完整实践,我们可以给出明确的答案:能,而且可能吃得更好。
对于AI Agent或任何热门技术赛道,后来者的机会不在于复现一个“通用聊天机器人”,而在于:
- 垂直场景深耕:将通用的Agent框架,应用于一个极其具体的行业或问题(如法律文书审核、电商客服排班、代码仓库智能分析)。你的“板面”就是解决这个细分问题的深度解决方案。
- 工作流创新:利用LangGraph等工具,设计出更高效、更稳定、更符合人类业务流程的复杂工作流。你的“板面”就是这套可复用的工作流模板或产品。
- 工具链完善:围绕主流框架,开发更好用的调试工具、监控面板、部署方案或提示词管理平台。你的“板面”就是提升整个生态开发效率的工具。
- 知识沉淀与传播:将你从零开始,踩过的坑、总结的最佳实践、成功的案例,写成像本文一样详实、可操作的教程。你的“板面”就是建立起来的技术影响力和个人品牌。
起步晚,不是劣势,而是优势。你无需在迷雾中探索,眼前已然是一条被无数先行者验证过、并铺就了诸多工具的道路。你需要做的,不是焦虑地“观碑”,而是选定一个“定点”,拿出工匠精神,深挖下去。从运行第一个Demo开始,到替换一个真实工具,再到持久化状态,最后封装成一个可部署的服务——每一步,你都在为自己烹饪那碗独一无二、热气腾腾的“技术板面”。
现在,关闭那些令人焦虑的资讯,打开你的IDE,从mkdir my-first-agent开始。