前言

在 AI 时代,我们经常听到 Agent、Skills、MCP、Function Calling 等概念,但这些概念之间的关系和使用场景往往让人困惑。本文将以一个实际的使用场景为例,深入解析这些概念。

场景介绍

环境配置

  • 平台:Ubuntu 服务器(已安装 OpenClaw 3.2)
  • Agent:OpenClaw-Vango(私人 AI 助手)
  • LLM:GLM-5(智谱AI,通过 API 密钥访问)
  • 权限:读写文件系统、执行 Shell 命令、访问 GitHub
  • 网络:畅通,可访问公网

使用场景

  1. 用户与 OpenClaw-Vango 进行多轮对话,学习英语时态
  2. 用户让 Agent 生成一篇英语学习笔记
  3. Agent 自动将笔记提交到 GitHub 仓库

核心问题

  • 远端 LLM(GLM-5)、本地 OpenClaw、Skills、MCP、Function Calling 之间是什么关系?
  • Agent 如何协调这些组件完成任务?
  • 在实际场景中,什么时候使用 Skills、什么时候使用 MCP、什么时候使用 Function Calling?

核心概念详解

1. Agent(智能体)

定义:Agent 是一个完整的 AI 助手实例,包含 LLM + 记忆 + 工具 + 配置。

比喻:Agent 就像一个智能助手公司,包含 CEO(LLM)、部门、工具。

例子

1
2
3
4
5
6
7
Agent: OpenClaw-Vango
├── LLM: GLM-5(决策中心)
├── Memory: 对话历史、用户偏好
├── Tools: 35+ 工具(read、write、exec、browser...)
├── Skills: 英语辅导员、天气查询、文件管理
├── Config: 工作目录、权限、密钥
└── Channels: 飞书、Telegram、CLI

关键

  • Agent 是最外层的容器
  • 包含所有其他组件
  • 是用户交互的入口

2. LLM Model(大语言模型)

定义:AI 的"大脑",负责理解、推理、决策和生成。

比喻:LLM 是 Agent 的 CEO(首席执行官)

例子

  • GPT-4、Claude、GLM-5、Gemini
  • 负责:理解用户意图、决策调用哪个工具、生成回复

关键

  • LLM 是核心决策者
  • 不直接执行操作,而是决策要做什么
  • 通过 Function Calling 调用工具

3. Function Calling(函数调用)

定义:一种协议/机制,让 LLM 能调用外部工具。

比喻:Function Calling 是内部通讯系统,让 CEO 能调用各部门。

工作原理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1. 发送工具定义给 LLM
   {
     "tools": [
       {
         "name": "write",
         "description": "写入文件到指定路径",
         "parameters": {
           "path": {"type": "string"},
           "content": {"type": "string"}
         }
       }
     ]
   }

2. LLM 决定调用工具
   {
     "tool_calls": [{
       "function": {
         "name": "write",
         "arguments": "{\"path\":\"note.md\",\"content\":\"...\"}"
       }
     }]
   }

3. 执行工具并返回结果
   {
     "role": "tool",
     "content": "{\"status\":\"success\"}"
   }

关键

  • Function Calling 是协议,不是具体的工具
  • 定义了 LLM 和工具之间的通信标准
  • 包含:工具定义、参数 schema、返回格式

4. Skills(技能)

定义:Agent 的专业能力模块,通过代码或配置实现。

比喻:Skills 是公司的专业部门(英语部、财务部、技术部)。

例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 英语辅导员 Skill
name: english-learning
description: 英语学习辅导,记录表达问题,生成学习笔记
tools:
  - read
  - write
  - web_search
prompts:
  - "你是英语辅导员,帮助学生提高英语水平..."
workflow:
  1. 识别英语问题
  2. 解释语法规则
  3. 记录到学习笔记
  4. 同步到博客

关键

  • Skills 是内置的专业能力
  • 可以包含多个工具
  • 可以有特定的提示词工作流

5. MCP(Model Context Protocol)

定义:标准化的工具连接协议,让 AI 能使用外部工具和服务。

比喻:MCP 是外部合作标准接口,连接其他公司的服务。

例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "mcpServers": {
    "filesystem": {
      "command": "mcp-filesystem",
      "args": ["/home/ubuntu/workspace"]
    },
    "github": {
      "command": "mcp-github",
      "args": ["--token", "ghp_xxx"]
    },
    "database": {
      "command": "mcp-postgres",
      "args": ["postgresql://localhost/db"]
    }
  }
}

关键

  • MCP 是协议标准
  • 用于连接外部服务(数据库、API、SaaS)
  • 提供统一的接口规范

架构图:组件关系

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
┌─────────────────────────────────────────────────────┐
                    AGENT                             
            OpenClaw-Vango                        
                                                      
  ┌──────────────────────────────────────────────┐  
                LLM Model                          
            GLM-5 - CEO                        
                                                    
     理解用户意图                                  
     推理决策                                      
     生成回复                                      
  └──────────────────────────────────────────────┘  
                                                     
  ┌──────────────────────────────────────────────┐  
          Function Calling(协议)                 
                                                    
     工具定义(schema                            
     参数传递(arguments                         
     结果返回(tool result                      
  └──────────────────────────────────────────────┘  
                                                     
  ┌──────────────────┬──────────────────────────┐  
     Skills               MCP Servers            
    (内置能力)        (外部服务协议)           
                                                 
     英语辅导         filesystem               
     天气查询         github                   
     文件管理         database                 
     代码助手         web APIs                 
  └──────────────────┴──────────────────────────┘  
                                                     
  ┌──────────────────────────────────────────────┐  
            Tools(实际执行)                       
                                                    
     read/write/edit   fs 模块                  
     exec              child_process            
     web_search        Brave API                
     browser           Puppeteer                
  └──────────────────────────────────────────────┘  
                                                      
└─────────────────────────────────────────────────────┘
                       
         ┌─────────────────────────┐
            Ubuntu 服务器          
             文件系统             
             Shell               
             Git                 
             网络访问             
         └─────────────────────────┘

实际使用场景详解

场景 1:英语时态学习(多轮对话)

用户输入

1
"详细解释一下 of、for、with、about 的区别"

完整请求流程

步骤 1:OpenClaw 构建请求

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "model": "glm-5",
  "messages": [
    {
      "role": "system",
      "content": "你是梵高,一个英语辅导员。你的任务是帮助用户学习英语..."
    },
    {
      "role": "user",
      "content": "详细解释一下 of、for、with、about 的区别"
    }
  ],
  "tools": [
    // 35+ 工具定义(但这次可能用不上)
    { "name": "read", ... },
    { "name": "write", ... },
    { "name": "exec", ... },
    // ...
  ]
}

步骤 2:GLM-5 推理

1
2
3
4
5
6
7
8
分析用户意图:
→ 这是一个英语学习问题
→ 需要解释介词的用法
→ 可能需要记录到学习笔记

决策:
→ 不需要调用工具(纯文本回复即可)
→ 激活英语辅导员 Skill 的上下文

步骤 3:GLM-5 返回

1
2
3
4
5
6
7
8
9
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "**Of vs For vs With vs About**\n\n核心区别:\n- **Of**:属于、...的(从属关系)\n- **For**:为了、给(目的、对象)\n- **With**:和、用(伴随、工具)\n- **About**:关于、大约(主题、围绕)\n\n详细用法...",
      "tool_calls": null
    }
  }]
}

关键点

  • 纯文本回复,没有调用工具
  • ✅ Skills 的作用:提供上下文(英语辅导员 persona)
  • ✅ Function Calling 机制存在,但未被使用
  • ✅ MCP 服务器未涉及

组件使用情况

  • Agent:协调所有组件
  • LLM:生成回复
  • Skills:英语辅导员提供上下文
  • Function Calling:未使用(不需要工具)
  • MCP:未使用(不需要外部服务)

场景 2:生成学习笔记(内容生成 + 文件写入)

用户输入

1
"生成一篇英语学习笔记,包含我们刚才讨论的内容,并提交到 GitHub"

完整请求流程

步骤 1:OpenClaw 构建请求(包含所有对话历史)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
  "model": "glm-5",
  "messages": [
    { "role": "system", "content": "你是梵高..." },
    
    // 之前的多轮对话
    { "role": "user", "content": "of vs for vs with vs about" },
    { "role": "assistant", "content": "**Of vs For vs With vs About**..." },
    
    { "role": "user", "content": "which vs that 的区别" },
    { "role": "assistant", "content": "**Which vs That**..." },
    
    { "role": "user", "content": "-ing 形式的用法" },
    { "role": "assistant", "content": "**-ing Form Usage**..." },
    
    // 当前指令
    { "role": "user", "content": "生成一篇英语学习笔记,包含我们刚才讨论的内容,并提交到 GitHub" }
  ],
  
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "write",
        "description": "写入文件到指定路径。如果文件不存在则创建,如果存在则覆盖",
        "parameters": {
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "文件路径(相对或绝对)"
            },
            "content": {
              "type": "string",
              "description": "要写入的内容"
            }
          },
          "required": ["path", "content"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "exec",
        "description": "执行 shell 命令",
        "parameters": {
          "type": "object",
          "properties": {
            "command": {
              "type": "string",
              "description": "要执行的命令"
            }
          },
          "required": ["command"]
        }
      }
    }
    // ... 其他 33+ 工具
  ]
}

关键

  • 所有对话历史都包含在请求中
  • ✅ 这就是为什么 LLM 能"记住"之前讨论的内容
  • ✅ 所有工具定义都发送给 LLM(35+ 个)

步骤 2:GLM-5 推理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
分析用户意图:
1. 生成英语学习笔记
2. 内容:包含刚才讨论的内容(of/for, which/that, -ing)
3. 提交到 GitHub

推理过程:
1. 需要生成笔记内容(基于对话历史)
2. 需要写入文件(调用 write 工具)
3. 需要提交 GitHub(调用 exec 工具)

决策顺序:
→ 先调用 write 工具(写入文件)
→ 等待写入成功
→ 再调用 exec 工具(git commit)

步骤 3:GLM-5 内容生成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
基于对话历史,GLM-5 自动生成笔记内容:

# English Learning Notes - 2026-03-06

## 1. Of vs For vs With vs About

### Of(属于、...的)
- 核心含义:从属关系、组成部分
- 例子:
  - the key **of** the door(门的钥匙)
  - a cup **of** coffee(一杯咖啡)

### For(为了、给)
- 核心含义:目的、对象、用途
- 例子:
  - This tool is **for** encryption.(这个工具用来加密)
  - I've been working here **for** two years.(持续两年)

### With(和、用)
- 核心含义:伴随、工具、方式
- 例子:
  - I work **with** Alice.(我和 Alice 一起工作)
  - Encrypt the data **with** AES.(用 AES 加密)

### About(关于、大约)
- 核心含义:主题、围绕
- 例子:
  - a book **about** cryptography(一本关于密码学的书)
  - **about** 10 minutes(大约 10 分钟)

---

## 2. Which vs That

### That(限定性从句)
- 特点:必要信息,无逗号
- 例子:
  - The server **that** crashed yesterday is back online.
  (昨天崩溃的那个服务器)

### Which(非限定性从句)
- 特点:额外信息,有逗号
- 例子:
  - The server, **which** runs on Linux, needs updates.
  (运行在 Linux 上的服务器)

**关键**
- **that** = essential info(必要信息)
- **which** = extra info(额外信息)

---

## 3. -ing Form Usage(9 种情况)

### 1. Continuous Tenses(进行时)
- I **am working** on the migration.

### 2. After Prepositions(介词后)
- interested **in learning** Kubernetes
- good **at debugging**

### 3. After Certain Verbs(特定动词后)
- **enjoy working** with new technologies
- **avoid making** mistakes

### 4. As Noun/Gerund(作为名词)
- **Working** remotely has many benefits.

### 5. After "go"(在 go 后)
- go **shopping** / go **swimming**

### 6. After Expressions(特定表达后)
- look forward **to meeting** you
- busy **debugging** the issue

### 7. As Adjective(作为形容词)
- an **interesting** project
- a **challenging** task

### 8. Reduced Clauses(简化从句)
- The developer **working** on the API is Alice.

### 9. After "There is/are"
- There's someone **waiting** for you.

---

## Summary

- **Of vs For vs With vs About**: of = 从属,for = 目的,with = 伴随,about = 关于
- **Which vs That**: that = 必要,which = 额外
- **-ing Form**: 9 种情况,关键是介词后、特定动词后、作为名词

*Generated by OpenClaw-Vango 🎨*

关键

  • ✅ GLM-5 基于对话历史自动总结内容
  • ✅ 内容是完整生成的(约 3.5 KB)
  • ✅ 格式化为 Markdown

步骤 4:GLM-5 路径决策

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
推理文件路径:

1. 系统提示词提到:
   - 工作目录: /home/ubuntu/.openclaw/workspace
   - 博客路径: /home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/

2. 内容类型分析:
   - 这是英语学习笔记
   - 用户要提交到 GitHub
   - 博客目录有 git 仓库

3. 路径决策:
   → /home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/notes/english-grammar-summary.md

4. 文件名推理:
   - 内容类型: 英语语法总结
   - 日期: 2026-03-06
   - 描述: english-grammar-summary
   - 扩展名: .md

步骤 5:GLM-5 返回工具调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_write_abc123",
          "type": "function",
          "function": {
            "name": "write",
            "arguments": "{\"path\":\"/home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/notes/english-grammar-summary.md\",\"content\":\"# English Learning Notes - 2026-03-06\\n\\n## 1. Of vs For vs With vs About\\n\\n### Of(属于、...的)\\n...[完整内容]...\\n\\n*Generated by OpenClaw-Vango 🎨*\"}"
          }
        }
      ]
    }
  }]
}

关键

  • arguments 包含完整的笔记内容(约 3.5 KB)
  • path 是 GLM-5 推理得出的
  • ✅ 所有换行符转义为 \n

步骤 6:OpenClaw 执行 write 工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 1. 解析工具调用
const toolCall = response.choices[0].message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);

// args = {
//   path: "/home/ubuntu/CipherHUB-Blogs/.../english-grammar-summary.md",
//   content: "# English Learning Notes...\n..."
// }

// 2. 查找 write 工具的 handler
const writeTool = toolRegistry.get("write");

// 3. 执行 handler
const result = await writeTool.handler(args);

// 4. write 工具的实际实现
import fs from 'fs';
import path from 'path';

async function handler(params) {
  // 确保目录存在
  const dir = path.dirname(params.path);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  
  // 写入文件
  fs.writeFileSync(params.path, params.content, 'utf-8');
  
  return {
    status: "success",
    path: params.path,
    size: params.content.length,  // 3542 字节
    lines: params.content.split('\n').length  // 128 行
  };
}

// 在 Ubuntu 服务器上实际执行:
// $ mkdir -p /home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/notes
// $ cat > /home/ubuntu/CipherHUB-Blogs/.../english-grammar-summary.md

步骤 7:返回结果给 GLM-5

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "messages": [
    ... 之前的对话,
    {
      "role": "tool",
      "tool_call_id": "call_write_abc123",
      "content": "{\"status\":\"success\",\"path\":\"/home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/notes/english-grammar-summary.md\",\"size\":3542,\"lines\":128}"
    }
  ]
}

关键点

  • Function Calling 被使用(write 工具调用)
  • Skills 提供上下文(英语辅导员,知道要记录笔记)
  • MCP 未使用(write 是内置工具,不需要外部协议)
  • ✅ 对话历史在每次请求中都发送(让 LLM “记住”)

组件使用情况

  • Agent:协调所有组件
  • LLM:生成内容 + 决策调用工具
  • Skills:英语辅导员提供上下文和工作流
  • Function Calling:调用 write 工具
  • MCP:未使用(write 是内置工具)

场景 3:提交 GitHub(git 操作)

步骤 8:GLM-5 第二次推理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
看到 write 工具执行成功:
{
  status: "success",
  path: "/home/ubuntu/CipherHUB-Blogs/.../english-grammar-summary.md"
}

推理下一步:
→ 用户要求提交到 GitHub
→ 记住文件路径:/home/ubuntu/.../english-grammar-summary.md
→ 需要执行 git 命令
→ 生成 commit message

决策:
→ 调用 exec 工具
→ 执行 git add + git commit + git push

步骤 9:GLM-5 生成 commit message

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
基于笔记内容生成 commit message:

标题:
Add English grammar summary - 2026-03-06

正文:
Summary of today's English learning:
- Of vs For vs With vs About
- Which vs That distinction
- -ing form in 9 situations

Generated by OpenClaw-Vango 🎨

步骤 10:GLM-5 返回 exec 工具调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_exec_def456",
          "type": "function",
          "function": {
            "name": "exec",
            "arguments": "{\"command\":\"cd /home/ubuntu/CipherHUB-Blogs && git add CipherHUBBlogs/content/languages/notes/english-grammar-summary.md && git commit -m \\\"Add English grammar summary - 2026-03-06\\n\\nSummary of today's English learning:\\n- Of vs For vs With vs About\\n- Which vs That distinction\\n- -ing form in 9 situations\\n\\nGenerated by OpenClaw-Vango 🎨\\\" && git push\"}"
          }
        }
      ]
    }
  }]
}

关键

  • ✅ GLM-5 记住了文件路径
  • ✅ GLM-5 生成了合适的 commit message
  • ✅ commit message 包含笔记的摘要

步骤 11:OpenClaw 执行 exec 工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 1. 解析工具调用
const execCall = response.choices[0].message.tool_calls[0];
const args = JSON.parse(execCall.function.arguments);

// args = {
//   command: "cd /home/ubuntu/CipherHUB-Blogs && git add ... && git commit ... && git push"
// }

// 2. 执行 exec 工具
const execTool = toolRegistry.get("exec");
const result = await execTool.handler(args);

// 3. exec 工具的实际实现
import { exec as execSync } from 'child_process';

async function handler(params) {
  return new Promise((resolve) => {
    execSync(
      params.command,
      {
        cwd: process.cwd(),
        maxBuffer: 1024 * 1024 * 10
      },
      (error, stdout, stderr) => {
        if (error) {
          resolve({ 
            error: error.message,
            stdout: stdout.toString(),
            stderr: stderr.toString()
          });
        } else {
          resolve({
            stdout: stdout.toString(),
            stderr: stderr.toString()
          });
        }
      }
    );
  });
}

// 在 Ubuntu 服务器上实际执行:
// $ cd /home/ubuntu/CipherHUB-Blogs
// $ git add CipherHUBBlogs/content/languages/notes/english-grammar-summary.md
// $ git commit -m "Add English grammar summary - 2026-03-06
// 
// Summary of today's English learning:
// - Of vs For vs With vs About
// - Which vs That distinction
// - -ing form in 9 situations
// 
// Generated by OpenClaw-Vango 🎨"
// $ git push

步骤 12:返回 git 结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "messages": [
    ... 之前的对话,
    {
      "role": "tool",
      "tool_call_id": "call_exec_def456",
      "content": "{\"stdout\":\"[main abc123def] Add English grammar summary\\n 1 file changed, 128 insertions(+)\\n create mode 100644 CipherHUBBlogs/content/languages/notes/english-grammar-summary.md\\nTo github.com:bowenerchen/CipherHUB-Blogs.git\\n   123abc..abc123  CipherHUBBlogs -> CipherHUBBlogs\\n\",\"stderr\":\"\"}"
    }
  ]
}

步骤 13:GLM-5 生成最终回复

1
2
3
4
5
6
7
8
9
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "✅ **已生成英语学习笔记并提交到 GitHub!**\n\n## 📝 笔记内容\n\n总结了我们今天讨论的内容:\n- **Of vs For vs With vs About** 的用法区别\n- **Which vs That** 在从句中的使用\n- **-ing 形式** 的 9 种情况\n\n## 📂 文件信息\n\n- **路径**: `/home/ubuntu/CipherHUB-Blogs/CipherHUBBlogs/content/languages/notes/english-grammar-summary.md`\n- **大小**: 3,542 字节\n- **行数**: 128 行\n\n## 🔗 GitHub\n\n- **Commit**: abc123def\n- **仓库**: bowenerchen/CipherHUB-Blogs\n- **分支**: CipherHUBBlogs\n\n**笔记已成功推送到 GitHub!** 🎨",
      "tool_calls": null
    }
  }]
}

关键点

  • Function Calling 被使用(exec 工具调用)
  • Skills 未直接参与(git 操作不需要特定 skill)
  • MCP 未使用(exec 是内置工具)
  • ✅ LLM 协调多个工具按顺序执行

组件使用情况

  • Agent:协调所有组件
  • LLM:决策 + 生成 commit message
  • Skills:未直接参与(git 操作不需要特定 skill)
  • Function Calling:调用 exec 工具
  • MCP:未使用(exec 是内置工具)

运行机制详解

完整请求流程图

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
┌─────────────────────────────────────────────────────┐
 1. 用户输入(Feishu                                
    "生成英语学习笔记并提交 GitHub"                   
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 2. OpenClaw Gateway 接收                             
     识别 channelFeishu                         
     识别 session(你的对话)                       
     准备构建请求                                    
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 3. 构建请求(包含所有组件)                          
    {                                                 
      model: "glm-5",                                
      messages: [                                     
        system: "你是梵高...",                        
        ... 所有对话历史 ...,                         
        user: "生成笔记并提交 GitHub"                 
      ],                                              
      tools: [ ... 所有 35+ 工具定义 ... ]            
    }                                                 
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 4. 发送 HTTPS 请求到 GLM-5                           
    POST https://open.bigmodel.cn/api/paas/v4/...   
    Headers:                                          
      Authorization: Bearer YOUR_API_KEY              
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 5. GLM-5 处理(第一次推理)                          
     理解用户意图                                    
     分析对话历史                                    
     决策:调用 write 工具                           
     生成笔记内容(3.5 KB                          
     推理文件路径                                    
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 6. GLM-5 返回 Function Call                         
    tool_calls: [{                                    
      function: {                                     
        name: "write",                                
        arguments: "{path:..., content:...}"          
      }                                               
    }]                                                
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 7. OpenClaw 解析和执行 write 工具                    
     解析 arguments                                  
     查找 handler                                    
     fs.writeFileSync(path, content)                
     返回结果                                        
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 8. 返回结果给 GLM-5                                  
    role: "tool"                                      
    content: "{\"status\":\"success\"}"               
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 9. GLM-5 处理(第二次推理)                          
     看到写入成功                                    
     记住文件路径                                    
     决策:调用 exec 工具                            
     生成 commit message                             
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 10. GLM-5 返回 Function Call                        
     tool_calls: [{                                   
       function: {                                    
         name: "exec",                                
         arguments: "{command:...}"                   
       }                                              
     }]                                               
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 11. OpenClaw 执行 exec 工具                          
      解析 arguments                                 
      child_process.exec(command)                   
      git add + git commit + git push               
      返回结果                                       
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 12. 返回结果给 GLM-5                                 
     role: "tool"                                     
     content: "{\"stdout\":\"[main abc123]...\"}"     
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 13. GLM-5 生成最终回复                               
     content: "✅ 已生成笔记并提交到 GitHub..."       
     tool_calls: null                                 
└─────────────────────────────────────────────────────┘
                    
┌─────────────────────────────────────────────────────┐
 14. OpenClaw 发送回复到 Feishu                       
      通过飞书 API 发送消息                          
      用户看到最终回复                               
└─────────────────────────────────────────────────────┘

工具调用机制详解

1. 工具定义(Schema)

每次请求都会发送所有工具的定义给 LLM:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "write",
        "description": "写入文件到指定路径。如果文件不存在则创建,如果存在则覆盖",
        "parameters": {
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "文件路径(相对或绝对)"
            },
            "content": {
              "type": "string",
              "description": "要写入的内容"
            }
          },
          "required": ["path", "content"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "exec",
        "description": "执行 shell 命令",
        "parameters": {
          "type": "object",
          "properties": {
            "command": {
              "type": "string",
              "description": "要执行的命令"
            }
          },
          "required": ["command"]
        }
      }
    }
    // ... 其他 33+ 工具
  ]
}

关键

  • ✅ 每次请求都包含所有工具(35+ 个)
  • ✅ 工具定义包含:name、description、parameters schema
  • 不包含实现代码(LLM 只知道"能做什么",不知道"怎么做")

2. LLM 决策

LLM 通过 description 理解工具用途:

1
2
3
4
5
6
7
8
9
用户说:"生成笔记"

LLM 看到工具列表:
- read: "读取文件内容" ❌ 不匹配
- write: "写入文件到指定路径" ✅ 匹配!
- exec: "执行 shell 命令" ⚠️ 也可以用,但不是最直接

决策:
→ 调用 write 工具

3. 参数生成

LLM 根据参数 schema 生成实际参数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
write 工具的参数要求:
{
  "path": string,  // 文件路径
  "content": string  // 文件内容
}

LLM 生成:
{
  "path": "/home/ubuntu/.../english-grammar-summary.md",
  "content": "# English Learning Notes...\n..."
}

4. 执行和返回

OpenClaw 执行工具并返回结果:

1
2
3
4
5
6
7
8
9
// 执行
const result = await tool.handler(params);

// 返回给 LLM
{
  role: "tool",
  tool_call_id: "call_write_abc123",
  content: JSON.stringify(result)
}

上下文传递机制

关键每次请求都包含所有对话历史

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "messages": [
    // 第 1 轮
    { "role": "user", "content": "of vs for" },
    { "role": "assistant", "content": "..." },
    
    // 第 2 轮
    { "role": "user", "content": "which vs that" },
    { "role": "assistant", "content": "..." },
    
    // 第 3 轮
    { "role": "user", "content": "-ing form" },
    { "role": "assistant", "content": "..." },
    
    // 工具调用(也算一轮)
    { "role": "assistant", "tool_calls": [...] },
    { "role": "tool", "content": "..." },
    
    // 当前(第 N 轮)
    { "role": "user", "content": "生成笔记" }
  ]
}

关键

  • ✅ 对话历史是累加的
  • 工具调用也算一轮对话
  • ✅ 每次请求发送完整历史
  • ✅ 对话越长 → token 消耗越多

Skills vs MCP vs Function Calling 的使用时机

对比表

组件层级作用使用时机例子
SkillsAgent 级别提供专业能力需要特定领域知识或工作流英语辅导员、天气查询、文件管理
MCP协议级别标准化工具接口需要连接外部服务数据库、GitHub API、外部 SaaS
Function Calling机制级别调用工具的协议需要执行任何工具read、write、exec、browser

使用时机详解

1. 什么时候使用 Skills?

场景特征

  • 需要特定领域知识
  • 需要复杂工作流
  • 需要上下文增强

例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 英语辅导员 Skill
触发条件:
  • 用户问英语问题
  • 需要记录学习笔记
  • 需要纠错和建议

工作流:
  1. 识别英语问题
  2. 解释语法规则
  3. 记录到学习笔记(自动调用 write 工具)
  4. 同步到博客(自动调用 git 工具)

提供的价值:
  • 专业的英语知识
  • 自动记录学习进度
  • 个性化建议

使用场景

  • ✅ 英语学习(英语辅导员 Skill)
  • ✅ 天气查询(天气 Skill - 知道调用哪个 API)
  • ✅ 代码助手(代码 Skill - 知道如何格式化、测试)

不使用 Skills

  • ❌ 简单的文件操作(不需要特定领域知识)
  • ❌ 通用的对话(纯文本回复即可)

2. 什么时候使用 MCP?

场景特征

  • 需要连接外部服务
  • 需要标准化接口
  • 需要动态扩展工具

例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "mcpServers": {
    "github": {
      "command": "mcp-github",
      "args": ["--token", "ghp_xxx"]
    },
    "database": {
      "command": "mcp-postgres",
      "args": ["postgresql://localhost/db"]
    }
  }
}

MCP 提供的工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
  "tools": [
    {
      "name": "github_create_issue",
      "description": "创建 GitHub Issue",
      "parameters": { ... }
    },
    {
      "name": "github_list_prs",
      "description": "列出 Pull Requests",
      "parameters": { ... }
    },
    {
      "name": "db_query",
      "description": "执行 SQL 查询",
      "parameters": { ... }
    }
  ]
}

使用场景

  • ✅ 连接数据库(查询数据)
  • ✅ 连接 GitHub(创建 Issue、PR)
  • ✅ 连接 Slack(发送消息)
  • ✅ 连接外部 API(调用 SaaS 服务)

不使用 MCP

  • ❌ 内置工具(read、write、exec 不需要 MCP)
  • ❌ 本地操作(文件系统、Shell 命令)

3. 什么时候使用 Function Calling?

场景特征

  • 需要执行任何工具
  • 需要 LLM 决策调用哪个工具

Function Calling 的作用

  • 协议:定义 LLM 和工具之间的通信标准
  • 机制:让 LLM 能调用所有工具(Skills 的工具、MCP 的工具、内置工具)

例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
所有工具都通过 Function Calling 调用:

1. 内置工具(write、exec):
   → 通过 Function Calling 协议调用

2. Skills 提供的工具:
   → 通过 Function Calling 协议调用

3. MCP 提供的工具:
   → 通过 Function Calling 协议调用

关键

  • Function Calling 是底层机制
  • 所有工具都通过 Function Calling 调用
  • Function Calling 不区分工具的来源(内置、Skills、MCP)

实际场景的组件使用

场景 1:英语时态学习(纯对话)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
用户:"of vs for 的区别"

组件使用:
✅ Agent(协调)
✅ LLM(生成回复)
✅ Skills(英语辅导员提供上下文)
❌ Function Calling(不需要工具)
❌ MCP(不需要外部服务)

原因:
→ 纯文本回复
→ 不需要执行操作

场景 2:生成笔记(内容生成 + 文件写入)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
用户:"生成英语学习笔记"

组件使用:
✅ Agent(协调)
✅ LLM(生成内容 + 决策调用工具)
✅ Skills(英语辅导员 - 知道要记录笔记)
✅ Function Calling(调用 write 工具)
❌ MCP(write 是内置工具,不需要 MCP)

原因:
→ 需要写入文件(调用工具)
→ Skills 提供上下文(知道要记录笔记)
→ write 是内置工具,不需要 MCP

场景 3:提交 GitHub(git 操作)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
用户:"提交到 GitHub"

组件使用:
✅ Agent(协调)
✅ LLM(决策 + 生成 commit message)
❌ Skills(git 操作不需要特定 skill)
✅ Function Calling(调用 exec 工具)
❌ MCP(exec 是内置工具,不需要 MCP)

原因:
→ 需要执行命令(调用工具)
→ git 操作不需要特定领域知识
→ exec 是内置工具,不需要 MCP

场景 4:查询数据库(假设)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
用户:"查询所有英语学习笔记"

组件使用:
✅ Agent(协调)
✅ LLM(决策)
❌ Skills(不需要特定 skill)
✅ Function Calling(调用 MCP 提供的 db_query 工具)
✅ MCP(连接数据库)

原因:
→ 需要连接外部数据库
→ 需要标准化接口(MCP)
→ 通过 Function Calling 调用 MCP 提供的工具

总结

核心关系

1
2
3
4
5
6
7
8
Agent(容器)
  └── LLM Model(大脑)
        └── Function Calling(调用机制)
              ├── Skills(内置专业能力)
              │     └── 提供工具(通过 Function Calling)
              └── MCP(外部工具协议)
                    └── 提供工具(通过 Function Calling)

关键要点

  1. Agent 是最外层容器,包含所有组件
  2. LLM 是核心决策者,负责理解和决策
  3. Function Calling 是底层机制,所有工具都通过它调用
  4. Skills 提供专业能力和上下文增强
  5. MCP 提供标准化接口连接外部服务

使用建议

  • 需要专业领域知识 → 使用 Skills
  • 需要连接外部服务 → 使用 MCP
  • 需要执行任何工具 → 通过 Function Calling
  • 简单对话 → 纯 LLM 生成

这就是从多轮对话到自动化工作流的完整技术实现! 🎨

通过这个实际场景,我们看到了 OpenClaw Agent 如何协调 LLM、Skills、MCP 和 Function Calling,将用户的自然语言指令转化为实际的自动化操作。