简介:本教程面向希望理解代码智能体内部原理的开发者,讲解如何基于大模型的工具调用能力,用约200行代码从零实现一个可在终端运行的极简编程智能体。内容覆盖智能体主循环、工具定义与安全执行、上下文工程入门,并提供结果验证清单与常见问题排查方法,帮助你系统建立AI原生开发的实践认知。
近一年来,代码智能体(Coding Agent)的能力出现了阶跃式提升:大模型的推理时间更长、可自主处理的任务复杂度显著提高,软件开发的协作方式随之被改写。教学与工程实践也在同步演进——某知名高校新近发布的现代软件开发课程,就推翻了上一年的教案,将“用约200行代码实现一个命令行编程智能体”安排为第一周的动手实验,并要求学生后续向真实的生产级开源代码库提交代码合并请求。这一安排背后的判断是:AI原生开发者正在成为软件团队中的核心角色,而理解智能体的内部机制,是成为这类工程师的第一步。
本教程将带你完成同样的核心任务:从零开始,用约200行代码实现一个能在终端中运行的极简编程智能体。它具备四个最基础的工具——读取文件、写入文件、编辑文件、执行终端命令,并通过一个“模型调用循环”自主完成多步编程任务。
学完本教程,你将掌握:
本教程适合以下读者:
适用场景包括:本地代码理解与修改助手、小规模重构与批处理脚本生成、代码审查前的预检工具、教学演示,以及在此基础上二次开发企业内部智能体的原型验证。
在动手之前,请确认以下条件已经就绪:
python -m venv .venv)。你也可以使用Go、TypeScript等熟悉的其他语言实现,本文示例以Python为准。workspace目录作为智能体的工作区;密钥一律通过环境变量注入,禁止写死在代码或提交到代码仓库。单轮调用大模型,只能得到一段“文字回答”,模型无法真正“做事”。让模型具备行动能力,需要三个要素配合:
三者组合起来,就构成智能体的主循环:
理解了这个循环,就理解了当前主流代码智能体的骨架。不同产品之间的差异,主要体现在工具更丰富、上下文工程更精细、权限与沙箱体系更完善、调度能力更强,但底层循环逻辑是一致的。
创建项目目录、虚拟环境并安装SDK依赖;随后定义工作区根目录常量,并约定后续所有文件操作与命令执行都必须限制在该目录内。之所以把安全边界放在第一步,是因为后面要实现的工具具备执行任意命令的能力,先画好红线,可以避免调试过程中出现误删文件、越权访问等问题。
系统提示词决定智能体的“性格”与边界,是上下文工程的核心。建议覆盖四方面内容:角色定位(你是谁、能做什么)、操作约束(只在工作区内活动、破坏性命令需谨慎)、输出规范(每步只做必要操作、任务完成后简洁总结)、异常行为(需求不明确时先提问而不是臆测)。注意提示词要精炼、可执行、无歧义,堆砌长篇大论反而会稀释关键约束的权重。
为四个基础工具编写结构化定义,说明每个工具的用途、参数类型与是否必填:
read_file:读取指定路径的文件内容;write_file:创建或覆盖写入文件;edit_file:以“旧文本替换为新文本”的方式做精确编辑;run_command:在工作区内执行终端命令。工具描述的质量直接影响模型的选择准确率——模型是依据这些描述来判断“该用哪个工具、怎么传参”的,因此描述要写清楚适用情形与限制条件。
推荐用“注册表”模式组织执行器,即一个工具名到函数的映射,便于后续扩展。实现时的关键点:
主循环维护消息列表,按第四节描述的流程反复调用模型。两个必须实现的保护机制:一是设置最大迭代次数,防止模型陷入“调用工具—观察结果—再调用”的死循环;二是当模型返回内容中没有工具调用时,视为任务完成,输出最终回答并退出本轮循环。
从环境变量读取接入地址、API密钥和模型名称,完成客户端初始化,与代码逻辑解耦。生成参数建议使用默认值或较低的温度,编程任务对稳定性的要求高于多样性。配置项与代码分离,便于在不同模型服务之间切换。
当对话变长后,需要做上下文预算控制:保留系统提示词与最近若干轮对话,对更早的历史进行裁剪或摘要压缩;对超长的工具返回结果做截断。这一步是“上下文工程”的入门实践,直接决定智能体在长任务中的稳定性与调用成本。
以下为核心骨架示例(完整实现约200行,LLMClient为抽象封装,具体实现取决于你所选模型服务的SDK,只要支持携带工具定义并返回结构化工具调用即可):
import os, subprocessMAX_ITERATIONS = 15WORKSPACE = os.path.abspath("./workspace")SYSTEM_PROMPT = """你是一个运行在终端中的编程助手。规则:1. 所有文件操作仅限当前工作区,禁止访问工作区之外的路径;2. 执行命令前评估风险,避免删除、覆盖等破坏性操作;3. 每步只调用必要的工具,任务完成后用简洁文字总结;4. 信息不足时先向用户提问,不要臆测。"""def safe_path(path: str) -> str:full = os.path.abspath(os.path.join(WORKSPACE, path))if not full.startswith(WORKSPACE):raise ValueError("路径越界:仅允许访问工作区内的文件")return fulldef execute_tool(name: str, args: dict) -> str:try:if name == "read_file":with open(safe_path(args["path"]), encoding="utf-8") as f:return f.read()[:4000]if name == "edit_file":p = safe_path(args["path"])text = open(p, encoding="utf-8").read()if args["old"] not in text:return "编辑失败:未找到目标文本,请先读取文件确认内容"open(p, "w", encoding="utf-8").write(text.replace(args["old"], args["new"], 1))return "编辑完成"if name == "run_command":proc = subprocess.run(args["command"], shell=True, cwd=WORKSPACE,capture_output=True, text=True, timeout=30)return (proc.stdout + proc.stderr)[:4000] or "命令执行完成"return f"未知工具:{name}"except Exception as e:return f"工具执行出错:{e}" # 错误也回填,便于模型自我修正def agent_loop(llm, messages):for _ in range(MAX_ITERATIONS):resp = llm.chat(messages, tools=TOOLS)messages.append(resp.message)if not resp.tool_calls:return resp.text # 无工具调用,视为任务完成for call in resp.tool_calls:result = execute_tool(call.name, call.arguments)messages.append({"role": "tool","tool_call_id": call.id, "content": result})return "已达最大迭代次数,任务未完成。"def main():llm = LLMClient(base_url=os.environ["LLM_BASE_URL"],api_key=os.environ["LLM_API_KEY"],model=os.environ["LLM_MODEL"])messages = [{"role": "system", "content": SYSTEM_PROMPT}]while True:user_input = input("> ").strip()if not user_input:continuemessages.append({"role": "user", "content": user_input})print(agent_loop(llm, messages))
建议按递进难度设计三个测试用例,分别验证不同能力:
同时逐项核对验证清单:工具调用参数是否合法、是否存在访问工作区之外的路径、是否出现无意义的重复调用、最终回答是否正确且简洁。三项测试全部通过,说明最小可用智能体已经跑通。
本教程以约200行代码为载体,完整走通了实现一个极简编程智能体的全过程:从理解“模型调用—工具执行—结果回填”的核心循环,到编写系统提示词、定义四个基础工具、实现安全的执行器与主循环,再到分场景验证、排查典型问题并给出优化方向。你会发现,智能体并不神秘,它的能力上限取决于工具设计的严谨程度与上下文工程的精细程度。建议你在此骨架上持续迭代:增加工具、完善权限体系、尝试更复杂的真实任务,逐步建立属于自己的AI原生开发方法论。