我如何从头开始构建一个 Agentic 编码 CLI
Source: Dev.to
抱歉,我无法直接访问外部链接获取文章内容。请您把需要翻译的文本粘贴在这里,我会帮您翻译成简体中文。
Source:
核心洞见:这只是一个循环
每个具备代理功能的编码工具——无论多么完善——都遵循相同的基本模式:
while needs_follow_up:
# 1️⃣ Send conversation + tools → LLM
# 2️⃣ If LLM returns tool calls → execute them, append results, loop
# 3️⃣ If LLM returns plain text → finish
这就是“魔法”:带函数调用的 while 循环。
其余 95% 包含:
- 上下文管理
- 工具执行
- 错误处理
- 权限检查
简化的代理循环
def run_agent_loop(user_input, conversation, config):
conversation.add_user(user_input)
for iteration in range(config.max_iterations):
stream = completion(
model=routed_model,
messages=conversation.messages,
tools=TOOL_DEFINITIONS,
stream=True,
)
text, tool_calls, usage = process_stream(stream)
if not tool_calls:
# No tools called — model is done
conversation.add_assistant(content=text)
break
# Execute each tool, feed results back, loop
for tc in tool_calls:
result = execute_tool(tc.name, tc.args)
conversation.add_tool_result(tc.id, result)
当用户说 “修复 app.py 中的 bug” 时,LLM 并不会直接编辑文件。它会:
- 调用
read_file("app.py")→ 获取源码。 - 调用
edit_file(...)并提供修复。 - 调用
run_command("pytest")进行验证。
每一步都是一次工具调用,循环会执行该调用并将结果反馈到下一次迭代中。
架构
┌─────────────────────────────────────────────────┐
│ cli.py (UI) │
│ REPL loop · slash commands · Rich terminal UI │
└──────────────────────┬──────────────────────────┘
│
┌──────────────────────▼──────────────────────────┐
│ agent.py (Brain) │
│ Agentic loop · context management · permissions│
│ │
│ LiteLLM ──→ Claude / GPT / Gemini / Ollama │
└──────────────────────┬──────────────────────────┘
│
┌──────────────────────▼──────────────────────────┐
│ tools.py (Hands) │
│ read_file · write_file · edit_file │
│ run_command · git_commit · search_text │
└─────────────────────────────────────────────────┘
| 文件 | 职责 |
|---|---|
| cli.py | 终端 UI(REPL、斜杠命令、会话管理) |
| agent.py | 大脑(代理循环、流式处理、权限、上下文压缩) |
| tools.py | 工具(文件 I/O、bash 执行、git、搜索) |
我最自豪的功能:成本感知路由
大多数 AI 编码工具只能锁定单一模型,导致你为一个简单解释付的费用和为一次完整重构付的费用相同。AgentCode 会根据请求的复杂度进行分类,并自动选择能够处理该请求且最便宜的模型。
路由表
| 层级 | 示例提示 | 模型 | 原因 |
|---|---|---|---|
| 轻量 | “这个函数是做什么的” | Haiku | 快速、便宜——仅仅是阅读和解释 |
| 中等 | “为 app.py 编写单元测试” | Sonnet | 需要理解代码并生成新代码 |
| 重型 | “重构整个认证系统” | Opus | 多文件、多步骤、架构思考 |
分类使用简单的模式匹配:
def classify_complexity(user_input):
text = user_input.lower()
heavy_score = sum(1 for p in HEAVY_PATTERNS if re.search(p, text))
medium_score = sum(1 for p in MEDIUM_PATTERNS if re.search(p, text))
if heavy_score >= 2:
return "heavy"
elif medium_score >= 1:
return "medium"
else:
return "light"
透明、易于调整,并且能真正省钱。
你可以随时使用 /model 命令覆盖自动选择。
流式传输:用户体验的差异
第一个版本在显示任何内容之前会等待完整的 LLM 响应,导致终端空白 5–10 秒。加入流式传输后,体验变成了 实时对话。
挑战
在一个自主循环中,LLM 可以在同一次响应中返回 纯文本 和 工具调用。文本 token 会逐个到达,而工具调用的参数则以片段形式出现,需要在执行前组装完整。
流式处理器
def process_stream(stream):
full_text = ""
tool_calls_acc = {}
for chunk in stream:
delta = chunk.choices[0].delta
# Text tokens — print immediately
if delta.content:
print(delta.content, end="", flush=True)
full_text += delta.content
# Tool call fragments — accumulate silently
if delta.tool_calls:
for tc_delta in delta.tool_calls:
idx = tc_delta.index
if idx not in tool_calls_acc:
tool_calls_acc[idx] = {"id": "", "name": "", "arguments": ""}
if tc_delta.function.arguments:
tool_calls_acc[idx]["arguments"] += tc_delta.function.arguments
return full_text, tool_calls_acc
- 文本实时流式输出到屏幕。
- 工具调用在后台悄悄组装。
用户会看到文字瞬间出现,而代理则在决定下一步要做什么。
多模型支持
AgentCode 使用 LiteLLM 作为抽象层。这意味着我只需用 OpenAI 的格式编写一套工具定义,LiteLLM 会将其转换为各供应商所需的格式。
在对话中切换模型
❯ /model gpt-4o
✓ Switched to gpt-4o
❯ /model claude-opus-4-6
✓ Switched to claude-opus-4-6
❯ /model ollama/qwen2.5-coder
✓ Switched to ollama/qwen2.5-coder
相同的工具、相同的循环、不同的大脑。本地 Ollama 选项意味着你可以零 API 成本运行整个系统。
权限系统
任何写文件或执行命令的工具在操作前都会询问:
🔒 Permission Required
Tool: write_file
Args: {"path": "src/handler.py", "content": "..."}
Allow this action? [y/n] (y):
只读工具(read_file、list_directory、search)自动批准。这使流程保持快速,同时防止代理在未经您同意的情况下进行任何破坏性操作。
我学到的
-
上下文管理是难点。
代理循环本身很简单。真正的工程工作在于管理上下文窗口——压缩旧消息、进行摘要、保持正确的信息可用——这才是关键。 -
工具定义比提示更重要。
具备清晰参数描述的完善工具胜过巧妙的系统提示。大语言模型会把工具模式当作文档来阅读。 -
流式输出改变一切。
“等待 8 秒才得到响应”与“文字即时出现”之间的差别,就像是使用令人沮丧的工具与令人愉快的工具之间的区别。 -
多模型灵活性被低估了。
不同模型在不同任务上各有优势。能够在它们之间热切换——或让路由器自行决定——就意味着你始终拥有最合适的工具来完成工作。
试一试
pip install agentcode-cli
export ANTHROPIC_API_KEY="your-key"
agentcode
代码库是可读的 Python —— 没有框架,也没有抽象。如果你想了解代理式编码工具是如何工作的,克隆它并阅读 agent.py。整个循环大约 50 行。
- GitHub:
- PyPI:
采用 MIT 许可证。欢迎反馈和贡献。
标签: python, ai, opensource, tutorial