从零构建AI Agent CLI:大模型自动化与命令行工具开发实战
1. 从零到一为什么我们需要一个AI Agent CLI最近和几个做AI应用开发的朋友聊天大家都有一个共同的痛点大模型的能力很强但每次想让它干点“自动化”的活儿都得写一堆胶水代码。比如我想让模型帮我分析一下今天的Git提交记录自动生成周报草稿或者监控某个API的状态出问题了自动发个通知。这些想法听起来不复杂但真动手做就得在Python脚本里反复调用OpenAI的API处理上下文管理、工具调用、错误重试代码很快就变得臃肿不堪。这就是AI Agent CLI的价值所在。它不是一个简单的命令行调用大模型的工具而是一个将大模型的推理能力与操作系统、本地工具、外部服务无缝衔接的自动化枢纽。你可以把它理解为一个“超级外脑”的命令行接口你只需要用自然语言告诉它目标它就能自主规划、调用工具、执行任务并把结果清晰地呈现给你。从搜索热词来看无论是claude code cli、kimi cli还是codex cli大家的诉求都很明确需要一个更高效、更直接、更可编程的方式来驾驭AI Agent的能力而不是被困在Web界面或复杂的SDK里。所以今天我想和你分享的就是如何从零开始打造一个属于你自己的、功能实用且可扩展的AI Agent CLI。这个项目非常适合有一定Python基础对AI应用开发感兴趣并且厌倦了重复造轮子的开发者。我们将从最核心的架构设计讲起一步步实现任务规划、工具调用、记忆管理和命令行交互最终你会得到一个能理解复杂指令、能使用电脑本地工具如读写文件、执行命令、查询网络的真正可用的智能助手。这不仅是一个学习项目更能直接提升你日常开发和工作的效率。2. 核心架构设计构建一个高效且可扩展的Agent大脑在动手写代码之前我们必须先把架构想清楚。一个健壮的AI Agent CLI其核心远不止是封装一个API调用。我们需要设计几个关键模块让它们各司其职协同工作。2.1 模块职责划分与通信机制我的设计主要分为四个核心层它们通过清晰的数据结构如字典、Pydantic模型进行通信核心推理引擎 (Core LLM Engine)这是Agent的“大脑”。它负责理解用户指令、进行任务分解、规划执行步骤并在需要时决定调用哪个工具。我们将选用一个性能足够且成本可控的大模型API作为核心例如OpenAI的GPT-4o或 Anthropic 的 Claude 3 Haiku。这一层的关键是设计高质量的系统提示词System Prompt明确告诉模型它的角色、能力和行动规范。工具系统 (Tool System)这是Agent的“手和脚”。工具是Agent与外界交互的唯一途径。一个工具本质上是一个函数附带清晰的名称、描述和参数定义。系统需要维护一个工具注册表并能根据模型的请求动态查找并执行对应的工具。我们将实现一些基础工具如execute_shell_command执行Shell命令、read_file读取文件、search_web网络搜索等。记忆与状态管理 (Memory State Management)这是Agent的“短期记忆”。为了处理多轮对话和复杂任务Agent需要记住之前的交互历史对话记忆和当前任务的执行状态任务状态。我们将实现一个简单的对话历史记录并在每次调用模型时将相关的历史信息作为上下文喂给它。对于复杂任务链还需要管理步骤间的状态传递。命令行界面与交互循环 (CLI Interaction Loop)这是Agent的“嘴和耳朵”。它负责接收用户的自然语言输入将推理引擎返回的结果可能是文本、工具调用请求呈现给用户并处理用户对工具执行结果的确认或提供额外输入。我们将构建一个交互式的REPLRead-Eval-Print Loop环境。它们的工作流程是这样的CLI接收用户输入 - 记忆模块将历史对话和当前输入组合成上下文 - 发送给核心推理引擎 - 模型返回一个结构化响应可能是最终答案也可能是一个工具调用请求- 如果是要调用工具工具系统则执行该工具并获取结果 - 将工具执行结果作为新消息追加到上下文 - 再次发送给模型进行下一步推理 - 循环直至模型返回最终答案 - CLI输出结果。提示在设计之初就采用这种“消息流”架构而非一次性问答是为后续支持复杂的、多步骤的任务如“帮我写个代码然后运行它再根据输出修改”打下坚实基础。这模仿了ReAct、AutoGPT等框架的核心思想。2.2 技术栈选型背后的考量选择合适的技术栈能让开发事半功倍。以下是我的选择及其理由语言Python这是AI领域毋庸置疑的首选。生态繁荣从大模型SDKopenai,anthropic到命令行解析argparse,click,typer再到异步IO都有成熟的库。开发速度快社区支持好。大模型SDKopenai或anthropic根据你选择的模型提供商而定。它们封装了API调用、流式响应等细节稳定可靠。建议同时做好抽象便于未来切换模型。命令行框架typer相比传统的argparsetyper基于类型提示能自动生成美观的CLI支持子命令、参数验证开发体验极佳。click也是一个好选择但typer与现代Python风格更契合。工具调用与结构化输出Pydantic这是关键。我们需要模型返回结构化的数据而不是自由文本。Pydantic可以让我们轻松定义工具调用的参数格式name,arguments并且其模型能与openai等库的function calling特性完美结合实现类型安全的工具调用解析。配置管理pydantic-settings用于管理API密钥、模型名称等配置。支持从环境变量、.env文件读取安全且方便。异步框架asyncio虽然初期可以同步但考虑到工具调用如网络请求可能是IO密集型的使用异步可以避免阻塞提升响应速度为未来扩展留有余地。这个技术栈平衡了能力、开发效率和可维护性。它没有选择像LangChain这样的重型框架是为了保证我们对每一层的实现都有完全的控制力和理解这正是“从零开始”的意义。3. 分步实现打造你的第一个智能命令行伙伴理论说得再多不如一行代码。让我们打开编辑器开始构建。我会假设项目名为ai_agent_cli。3.1 项目初始化与基础配置首先创建项目结构并安装依赖。我习惯用poetry管理依赖和虚拟环境用pip也可以。mkdir ai_agent_cli cd ai_agent_cli poetry init -n # 交互式创建pyproject.toml这里用-n跳过编辑pyproject.toml加入依赖[tool.poetry] name ai-agent-cli version 0.1.0 description A DIY AI Agent Command Line Interface authors [Your Name youexample.com] [tool.poetry.dependencies] python ^3.9 openai ^1.0.0 # 或 anthropic typer {extras [all], version ^0.9.0} pydantic ^2.0.0 pydantic-settings ^2.0.0 httpx ^0.25.0 # 用于工具中的HTTP请求 rich ^13.0.0 # 让命令行输出更美观 python-dotenv ^1.0.0 # 加载.env文件 [tool.poetry.group.dev.dependencies] pytest ^7.0.0 ipython ^8.0.0 [build-system] requires [poetry-core] build-backend poetry.core.masonry.api然后安装依赖poetry install。接下来创建配置文件。我们使用pydantic-settings来管理敏感信息。# config.py from pydantic_settings import BaseSettings from pydantic import Field class Settings(BaseSettings): openai_api_key: str Field(..., envOPENAI_API_KEY) openai_base_url: str | None Field(None, envOPENAI_BASE_URL) # 兼容其他兼容API model_name: str gpt-4o # 默认模型 class Config: env_file .env settings Settings()在项目根目录创建.env文件务必加入.gitignoreOPENAI_API_KEYsk-your-actual-key-here这样我们就安全地管理了API密钥。3.2 核心引擎与大模型对话并解析结构化指令核心引擎的任务是发送提示词接收模型响应并解析出结构化指令尤其是工具调用。我们创建一个agent/core.py。首先定义消息格式。这遵循OpenAI的API格式。# agent/core.py from typing import Literal, List, Dict, Any, Optional from pydantic import BaseModel class Message(BaseModel): role: Literal[system, user, assistant, tool] content: str name: Optional[str] None # 用于工具调用时的工具名 tool_call_id: Optional[str] None # 工具调用ID class ToolCall(BaseModel): id: str type: Literal[function] function function: Dict[str, Any] # 包含 name 和 arguments然后实现一个简单的对话历史管理类。# agent/memory.py from .core import Message from typing import List class ConversationMemory: def __init__(self, system_prompt: str, max_tokens: int 4000): self.system_prompt system_prompt self.max_tokens max_tokens # 简单的上下文长度管理 self.messages: List[Message] [Message(rolesystem, contentsystem_prompt)] def add_message(self, message: Message): self.messages.append(message) # 简单的截断策略如果消息太多移除最早的非系统消息 self._truncate_conversation() def _truncate_conversation(self): # 这是一个简化的实现。生产环境需要考虑token计数。 if len(self.messages) 20: # 例如保留最多20轮对话 # 保留系统消息和最近的一些消息 self.messages [self.messages[0]] self.messages[-19:] def get_messages_for_api(self) - List[Dict]: return [msg.model_dump(exclude_noneTrue) for msg in self.messages]现在实现最核心的AgentEngine。它将整合模型调用和初步的工具调用解析。# agent/engine.py import json from typing import List, Dict, Any, Optional from openai import OpenAI # 或 from anthropic import Anthropic from .core import Message, ToolCall from .memory import ConversationMemory from config import settings class AgentEngine: def __init__(self, memory: ConversationMemory): self.memory memory self.client OpenAI(api_keysettings.openai_api_key, base_urlsettings.openai_base_url) self.model settings.model_name async def get_completion(self, tools: List[Dict] None) - Dict[str, Any]: 获取模型补全支持工具调用。 messages self.memory.get_messages_for_api() kwargs { model: self.model, messages: messages, stream: False, } if tools: kwargs[tools] tools kwargs[tool_choice] auto # 让模型决定是否调用工具 try: response await self.client.chat.completions.create(**kwargs) # 注意openai1.0.0 的异步调用是 await client.chat.completions.create(...) # 这里为了简化先写同步后面会调整。实际使用时需用 async with OpenAI(...) as client: 和 await # 我们先按同步逻辑写理解流程。 response_message response.choices[0].message return { content: response_message.content, tool_calls: response_message.tool_calls # 这是一个ToolCall对象列表 } except Exception as e: # 处理网络错误、API错误等 return {content: f调用模型时发生错误: {e}, tool_calls: None} def parse_tool_calls(self, tool_calls: List[Any]) - List[ToolCall]: 解析API返回的工具调用信息。 parsed [] for tc in tool_calls or []: # 将API返回的对象转换为我们的Pydantic模型 parsed.append(ToolCall( idtc.id, functiontc.function.model_dump() # 假设是OpenAI的FunctionCall对象 )) return parsed注意上面的get_completion方法为了流程清晰写成了同步形式。在实际项目中强烈建议使用异步async/await因为工具调用如网络请求可能是IO密集型的。你可以使用httpx.AsyncClient和asyncio来改造。这里我们先理解核心流程。3.3 工具系统赋予Agent行动的能力工具是Agent能力的扩展。我们定义一个基础工具类并实现几个常用工具。# agent/tools/base.py from typing import Any, Dict, Type from pydantic import BaseModel, Field import inspect class Tool(BaseModel): 工具基类。每个工具对应一个函数和其参数模式。 name: str description: str args_schema: Type[BaseModel] # 用Pydantic模型定义参数 def run(self, **kwargs) - Any: 运行工具。子类需要实现具体的逻辑。 raise NotImplementedError def to_openai_format(self) - Dict: 将工具描述转换为OpenAI Function Calling格式。 schema self.args_schema.model_json_schema() # 清理schema移除不必要的标题等 return { type: function, function: { name: self.name, description: self.description, parameters: schema } }现在实现一个具体的工具执行Shell命令。# agent/tools/shell.py import subprocess from typing import Optional from pydantic import BaseModel, Field from .base import Tool class ShellArgs(BaseModel): command: str Field(description要执行的Shell命令例如 ls -la 或 python --version) timeout: Optional[int] Field(default30, description命令执行超时时间秒) class ShellTool(Tool): def __init__(self): super().__init__( nameexecute_shell_command, description在本地系统上执行一个Shell命令并返回输出。谨慎使用确保命令安全。, args_schemaShellArgs ) def run(self, command: str, timeout: int 30) - str: try: result subprocess.run( command, shellTrue, capture_outputTrue, textTrue, timeouttimeout ) output fSTDOUT:\n{result.stdout}\n\nSTDERR:\n{result.stderr}\n\nRETURN CODE: {result.returncode} return output except subprocess.TimeoutExpired: return 错误命令执行超时。 except Exception as e: return f执行命令时发生未知错误: {e}再实现一个读取文件的工具。# agent/tools/file.py from pathlib import Path from pydantic import BaseModel, Field, validator from .base import Tool class ReadFileArgs(BaseModel): file_path: str Field(description要读取的文件的路径可以是相对路径或绝对路径) validator(file_path) def prevent_path_traversal(cls, v): # 一个非常基础的安全检查防止路径穿越攻击 if .. in v or v.startswith(/) or ~ in v: # 在实际项目中这里需要更严格的限制比如将操作限制在特定工作目录下 raise ValueError(出于安全考虑文件路径受到限制。) return v class ReadFileTool(Tool): def __init__(self): super().__init__( nameread_file, description读取指定文件的内容。, args_schemaReadFileArgs ) def run(self, file_path: str) - str: try: path Path(file_path) if not path.exists(): return f错误文件 {file_path} 不存在。 if not path.is_file(): return f错误{file_path} 不是一个文件。 # 简单限制文件大小防止读取过大文件 if path.stat().st_size 1024 * 1024: # 1MB return 错误文件过大出于安全考虑不予读取。 return path.read_text(encodingutf-8, errorsignore) except Exception as e: return f读取文件时发生错误: {e}我们需要一个工具管理器来注册和查找工具。# agent/tools/registry.py from typing import Dict, List from .base import Tool class ToolRegistry: def __init__(self): self._tools: Dict[str, Tool] {} def register(self, tool: Tool): if tool.name in self._tools: raise ValueError(f工具 {tool.name} 已注册。) self._tools[tool.name] tool def get_tool(self, name: str) - Tool: tool self._tools.get(name) if not tool: raise KeyError(f未找到工具: {name}) return tool def get_all_tools(self) - List[Tool]: return list(self._tools.values()) def get_openai_tools(self) - List[Dict]: return [tool.to_openai_format() for tool in self._tools.values()]在项目初始化时创建注册表并添加工具。# agent/__init__.py 或 main.py 中 from .tools.registry import ToolRegistry from .tools.shell import ShellTool from .tools.file import ReadFileTool def create_tool_registry() - ToolRegistry: registry ToolRegistry() registry.register(ShellTool()) registry.register(ReadFileTool()) # 未来可以在这里注册更多工具网络搜索、计算器、数据库查询等 return registry3.4 主循环与CLI集成让一切运转起来最后我们将所有模块串联起来形成一个交互式的主循环并用typer包装成命令行应用。首先编写核心的主循环逻辑。# agent/loop.py import json from typing import Optional from rich.console import Console from rich.markdown import Markdown from .engine import AgentEngine from .memory import ConversationMemory from .tools.registry import ToolRegistry from .core import Message console Console() class AgentLoop: def __init__(self, engine: AgentEngine, tool_registry: ToolRegistry): self.engine engine self.tool_registry tool_registry async def process_input(self, user_input: str): 处理单轮用户输入。 # 1. 将用户输入添加到记忆 self.engine.memory.add_message(Message(roleuser, contentuser_input)) # 进入Agent思考-行动循环 max_steps 10 # 防止无限循环 for step in range(max_steps): # 2. 获取模型响应 tools_def self.tool_registry.get_openai_tools() response await self.engine.get_completion(toolstools_def) # 3. 处理响应 if response.get(tool_calls): # 模型要求调用工具 tool_calls response[tool_calls] for tc in tool_calls: tool_name tc.function.name tool_args json.loads(tc.function.arguments) console.print(f[bold yellow]Agent 决定调用工具: {tool_name}[/bold yellow]) console.print(f参数: {tool_args}) try: tool self.tool_registry.get_tool(tool_name) # 运行工具 result tool.run(**tool_args) console.print(f[green]工具执行结果:[/green]\n{result}) # 将工具执行结果作为消息添加回对话历史 self.engine.memory.add_message( Message( roletool, contentstr(result), tool_call_idtc.id, nametool_name ) ) except Exception as e: error_msg f调用工具 {tool_name} 失败: {e} console.print(f[red]{error_msg}[/red]) self.engine.memory.add_message( Message( roletool, contenterror_msg, tool_call_idtc.id, nametool_name ) ) # 工具调用后继续循环让模型根据结果进行下一步思考 continue else: # 模型给出了最终答案 final_answer response.get(content, 无响应内容) # 将助手的回复也加入记忆 self.engine.memory.add_message(Message(roleassistant, contentfinal_answer)) # 输出答案 console.print(Markdown(final_answer)) break else: console.print([red]警告达到最大循环步骤可能陷入循环。[/red])然后创建命令行入口点。# cli.py import asyncio import typer from rich.prompt import Prompt from agent.memory import ConversationMemory from agent.engine import AgentEngine from agent.loop import AgentLoop from agent import create_tool_registry app typer.Typer(help你的AI Agent命令行助手) # 定义系统提示词 - 这是Agent的“人格”和行为准则 SYSTEM_PROMPT 你是一个运行在命令行环境中的AI助手。你的目标是帮助用户完成各种任务。 你可以使用工具来与用户的计算机系统交互例如执行命令、读取文件等。 请遵循以下规则 1. 安全第一。不要执行任何可能破坏系统、删除文件或泄露隐私的危险命令。如果用户要求请礼貌拒绝并解释风险。 2. 保持专注。如果任务复杂将其分解为步骤一步一步来。 3. 清晰沟通。将工具执行的结果和你的思考过程用易于理解的方式告诉用户。 4. 如果遇到错误或不确定请如实告知用户不要编造信息。 你拥有的工具 {tools_list} 现在开始帮助用户吧。对于用户的第一个请求请先友好地打招呼。 app.command() def chat(): 启动交互式聊天会话。 # 初始化组件 tool_registry create_tool_registry() # 动态生成工具列表描述 tools_desc \n.join([f- {tool.name}: {tool.description} for tool in tool_registry.get_all_tools()]) final_system_prompt SYSTEM_PROMPT.format(tools_listtools_desc) memory ConversationMemory(system_promptfinal_system_prompt) engine AgentEngine(memorymemory) loop AgentLoop(engineengine, tool_registrytool_registry) console typer.echo console([bold green]AI Agent CLI 已启动输入 quit 或 exit 退出。[/bold green]) console(f[dim]可用工具: {, .join([t.name for t in tool_registry.get_all_tools()])}[/dim]) while True: try: user_input Prompt.ask(\n[bold cyan]你[/bold cyan]) if user_input.lower() in (quit, exit, q): console(再见) break if not user_input.strip(): continue # 运行异步主循环 asyncio.run(loop.process_input(user_input)) except KeyboardInterrupt: console(\n\n中断。输入 quit 退出。) except EOFError: console(\n再见) break except Exception as e: console(f[red]发生未预期错误: {e}[/red]) if __name__ __main__: app()现在你可以通过poetry run python cli.py chat来启动你的AI Agent了它会先打招呼然后等待你的指令。你可以尝试说“列出当前目录的文件”它会调用execute_shell_command工具运行ls -la并返回结果。4. 进阶优化与实战技巧让你的Agent更强大可靠一个能跑起来的原型只是第一步。要让这个Agent真正实用、可靠还需要在以下几个方向深耕。4.1 提升稳定性的关键设计1. 上下文长度管理与摘要我们之前用简单的消息条数截断这很不精确。更专业的做法是计算Token数。你可以使用tiktoken库针对OpenAI模型来估算。当上下文接近模型限制时如16K需要触发摘要让模型自己总结之前的对话重点然后将摘要作为新的系统消息或历史消息替换掉旧的详细记录从而腾出空间。2. 工具调用的验证与沙箱我们的Shell工具非常危险必须实施沙箱机制。命令白名单/黑名单禁止执行rm -rf /、format、dd等危险命令。可以维护一个危险模式列表。工作目录限制使用subprocess的cwd参数将命令执行限制在某个安全目录如/tmp/agent_workspace下。超时控制我们已经做了这很重要。用户确认对于高风险操作如修改文件、安装软件可以让Agent先输出计划执行的命令等待用户明确确认y/N后再执行。3. 错误处理与重试机制网络请求、API调用都可能失败。需要为get_completion和工具run方法添加重试逻辑例如使用tenacity库。对于模型返回的格式错误如工具参数JSON解析失败应能捕获异常并将错误信息反馈给模型让它重新生成。4.2 扩展Agent能力的实用工具基础工具只能满足简单需求。要让Agent成为得力助手需要为其装备更多“武器”。网络搜索工具集成Serper API、Google Programmable Search或Bing Search API。让Agent能获取实时信息。关键点教会模型如何构造搜索查询词。代码解释与执行工具创建一个安全的Python代码沙箱如使用Docker容器或pysandbox。让Agent可以编写、测试小的代码片段。文件写入工具与读取对应实现安全的文件写入。必须包含路径检查和内容预览确认。日历/邮件集成通过OAuth2连接Google Calendar或Outlook让Agent可以帮你安排会议、发送邮件需极其谨慎的授权和范围控制。自定义工具这是最强大的部分。你可以为你的日常工作流创建专用工具。例如一个“部署服务”工具封装了连接测试服务器、执行部署脚本的步骤一个“查询数据库”工具用于快速拉取业务数据。添加新工具只需三步1) 定义参数模型2) 继承Tool基类实现run方法3) 在create_tool_registry函数中注册它。整个架构是高度可插拔的。4.3 性能优化与用户体验打磨1. 流式输出目前模型思考时间长时用户会干等。实现流式输出Streaming可以显著提升体验。OpenAI和Anthropic的SDK都支持流式响应。你需要修改get_completion和主循环逐步打印模型生成的content而不是等全部生成完。对于工具调用可以在模型“思考”时显示一个动画指示器。2. 会话持久化每次启动都重新开始对话很不方便。可以将ConversationMemory中的消息列表序列化如用json保存到本地文件或数据库。下次启动时加载实现跨会话的记忆。可以为每个会话生成一个ID。3. 配置化与插件系统将系统提示词、工具列表、模型参数等提取到外部配置文件如config.yaml中。更高级的是实现一个插件系统允许用户通过放置Python文件到特定目录如~/.agent_cli/plugins/来动态加载新工具而无需修改核心代码。5. 避坑指南与常见问题排查在开发和使用的过程中我踩过不少坑。这里总结一下希望你能避开。5.1 开发与调试中的典型问题问题1模型不调用工具总是直接回答。可能原因1工具描述不够清晰。模型是根据工具的名称和描述来决定是否调用的。确保你的description字段准确描述了工具的功能和使用场景。例如“获取当前天气”就比“天气工具”好得多。可能原因2系统提示词未强调工具使用。在系统提示词中明确指令如“如果你需要获取实时信息或操作本地系统请务必使用我提供的工具。”调试方法打印出发送给模型的完整消息列表和工具定义检查是否有误。也可以先用一个非常简单的、模型肯定需要工具的指令测试如“现在的时间戳是多少”如果你没有提供时间工具它应该调用Shell工具执行date命令。问题2工具调用参数解析失败。可能原因模型生成的参数JSON格式错误或者与Pydantic模型不匹配。解决方案在parse_tool_calls和工具run方法中加入更健壮的异常捕获。当解析失败时将错误信息作为tool角色的消息返回给模型让它修正。例如“上次调用的参数无效错误信息是XXX。请重新尝试。”问题3上下文溢出模型失忆。现象对话进行到后面模型似乎忘记了很早之前的约定或信息。解决方案如前所述实现基于Token的精确计数和摘要功能。对于超长文档处理可以考虑使用RAG检索增强生成技术将文档切片存储到向量数据库在需要时检索相关片段注入上下文而不是塞入整个文档。5.2 安全与生产环境部署警告警告1Shell工具是最大的安全隐患。永远不要在有重要数据的生产服务器上直接运行未加严格限制的Agent。即使有白名单也可能存在绕过。考虑以下策略完全禁用在不可信环境中直接不注册Shell工具。模拟环境提供一个模拟的Shell环境只返回预设的安全命令结果。审计日志记录所有被请求和执行命令方便事后审查。警告2API密钥与数据隐私。.env文件绝不能提交到版本控制。考虑支持加密的密钥存储或使用操作系统提供的密钥链。明确告知用户对话内容可能会被发送到第三方AI API提供商如OpenAI因此不要输入高度敏感信息。警告3无限循环与资源消耗。我们的主循环有max_steps限制这很好。还需要考虑单轮对话时间限制防止单个复杂任务卡住CLI。Token消耗监控记录每轮对话的Token使用量避免意外产生高额费用。5.3 效果不佳时的提示词工程技巧如果Agent表现不符合预期调整提示词往往是性价比最高的方法。角色扮演Persona在系统提示词中为其设定一个更具体的角色如“你是一位经验丰富的Linux系统管理员”或“你是一位细心周到的个人秘书”这能引导其输出风格和专业性。少样本学习Few-shot在系统提示词中提供几个用户指令和理想Agent行为的例子。例如用户今天的天气怎么样 助手我将使用网络搜索工具来查询实时天气。 然后展示工具调用和回复的完整格式这能极大地规范模型的输出格式和行为模式。分步指令Step-by-step对于复杂任务在用户指令中直接要求模型“请先规划步骤然后逐步执行”有时比让它自己规划更有效。后处理Post-processing不要完全信任模型的输出。对于关键操作如文件路径、命令可以编写简单的后处理脚本进行二次验证和清洗。实现一个AI Agent CLI的过程就像在精心组装一个机器人。从最初只能简单对话的“大脑”到装上可以操作世界的“手脚”再到为它制定行为准则、提升可靠性。每一步的深入都让你对AI如何与真实世界交互有更深刻的理解。这个项目没有终点你可以根据自己的需求不断为它添加新的工具和能力让它真正成为你工作流中不可或缺的一部分。我自己的版本已经集成了十多个工具从管理服务器到处理数据报表它每天都能帮我省下不少时间。希望你的构建之旅同样充满乐趣和收获。