CL-04_nanoAgent:103 行极简实现到完整 Agent

nanoAgent:103 行极简实现到完整 Agent

"问题不在于你看到了什么,而在于你看见了什么。" ------ 梭罗

前言

2026 年,AI Agent 生态迎来了前所未有的爆发。从 LangGraph 到 CrewAI,从 AutoGen 到 Google ADK,框架层的繁荣让开发者目不暇接。然而,一个仅有 103 行 Python 代码的项目 nanoAgent 却在 GitHub 上引发了另一场讨论:Agent 的本质到底有多简单?

这个由开发者 sanbuphy 创建的极简项目,没有向量数据库,没有复杂的图编排,没有记忆管理中间件------它仅靠 OpenAI 的 Function Calling 接口和一个 while 循环,就实现了能执行 bash 命令、读写文件的完整 Agent。项目 README 的一句话精准概括了它的哲学:"If you can read ~100 lines of Python, you understand agents."

在 Agent 框架日趋复杂化的今天,nanoAgent 的存在像一面镜子------它照出的不是一个玩具,而是所有 Agent 框架共有的最小公分母。理解这 103 行,就是理解 Agent 的第一性原理。


一、极简哲学:为什么 103 行就够了?

1.1 Agent 的本质是什么?

在深入代码之前,我们先厘清一个概念。当我们说"AI Agent"时,我们到底在说什么?

根据 Lilian Weng 在其经典博文《LLM Powered Autonomous Agents》中的定义,一个 Agent 系统的核心组件包括:

  1. 规划(Planning):将大任务拆解为子任务
  2. 记忆(Memory):短期上下文与长期知识
  3. 工具使用(Tool Use):调用外部能力
  4. 行动(Action):执行具体操作并观察结果

这四个组件构成了 Agent 的核心循环。但请注意------规划可以退化为"让 LLM 自己决定下一步",记忆可以退化为"消息历史列表",工具可以是最基础的 bash/read/write,行动就是执行函数调用。

当一切退化到最小状态,Agent 的本质就暴露出来了:

复制代码
while 任务未完成:
    1. 把上下文发给 LLM
    2. LLM 决定下一步(调用工具 or 返回结果)
    3. 如果调用工具,执行它,把结果追加到上下文
    4. 重复

这就是 nanoAgent 的全部逻辑。它没有"框架",因为它不需要框架。

1.2 与 Karpathy 的 "Software 2.0" 精神一脉相承

Andrej Karpathy 在 2017 年提出 "Software 2.0" 的概念:未来的软件不再是人类手写的逻辑规则,而是由数据和优化目标驱动的神经网络权重。Agent 正是这一理念的最新体现------你不需要编写"如果用户说X就执行Y"的规则树,你只需要给 LLM 提供工具列表和任务描述,让它自己决定调用链。

nanoAgent 的极简性恰好证明了这一点:当你的"程序"是 GPT-4o-mini 的推理能力时,你真正需要编写的"胶水代码"极少。

1.3 Less is More 的工程价值

极简不是炫技,而是有实际工程价值的:

  • 可审计性:103 行代码,10 分钟读完,每个决策点都透明
  • 可调试性:没有抽象层遮蔽,出错时你能直接看到是哪一行的问题
  • 可移植性:一个文件,一个依赖(openai),任何 Python 环境都能跑
  • 教学价值:新成员通过阅读这 103 行就能理解 Agent 的核心机制

二、架构总览

在逐行解析之前,先通过架构图理解 nanoAgent 的整体结构:
#mermaid-svg-HLhiuwWqeV5KD08p{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HLhiuwWqeV5KD08p .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HLhiuwWqeV5KD08p .error-icon{fill:#552222;}#mermaid-svg-HLhiuwWqeV5KD08p .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HLhiuwWqeV5KD08p .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HLhiuwWqeV5KD08p .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HLhiuwWqeV5KD08p .marker.cross{stroke:#333333;}#mermaid-svg-HLhiuwWqeV5KD08p svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HLhiuwWqeV5KD08p p{margin:0;}#mermaid-svg-HLhiuwWqeV5KD08p .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HLhiuwWqeV5KD08p .cluster-label text{fill:#333;}#mermaid-svg-HLhiuwWqeV5KD08p .cluster-label span{color:#333;}#mermaid-svg-HLhiuwWqeV5KD08p .cluster-label span p{background-color:transparent;}#mermaid-svg-HLhiuwWqeV5KD08p .label text,#mermaid-svg-HLhiuwWqeV5KD08p span{fill:#333;color:#333;}#mermaid-svg-HLhiuwWqeV5KD08p .node rect,#mermaid-svg-HLhiuwWqeV5KD08p .node circle,#mermaid-svg-HLhiuwWqeV5KD08p .node ellipse,#mermaid-svg-HLhiuwWqeV5KD08p .node polygon,#mermaid-svg-HLhiuwWqeV5KD08p .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HLhiuwWqeV5KD08p .rough-node .label text,#mermaid-svg-HLhiuwWqeV5KD08p .node .label text,#mermaid-svg-HLhiuwWqeV5KD08p .image-shape .label,#mermaid-svg-HLhiuwWqeV5KD08p .icon-shape .label{text-anchor:middle;}#mermaid-svg-HLhiuwWqeV5KD08p .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HLhiuwWqeV5KD08p .rough-node .label,#mermaid-svg-HLhiuwWqeV5KD08p .node .label,#mermaid-svg-HLhiuwWqeV5KD08p .image-shape .label,#mermaid-svg-HLhiuwWqeV5KD08p .icon-shape .label{text-align:center;}#mermaid-svg-HLhiuwWqeV5KD08p .node.clickable{cursor:pointer;}#mermaid-svg-HLhiuwWqeV5KD08p .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HLhiuwWqeV5KD08p .arrowheadPath{fill:#333333;}#mermaid-svg-HLhiuwWqeV5KD08p .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HLhiuwWqeV5KD08p .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HLhiuwWqeV5KD08p .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HLhiuwWqeV5KD08p .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HLhiuwWqeV5KD08p .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HLhiuwWqeV5KD08p .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HLhiuwWqeV5KD08p .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HLhiuwWqeV5KD08p .cluster text{fill:#333;}#mermaid-svg-HLhiuwWqeV5KD08p .cluster span{color:#333;}#mermaid-svg-HLhiuwWqeV5KD08p div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HLhiuwWqeV5KD08p .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HLhiuwWqeV5KD08p rect.text{fill:none;stroke-width:0;}#mermaid-svg-HLhiuwWqeV5KD08p .icon-shape,#mermaid-svg-HLhiuwWqeV5KD08p .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HLhiuwWqeV5KD08p .icon-shape p,#mermaid-svg-HLhiuwWqeV5KD08p .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HLhiuwWqeV5KD08p .icon-shape .label rect,#mermaid-svg-HLhiuwWqeV5KD08p .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HLhiuwWqeV5KD08p .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HLhiuwWqeV5KD08p .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HLhiuwWqeV5KD08p :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} nanoAgent 架构(103 行)
核心循环
工具定义层
包含 tool_calls
无 tool_calls
tool_calls 响应
messages + tools
用户输入
run_agent 函数
LLM 响应
工具调度器
返回最终结果
execute_bash
read_file
write_file
将结果追加到 messages
OpenAI API

Function Calling

这个架构图揭示了 nanoAgent 的三个关键层次:

  1. 入口层:接收用户输入,构建初始 messages
  2. 核心循环:LLM 调用 → 工具调度 → 结果回注 → 再次调用
  3. 工具层:三个最小工具(bash、read、write)的实现

三、103 行逐行解析

3.1 初始化与客户端(第 1-10 行)

python 复制代码
import os
import json
import subprocess
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    base_url=os.environ.get("OPENAI_BASE_URL")
)

这 10 行完成了 Agent 的"基础设施"搭建。注意 base_url 参数------这是 nanoAgent 能对接任意 OpenAI 兼容 API 的关键。无论是本地的 Ollama、vLLM,还是第三方代理服务,只要兼容 OpenAI 的接口格式,就能直接使用。

这种设计体现了接口标准化的思想。OpenAI 的 Function Calling 格式已经事实上成为了行业标准,nanoAgent 通过依赖这一标准,实现了模型无关性。

3.2 工具定义层(第 12-50 行)

python 复制代码
tools = [
    {
        "type": "function",
        "function": {
            "name": "execute_bash",
            "description": "Execute a bash command",
            "parameters": {
                "type": "object",
                "properties": {"command": {"type": "string"}},
                "required": ["command"],
            },
        },
    },
    # read_file 和 write_file 类似定义...
]

工具定义采用 JSON Schema 格式,这是 OpenAI Function Calling 协议的标准方式。每个工具包含三个要素:

  • name:工具的唯一标识符
  • description:自然语言描述,LLM 靠这个理解何时该用这个工具
  • parameters:JSON Schema 格式的参数定义

这里的 description 字段至关重要------它是 LLM 决策的依据。一个好的 description 应该明确说明工具的能力边界和适用场景。

3.3 工具实现层(第 52-70 行)

python 复制代码
def execute_bash(command):
    result = subprocess.run(command, shell=True, capture_output=True, text=True)
    return result.stdout + result.stderr

def read_file(path):
    with open(path, "r") as f:
        return f.read()

def write_file(path, content):
    with open(path, "w") as f:
        f.write(content)
    return f"Wrote to {path}"

这是 Agent 的"手和脚"。三个函数分别对应:

  • execute_bash:系统级操作的万能接口。通过 bash,Agent 可以安装包、运行脚本、查询系统状态------几乎所有计算机能做的事情都可以通过这个入口完成
  • read_file:获取信息的能力。Agent 通过读取文件来理解代码、配置和数据
  • write_file:产出结果的能力。Agent 可以创建文件、修改代码、生成报告

注意一个关键设计决策:nanoAgent 将 bash 作为一等公民工具 。这意味着它不需要为每个操作实现专用工具------curl 替代 HTTP 客户端,grep 替代搜索工具,git 替代版本控制工具。这是极简主义的核心策略:用通用工具替代专用工具。

3.4 核心循环(第 75-100 行)

python 复制代码
def run_agent(user_message, max_iterations=5):
    messages = [
        {"role": "system", "content": "You are a helpful assistant. Be concise."},
        {"role": "user", "content": user_message},
    ]
    for _ in range(max_iterations):
        response = client.chat.completions.create(
            model=os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
            messages=messages,
            tools=tools,
        )
        message = response.choices[0].message
        messages.append(message)
        if not message.tool_calls:
            return message.content
        for tool_call in message.tool_calls:
            name = tool_call.function.name
            args = json.loads(tool_call.function.arguments)
            print(f"[Tool] {name}({args})")
            if name not in functions:
                result = f"Error: Unknown tool '{name}'"
            else:
                result = functions[name](**args)
            messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": result})
    return "Max iterations reached"

这是整个 Agent 的心脏。让我们拆解这个循环的每一步:

Step 1:构建初始上下文

messages 列表是 Agent 的"短期记忆"。初始包含 system prompt 和用户消息。

Step 2:调用 LLM

将当前 messages 和 tools 定义发送给 LLM。LLM 返回的可能是:

  • 一段普通文本(任务完成)
  • 一个或多个 tool_calls(需要执行工具)

Step 3:判断是否需要工具调用

python 复制代码
if not message.tool_calls:
    return message.content

这是循环的终止条件。当 LLM 认为任务完成或无需工具时,返回最终结果。

Step 4:执行工具并回注结果

python 复制代码
for tool_call in message.tool_calls:
    # 执行工具
    result = functions[name](**args)
    # 将结果追加到上下文
    messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": result})

关键点:工具结果以 "tool" 角色追加到 messages。这样 LLM 在下一轮调用时能看到工具的执行结果,从而做出后续决策。

Step 5:循环控制

max_iterations=5 是一个安全阀,防止 Agent 陷入无限循环。在实际使用中,你可以根据任务复杂度调整这个值。

3.5 入口点(第 101-103 行)

python 复制代码
if __name__ == "__main__":
    import sys
    task = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Hello"
    print(run_agent(task))

简洁的命令行接口。使用方式:

bash 复制代码
python agent.py "找到所有 .py 文件并统计总代码行数"

四、功能扩展:从 103 行到生产级

nanoAgent 的极简设计天然支持扩展。以下是几种常见的扩展路径:

4.1 添加记忆系统

基础版 nanoAgent 没有跨会话记忆。我们可以用一个 Markdown 文件实现简单的持久化记忆:

python 复制代码
MEMORY_FILE = "agent_memory.md"

def load_memory():
    if not os.path.exists(MEMORY_FILE):
        return ""
    with open(MEMORY_FILE, 'r') as f:
        content = f.read()
        # 只保留最近 50 行,防止上下文溢出
        lines = content.split('\n')
        return '\n'.join(lines[-50:]) if len(lines) > 50 else content

def save_memory(task, result):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    entry = f"\n## {timestamp}\n**Task:** {task}\n**Result:** {result}\n"
    with open(MEMORY_FILE, 'a') as f:
        f.write(entry)

run_agent 中,将 load_memory() 的结果注入 system prompt,任务完成后调用 save_memory(),就实现了跨会话的记忆持久化。

4.2 添加任务规划

nanoAgent 的 agent-plus.py 版本增加了一个 create_plan 函数,让 Agent 在执行前先进行任务分解:

python 复制代码
def create_plan(task):
    response = client.chat.completions.create(
        model=os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
        messages=[
            {"role": "system", "content": "Break down the task into 3-5 simple, actionable steps. Return as JSON array."},
            {"role": "user", "content": f"Task: {task}"}
        ],
        response_format={"type": "json_object"}
    )
    plan_data = json.loads(response.choices[0].message.content)
    steps = plan_data.get("steps", [task]) if isinstance(plan_data, dict) else plan_data
    for i, step in enumerate(steps, 1):
        print(f"  {i}. {step}")
    return steps

这是一种 Plan-then-Execute 模式。Agent 先将复杂任务分解为子步骤,然后逐步执行。这比直接让 Agent 处理复杂任务更可靠,因为每个子步骤的上下文更聚焦。

4.3 添加安全沙箱

基础版的 execute_bash 直接在宿主系统上执行命令,存在安全风险。一个简单的改进是添加命令白名单和超时控制:

python 复制代码
ALLOWED_PATTERNS = ['ls', 'cat', 'grep', 'find', 'wc', 'head', 'tail', 'echo', 'pwd']
BLOCKED_PATTERNS = ['rm -rf', 'sudo', 'chmod 777', 'mkfs', 'dd if=']

def execute_bash_safe(command, timeout=30):
    # 检查黑名单
    for pattern in BLOCKED_PATTERNS:
        if pattern in command:
            return f"Error: Blocked dangerous command pattern: {pattern}"
    
    try:
        result = subprocess.run(
            command, shell=True, capture_output=True, 
            text=True, timeout=timeout
        )
        return result.stdout + result.stderr
    except subprocess.TimeoutExpired:
        return "Error: Command timed out"

更进一步,可以使用 Docker 容器作为沙箱,将 Agent 的执行环境与宿主完全隔离。


五、代码示例:完整 103 行实现

以下是 nanoAgent 的完整代码,可以直接复制运行:

python 复制代码
"""
nanoAgent - 103 行极简 AI Agent
使用 OpenAI Function Calling 实现的最小 Agent
工具:execute_bash, read_file, write_file
"""

import os
import json
import subprocess
from openai import OpenAI

# ========== 初始化客户端 ==========
client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    base_url=os.environ.get("OPENAI_BASE_URL")
)

# ========== 工具定义(JSON Schema 格式) ==========
tools = [
    {
        "type": "function",
        "function": {
            "name": "execute_bash",
            "description": "Execute a bash command on the system",
            "parameters": {
                "type": "object",
                "properties": {
                    "command": {"type": "string", "description": "The bash command to execute"}
                },
                "required": ["command"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "read_file",
            "description": "Read the contents of a file at the given path",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "Path to the file to read"}
                },
                "required": ["path"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "write_file",
            "description": "Write content to a file at the given path",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "Path to the file to write"},
                    "content": {"type": "string", "description": "Content to write to the file"},
                },
                "required": ["path", "content"],
            },
        },
    },
]

# ========== 工具实现 ==========
def execute_bash(command):
    """执行 bash 命令,返回 stdout + stderr"""
    result = subprocess.run(command, shell=True, capture_output=True, text=True)
    return result.stdout + result.stderr

def read_file(path):
    """读取文件内容"""
    with open(path, "r") as f:
        return f.read()

def write_file(path, content):
    """写入文件内容"""
    with open(path, "w") as f:
        f.write(content)
    return f"Wrote to {path}"

# 工具名称到函数的映射
functions = {
    "execute_bash": execute_bash,
    "read_file": read_file,
    "write_file": write_file,
}

# ========== Agent 核心循环 ==========
def run_agent(user_message, max_iterations=5):
    """
    Agent 核心逻辑:
    1. 构建上下文(messages)
    2. 调用 LLM
    3. 如果 LLM 返回 tool_calls,执行工具并回注结果
    4. 重复直到 LLM 不再调用工具(任务完成)或达到最大迭代次数
    """
    messages = [
        {"role": "system", "content": "You are a helpful assistant. Be concise."},
        {"role": "user", "content": user_message},
    ]
    
    for iteration in range(max_iterations):
        # 调用 LLM
        response = client.chat.completions.create(
            model=os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
            messages=messages,
            tools=tools,
        )
        message = response.choices[0].message
        messages.append(message)
        
        # 如果没有工具调用,说明任务完成
        if not message.tool_calls:
            return message.content
        
        # 执行所有工具调用
        for tool_call in message.tool_calls:
            name = tool_call.function.name
            args = json.loads(tool_call.function.arguments)
            print(f"[Tool] {name}({args})")
            
            # 执行工具
            if name not in functions:
                result = f"Error: Unknown tool '{name}'"
            else:
                result = functions[name](**args)
            
            # 将工具结果追加到上下文
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": str(result),
            })
    
    return "Max iterations reached"

# ========== 入口 ==========
if __name__ == "__main__":
    import sys
    task = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Hello"
    print(run_agent(task))

运行示例:

bash 复制代码
# 安装依赖
pip install openai

# 设置环境变量
export OPENAI_API_KEY='your-key-here'
export OPENAI_MODEL='gpt-4o-mini'  # 可选

# 运行
python agent.py "列出当前目录下所有 Python 文件"
python agent.py "创建一个 hello.py,内容是打印 Hello World"
python agent.py "读取 README.md 并总结其内容"

六、权衡分析:极简的代价

极简设计不是免费的午餐。nanoAgent 在获得简洁性的同时,也做出了明确的权衡。

6.1 与主流框架的对比

维度 nanoAgent(103 行) LangGraph CrewAI OpenAI Agents SDK
代码量 103 行 ~50,000 行 ~30,000 行 ~15,000 行
依赖 1 个(openai) 20+ 15+ 5+
多 Agent 支持 ❌ 单 Agent ✅ 图编排 ✅ 角色组队 ✅ Handoff
记忆系统 ❌ 无(需自行扩展) ✅ 内置检查点 ✅ 内置 ✅ 内置
流式输出 ❌ 同步阻塞
错误恢复 ❌ 简单重试 ✅ 重试+回退
MCP 支持
学习成本 ⭐ 10 分钟 ⭐⭐⭐ 2-3 天 ⭐⭐ 1 天 ⭐⭐ 半天
适用场景 学习/原型/脚本 复杂工作流 团队协作 生产级应用
可调试性 ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐

6.2 nanoAgent 的优势

  1. 零学习成本:任何会写 Python 的人都能在 10 分钟内理解并修改
  2. 零依赖地狱 :只需 pip install openai,没有版本冲突
  3. 完全透明:没有抽象层,每个决策都可见
  4. 极致可移植:一个文件,复制粘贴即可使用

6.3 nanoAgent 的局限

  1. 单 Agent 限制:无法编排多个 Agent 协作
  2. 无状态管理:每次运行都是无状态的,没有断点续传
  3. 同步阻塞:工具执行是同步的,无法并行
  4. 无流式输出:用户必须等待完整响应
  5. 安全风险:直接执行 bash 命令,没有沙箱隔离

6.4 何时选择 nanoAgent?

  • 学习 Agent 原理:最好的入门教材
  • 快速原型验证:验证一个 Agent 想法是否可行
  • 简单自动化脚本:文件整理、代码生成等简单任务
  • 嵌入到现有系统:作为更大系统的一个组件

何时选择 nanoAgent?

  • 需要多 Agent 协作
  • 需要复杂的错误恢复
  • 需要生产级的监控和日志
  • 需要流式输出和实时反馈

七、总结:看见 Agent 的本质

nanoAgent 的价值不在于它能做什么------103 行代码的局限性是显而易见的。它的价值在于它揭示了什么

当你读完这 103 行,你会意识到:

  1. Agent 不是魔法:它就是一个循环(调用 LLM → 执行工具 → 回注结果)
  2. LLM 是引擎,循环是骨架:框架只是给这个骨架添加了血肉
  3. Function Calling 是关键接口:它让 LLM 从"对话机器"变成了"行动者"
  4. 工具定义的质量决定了 Agent 的能力上限:description 写得好不好,直接影响 LLM 的决策质量

正如 Rich Hickey 在《Simple Made Easy》中所强调的:简单(simple)不等于容易(easy),简单意味着没有交织的复杂性。 nanoAgent 是简单的------它没有不必要的复杂性。而当你需要更多功能时,你可以在理解这个简单内核的基础上,有选择地添加复杂性。

这就是 nanoAgent 教给我们的最重要的一课:在添加任何抽象之前,先理解你正在抽象的东西。


参考文献

  1. Weng, L. (2023). "LLM Powered Autonomous Agents." lilianweng.github.io. https://lilianweng.github.io/posts/2023-06-23-agent/
  2. Yao, S., et al. (2023). "ReAct: Synergizing Reasoning and Acting in Language Models." ICLR 2023. arXiv:2210.03629
  3. Schick, T., et al. (2023). "Toolformer: Language Models Can Teach Themselves to Use Tools." NeurIPS 2023. arXiv:2302.04761
  4. Karpathy, A. (2017). "Software 2.0." Medium. https://medium.com/@karpathy/software-2-0-a64152b37c35
  5. OpenAI. (2024). "Function Calling Guide." OpenAI Platform Documentation. https://platform.openai.com/docs/guides/function-calling

本系列覆盖 AI 大模型基础、Agent 开发、MCP 协议、Skill 开发、RAG、模型微调、部署推理 七大方向,从入门到实战的全栈内容持续更新中。

所有文章的 Markdown 源文件、可运行代码、高清配图已整理成完整资料包。

👍 点赞 + ⭐ 关注,评论区扣「1」,挨个发你领取方式 👇

相关推荐
元岳数字人小元1 小时前
数字人交互的用户体验设计与场景交互感受
运维·人工智能·开源·人机交互·交互
乱世刀疤1 小时前
AI Fabric智能算网:重塑AI算力基座,开启智算效能革命
人工智能
资讯综合1 小时前
2026年GEO服务商评测:Deepseek适配与网站优化能力成为合作重点
大数据·人工智能
cxr8281 小时前
从“结论“到“假说“:VentureMind 的本体论革命
人工智能
xu_徐1 小时前
品牌在DeepSeek、Kimi缺少正面信息?亚孖酷奇如何提升AI可见度
人工智能
hey you~1 小时前
语音机器人如何减少进线客户等待时长?提速方案
人工智能·智能客服·asr·ivr·语音机器人·呼叫中心·等待时长
runningshark2 小时前
Lecture: Signposting Your Contribution: Prompt Point to My Example
prompt
hans汉斯2 小时前
【计算机科学与应用】层级评论上下文依赖识别数据集构建与研究——以小红书旅游评论数据为例
人工智能·算法·yolo·目标检测·cnn·旅游