一文读懂 LLM、Agent、Skills 与 MCP:AI 应用的四层架构

引言

打开任何一份 AI 行业报告,你都会反复看到四个词:LLM、Agent、Skills、MCP。它们被同时提及的频率越来越高,但很少有人把它们讲清楚——很多教程把 LLM 和 Agent 混为一谈,把 Skills 说成”高级 Prompt”,把 MCP 当成”新版 Function Calling”。

这种混淆带来的直接后果是:你买了一堆工具,读了很多教程,却仍然写不出一个能落地的 AI 应用。因为你不清楚每一层负责什么、层与层之间靠什么接口通信、出了问题该在哪一层排查

本文不打算重复”什么是大模型”这种科普,而是把四个概念拆成四层架构,用一套贯穿始终的实战案例(自动发布博客)讲清楚:

  • LLM 是大脑,负责推理与生成;
  • Agent 是大脑加上四肢,负责决策与循环;
  • Skills 是肌肉记忆,负责把”怎么做”沉淀成可复用流程;
  • MCP 是神经系统,负责让 Agent 安全、标准化地调用外部工具。

读完之后,你应该能自己画出一张架构图,并且知道该给哪一层加什么代码。

Hermes Agent 工作形态

一、四个概念各是什么

1. LLM:大脑

LLM(Large Language Model,大语言模型) 是一个在海量文本上训练的神经网络,输入一段文本,输出一段文本。它本身不会上网、不会读文件、不会执行命令——它只会”预测下一个 token”。

关键点:LLM 是无状态的。它不知道你是谁、不知道上次聊到哪、不知道你项目里有哪些文件。所有”记住””执行”的能力,都是在它之外搭起来的。

# LLM 的本质:一个纯函数,输入 token,输出 token
def llm(prompt: str) -> str:
    # 没有工具、没有文件、没有网络——只有预测
    return "根据您提供的信息,建议您……"

answer = llm("Ubuntu 22.04 怎么升级内核?")

2. Agent:大脑 + 四肢 + 循环

Agent(智能体) 是围绕 LLM 搭建的一个运行循环:用户给目标 → LLM 规划 → 调用工具 → 观察结果 → 再规划 → …… 直到目标完成。

同样是”升级内核”这个需求,LLM 只能输出一段文字建议;Agent 会真的去 ssh 到服务器、执行 apt、检查日志、失败重试,最后回报”已升级到 5.15.0-124″。

区别不在于模型能力,而在于有没有一个循环在持续调用工具并观察结果

  用户目标
     │
     ▼
┌──────────────────────────┐
│  Agent Loop(决策循环)   │
│  ┌────────┐   ┌────────┐ │
│  │  LLM   │──▶│ Planner│ │
│  │(推理)  │◀──│        │ │
│  └────────┘   └───┬────┘ │
│        ▲          │      │
│        │          ▼      │
│   观察结果 ◀── 工具执行  │
│  (Observation) (Tool Call)│
└──────────────────────────┘

3. Skills:可复用的肌肉记忆

Skills(技能) 是把”完成某类任务的标准流程”写成的结构化文档(通常是一个带 YAML 头部的 Markdown 文件),让 Agent 遇到同类任务时直接照做,而不必每次都重新摸索。

一个 Skill 至少包含:

  • 触发条件:什么情况下该用这个技能;
  • 步骤:带精确命令的操作序列;
  • 坑点(Pitfalls):踩过的失败路径及规避方法;
  • 验证方式:怎么确认做对了。

Skill 和 Prompt 的本质区别是:Prompt 是一次性的口头交代,Skill 是沉淀下来的书面 SOP。Prompt 写错了这一次就浪费了;Skill 修一次,之后每次执行都受益。

Skill 文件示例

4. MCP:工具接入的标准协议

MCP(Model Context Protocol,模型上下文协议) 是一套让 LLM/Agent 标准化调用外部工具的协议,本质是 JSON-RPC 2.0 之上的约定。

在它出现之前,每接一个工具都要写一套专属的胶水代码:OpenAI 的 Function Calling、Anthropic 的 Tool Use、各家 SDK 的自定义 schema…… MCP 把这些统一成三种原语:

原语 方向 作用
tools/list 客户端 → 服务端 服务端宣告”我能提供哪些工具”
tools/call 客户端 → 服务端 客户端请求执行某个工具
resources/* 双向 暴露文档、文件等上下文资源

一句话理解:MCP Server 是把工具封装成标准接口的进程,MCP Client 是负责发现和调用的那一方。Agent 只需要连 Client,不需要知道工具背后的实现细节。

5. 四层总览

┌─────────────────────────────────────────┐
│  L1  Skills   可复用流程 / SOP            │  ← 解决"怎么做"
├─────────────────────────────────────────┤
│  L2  Agent    决策循环 / 工具编排          │  ← 解决"谁来做"
├─────────────────────────────────────────┤
│  L3  MCP      工具接入标准协议            │  ← 解决"怎么调"
├─────────────────────────────────────────┤
│  L4  LLM      推理与文本生成              │  ← 解决"想什么"
└─────────────────────────────────────────┘

排查问题的方向也是反的:结果不对先看 L2(循环决策是不是错了),工具调用失败看 L3(协议/参数),输出质量差看 L4(模型/Prompt),流程跑偏看 L1(Skill 描述是否准确)。

二、实战:一个 Agent 自动发布博客

下面用一个真实场景把四层串起来:让 Agent 读到 Markdown 稿件,转成 HTML,发布到 WordPress,再把链接回传

1. Agent 主循环(L2)

Agent 的核心就是一个 while 循环:调用 LLM 决定下一步,执行工具,把结果喂回去。

import json
import subprocess

def agent_loop(goal: str, max_turns: int = 10) -> str:
    """最简 Agent 循环:LLM 规划 + 工具执行 + 观察结果"""
    messages = [{"role": "user", "content": goal}]
    for turn in range(max_turns):
        # 1) LLM 规划下一步(这里抽象掉具体模型调用)
        decision = call_llm(messages, tools=TOOL_SCHEMAS)

        # 2) 如果没有工具调用,说明任务完成
        if not decision.get("tool_calls"):
            return decision["content"]

        # 3) 执行工具,把结果追加进上下文
        for call in decision["tool_calls"]:
            result = dispatch_tool(call["name"], call["arguments"])
            messages.append({
                "role": "tool",
                "name": call["name"],
                "content": json.dumps(result, ensure_ascii=False),
            })
    return "达到最大轮次,任务未完成"

这里的 dispatch_tool 就是 L3(MCP)要接管的地方。

2. 加载 Skills(L1)

Agent 启动时扫描技能目录,把命中的 Skill 注入上下文,让 LLM”照着 SOP 做”。

# 扫描可用技能并提取 frontmatter
for skill in /root/.hermes/skills/web-development/wordpress-install; do
  echo "=== $(basename $skill) ==="
  sed -n '/^---$/,/^---$/p' "$skill/SKILL.md" | head -n 8
done

# 统计技能总数与分类
find /root/.hermes/skills -name 'SKILL.md' | wc -l
find /root/.hermes/skills -mindepth 1 -maxdepth 1 -type d | sort

输出示例:

=== wordpress-install ===
---
name: wordpress-install
description: "安装、配置、管理和发布 WordPress — 包括手动部署、wp-cli 管理、REST API / Direct PHP 自动发文..."
version: 1.0.1
---
72
/root/.hermes/skills/web-development
/root/.hermes/skills/devops
/root/.hermes/skills/research

3. 通过 MCP 调用工具(L3)

Agent 不直接 exec 发布脚本,而是通过 MCP Client 请求一个”publish 工具”。Client 配置文件声明要连哪些 Server:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/wwwroot"],
      "transport": "stdio"
    },
    "wordpress": {
      "command": "python3",
      "args": ["/root/tools/wp-mcp-server.py"],
      "env": { "WP_DIR": "/home/wwwroot/www.stellardata.top" },
      "transport": "stdio"
    }
  }
}

Agent 拿到 tools/list 返回后,会看到类似这样的工具清单:

{
  "tools": [
    {
      "name": "wp_publish_markdown",
      "description": "将本地 Markdown 文件转换为 HTML 并发布到 WordPress",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": { "type": "string", "description": "Markdown 文件绝对路径" },
          "category": { "type": "string", "description": "WordPress 分类名称" }
        },
        "required": ["path"]
      }
    }
  ]
}

4. MCP 协议的原始报文

MCP 走 JSON-RPC 2.0,一次完整的”列出工具 → 调用工具”长这样:

// 请求:列出可用工具
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

// 响应:调用 publish 工具
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      { "type": "text", "text": "Published: https://www.stellardata.top/?p=3263" }
    ]
  }
}

关键在于:Agent 侧只依赖 tools/list + tools/call 这两个方法名,工具实现在哪台机器、用哪种语言写,它完全不用关心。

5. 客户端与运行时配置

MCP Server 的运行参数通常放在配置文件和环境变量里:

# Hermes Agent 的 MCP 客户端配置片段
mcp:
  enabled: true
  servers:
    wordpress:
      command: python3
      args: [/root/tools/wp-mcp-server.py]
      transport: stdio
      timeout: 60
    filesystem:
      command: npx
      args: [-y, "@modelcontextprotocol/server-filesystem", /home/wwwroot]
; MCP Server 运行时配置(.env / INI 风格)
[wordpress]
WP_DIR = /home/wwwroot/www.stellardata.top
POST_AUTHOR = 1
DEFAULT_CATEGORY = IT互联网
FEATURED_IMAGE_ID = 1623

[security]
; 允许 Agent 发布的分类白名单
ALLOWED_CATEGORIES = IT互联网,IT资讯,大数据
; 是否允许覆盖已有文章
ALLOW_OVERWRITE = false

三、动手写一个 MCP Server

理论讲完,下面给一个可直接运行的最小 MCP Server:把”发布 Markdown”暴露成标准工具。

1. Server 实现

#!/usr/bin/env python3
"""最小 WordPress MCP Server:把发布能力暴露为标准 MCP 工具"""
import json
import os
import subprocess
import sys

WP_DIR = os.environ.get("WP_DIR", "/home/wwwroot/www.stellardata.top")
PUBLISH_SH = "/root/.hermes/skills/web-development/wordpress-install/scripts/direct-publish.sh"

TOOLS = [{
    "name": "wp_publish_markdown",
    "description": "将本地 Markdown 文件发布到 WordPress",
    "inputSchema": {
        "type": "object",
        "properties": {
            "path": {"type": "string", "description": "Markdown 文件路径"}
        },
        "required": ["path"],
    },
}]

def handle_publish(args: dict) -> dict:
    proc = subprocess.run(
        ["bash", PUBLISH_SH, args["path"]],
        capture_output=True, text=True, cwd=WP_DIR, timeout=120,
    )
    return {"stdout": proc.stdout, "stderr": proc.stderr, "code": proc.returncode}

def dispatch(request: dict) -> dict:
    method = request.get("method")
    rid = request.get("id")
    if method == "tools/list":
        return {"jsonrpc": "2.0", "id": rid, "result": {"tools": TOOLS}}
    if method == "tools/call":
        name = request["params"]["name"]
        args = request["params"]["arguments"]
        if name == "wp_publish_markdown":
            return {"jsonrpc": "2.0", "id": rid,
                    "result": {"content": [{"type": "text", "text": json.dumps(handle_publish(args), ensure_ascii=False)}]}}
        return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32602, "message": f"unknown tool: {name}"}}
    return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32601, "message": f"unknown method: {method}"}}

def main():
    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue
        sys.stdout.write(json.dumps(dispatch(json.loads(line)), ensure_ascii=False) + "n")
        sys.stdout.flush()

if __name__ == "__main__":
    main()

2. 本地连通性验证

不启动完整 Agent,直接用管道验证 Server 是否正常响应:

printf '%sn' 
  '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' 
  | python3 /root/tools/wp-mcp-server.py | python3 -m json.tool

# 验证 WordPress 环境就绪
cd /home/wwwroot/www.stellardata.top && php -r '
define("WP_USE_THEMES", false);
require("wp-load.php");
echo "WP OK: " . get_bloginfo("name") . "n";
'

# 检查发布脚本可执行
test -x /root/.hermes/skills/web-development/wordpress-install/scripts/direct-publish.sh && echo "publish.sh OK"

3. 端到端调用

# 准备一篇测试稿件
cp /tmp/auto_article.md /tmp/mcp-test-article.md

# 直接调用工具方法,绕过 Agent
printf '%sn' 
  '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"wp_publish_markdown","arguments":{"path":"/tmp/mcp-test-article.md"}}}' 
  | python3 /root/tools/wp-mcp-server.py

执行成功后,result.content[0].text 里会包含发布脚本的 stdout,其中包括文章 ID 与 permalink。

四、常见问题

Q1:LLM 和 Agent 是同一个东西吗?

不是。LLM 是一个模型(一次输入、一次输出、无状态);Agent 是运行 LLM 的循环 + 工具编排层。同一个 GPT-4 或 Qwen,接进不同 Agent 框架后能力差异巨大——差异全部来自 L2,而不是 L4。

Q2:Skills 不就是更长的 Prompt 吗?

表面像,机制不同。Prompt 是本次会话的临时指令;Skill 是持久化、带元数据、可版本管理的流程文档,Agent 会按触发条件按需加载,只在需要时占用上下文。工程上还多出三层价值:可复用(多个 Agent 共享)、可维护(改一次全局生效)、可验证(Skill 里的验证步骤)。

Q3:MCP 会取代 Function Calling 吗?

互补而非替代。Function Calling 是模型层能力(教模型如何吐出结构化参数),MCP 是协议层标准(定义工具如何被发现与调用)。模型输出 Function Calling 格式的 JSON,Agent 再通过 MCP 路由到具体 Server。MCP 解决的是”生态碎片化”,Function Calling 解决的是”模型会不会调”。

Q4:我需要自己写 MCP Server 吗?

看场景。如果只是个人使用现成工具(文件系统、GitHub、Slack),直接用官方 Server 即可。但如果你的核心能力藏在内部系统里(公司 CMS、内网数据库、私有 API),写一个 Server 把能力封装成标准工具,是整个 Agent 体系里 ROI 最高的一步——一次封装,所有 Agent 都能调用。

Q5:Skills 有安全风险吗?

有,而且是供应链风险。Agent 会信任并执行 Skill 里的命令,一个恶意 Skill 等同于给 Agent 一把万能钥匙。三点防御:① 只从可信来源安装 Skill;② 安装前审读全文,尤其是含 rmcurl | sh、凭据读取的步骤;③ 高权限操作(写数据库、发消息、扣费)在 Agent 侧设确认门禁,不要让 Skill 单独决定。

五、总结

  1. LLM 是大脑:只做推理与生成,无状态、无工具、无记忆。它决定了输出质量的天花板。
  2. Agent 是循环:真正带来”自动化”的是 LLM 外面的那个 while 循环,不是模型本身。
  3. Skills 是 SOP:把踩过的坑沉淀成文档,一次修复、长期受益,是 Agent 能力复用的基本单位。
  4. MCP 是协议:统一工具接入方式,解决生态碎片化,让内部能力一次封装、处处调用。
  5. 排查顺序自下而上:输出差改 LLM/Prompt,调不动查 MCP,跑偏改 Skill,决策错改 Agent。

如果你只能做一件事,建议从写第一个 MCP Server开始——把你自己每天都要手动干的那个活儿暴露成标准工具,你会立刻理解这四个概念为什么必须一起出现。

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容