"最小 AI Agent 示例"
包含:
- LLM
- Skill
- MCP
- Runtime
并且:
明确区分:
Skill 调用
MCP 调用
用 Python 写一个非常清晰的结构。
一、目标
用户输入:
text
分析 logs/test.log 并生成测试建议
Agent 会:
1. 通过 MCP 读取文件
text
filesystem.read()
2. 通过 Skill 分析日志
text
AnalyzeLogSkill()
3. 返回结果
二、整体架构
text
用户
↓
Agent Runtime
↓
LLM
↙ ↘
Skill MCP
(业务能力) (外部系统)
三、代码结构
text
project/
│
├── agent.py
├── runtime.py
├── skills/
│ └── analyze_log.py
├── mcp/
│ └── filesystem.py
四、MCP 示例(文件系统)
mcp/filesystem.py
python
class FileSystemMCP:
def read_file(self, path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
五、Skill 示例(日志分析)
skills/analyze_log.py
python
class AnalyzeLogSkill:
def run(self, log_text):
result = {
"timeout_count": 0,
"disconnect_count": 0,
"suggestion": []
}
lines = log_text.splitlines()
for line in lines:
if "timeout" in line.lower():
result["timeout_count"] += 1
if "disconnect" in line.lower():
result["disconnect_count"] += 1
if result["timeout_count"] > 0:
result["suggestion"].append(
"检查串口超时配置"
)
if result["disconnect_count"] > 0:
result["suggestion"].append(
"检查USB连接稳定性"
)
return result
六、Runtime(核心)
runtime.py
这里是:
真正调度:
Skill + MCP 的地方
python
from mcp.filesystem import FileSystemMCP
from skills.analyze_log import AnalyzeLogSkill
class AgentRuntime:
def __init__(self):
# 注册 MCP
self.filesystem_mcp = FileSystemMCP()
# 注册 Skill
self.analyze_skill = AnalyzeLogSkill()
def execute_tool_call(self, tool_name, args):
# MCP 调用
if tool_name == "filesystem.read":
return self.filesystem_mcp.read_file(
args["path"]
)
# Skill 调用
elif tool_name == "AnalyzeLogSkill":
return self.analyze_skill.run(
args["log_text"]
)
else:
raise Exception(f"Unknown tool: {tool_name}")
七、模拟 LLM
真实情况:
LLM 会输出 Tool Call。
这里我们手动模拟。
agent.py
python
from runtime import AgentRuntime
runtime = AgentRuntime()
# =========================
# Step1:
# LLM 决定调用 MCP
# =========================
tool_call_1 = {
"tool": "filesystem.read",
"args": {
"path": "logs/test.log"
}
}
log_text = runtime.execute_tool_call(
tool_call_1["tool"],
tool_call_1["args"]
)
print("读取日志:")
print(log_text)
# =========================
# Step2:
# LLM 决定调用 Skill
# =========================
tool_call_2 = {
"tool": "AnalyzeLogSkill",
"args": {
"log_text": log_text
}
}
analysis_result = runtime.execute_tool_call(
tool_call_2["tool"],
tool_call_2["args"]
)
print("\n分析结果:")
print(analysis_result)
八、logs/test.log 示例
text
[INFO] start test
[ERROR] timeout
[ERROR] serial disconnect
九、运行结果
text
读取日志:
[INFO] start test
[ERROR] timeout
[ERROR] serial disconnect
分析结果:
{
'timeout_count': 1,
'disconnect_count': 1,
'suggestion': [
'检查串口超时配置',
'检查USB连接稳定性'
]
}
十、这里谁是 MCP?谁是 Skill?
MCP
python
filesystem.read
作用:
"连接外部世界"
真正操作:
- 文件
- 数据库
- 串口
- 浏览器
Skill
python
AnalyzeLogSkill
作用:
"业务能力"
负责:
- 分析
- 推理
- 工作流
十一、真正的 LLM 会怎样?
真实情况不是手写:
python
tool_call_1 = {...}
而是:
LLM 自动生成:
json
{
"tool": "filesystem.read",
"args": {
"path": "logs/test.log"
}
}
Runtime 再执行。
十二、更像真正 Agent 的版本
真正 Agent 会:
text
LLM
↓
读取日志(MCP)
↓
分析错误(Skill)
↓
生成修复建议(Skill)
↓
调用串口(MCP)
↓
重新测试(Skill)
↓
上传MES(MCP)
十三、工业自动化里的典型映射
你现在做的自动测试平台:
其实可以直接拆成:
| 类型 | 示例 |
|---|---|
| MCP | SerialPortMCP |
| MCP | MESMCP |
| MCP | DatabaseMCP |
| MCP | PowerSupplyMCP |
| Skill | AnalyzeFailureSkill |
| Skill | GenerateTestFlowSkill |
| Skill | AutoRepairSkill |
| Skill | ReportSkill |
十四、最关键的本质
真正重要的是:
Skill 负责"智能"
MCP 负责"连接"
Runtime 负责"执行"
LLM 负责"决策"
十五、一句话理解
这个示例里:
text
filesystem.read
↓
这是 MCP
AnalyzeLogSkill
↓
这是 Skill
LLM 只是:
"决定什么时候调用谁"
上面的不清楚,写一个真实能用的
下面给你一个:
真正"可运行"的 AI Agent 示例
包含:
- 真正的 LLM(OpenAI API)
- MCP
- Skill
- Runtime
- 自动 Tool Calling
- API Key 配置
并且:
明确区分:
MCP 调用
Skill 调用
这个例子你可以直接跑。
一、项目结构
text
agent_demo/
│
├── main.py
├── runtime.py
├── config.py
│
├── skills/
│ └── analyze_log.py
│
├── mcp/
│ └── filesystem.py
│
├── logs/
│ └── test.log
│
└── requirements.txt
二、安装依赖
requirements.txt
txt
openai>=1.30.0
安装:
bash
pip install -r requirements.txt
三、配置 API Key
config.py
python
OPENAI_API_KEY = "你的API_KEY"
MODEL_NAME = "gpt-4.1-mini"
你也可以改成环境变量:
python
import os
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
四、MCP(文件系统)
mcp/filesystem.py
这里模拟:
MCP Server
python
class FileSystemMCP:
def read_file(self, path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
五、Skill(日志分析)
skills/analyze_log.py
python
class AnalyzeLogSkill:
def run(self, log_text):
timeout_count = 0
disconnect_count = 0
for line in log_text.splitlines():
line = line.lower()
if "timeout" in line:
timeout_count += 1
if "disconnect" in line:
disconnect_count += 1
result = {
"timeout_count": timeout_count,
"disconnect_count": disconnect_count,
"suggestions": []
}
if timeout_count > 0:
result["suggestions"].append(
"检查串口超时设置"
)
if disconnect_count > 0:
result["suggestions"].append(
"检查USB连接稳定性"
)
return result
六、Runtime(核心)
runtime.py
这里:
真正调度:
Skill + MCP
python
import json
from mcp.filesystem import FileSystemMCP
from skills.analyze_log import AnalyzeLogSkill
class AgentRuntime:
def __init__(self):
self.filesystem = FileSystemMCP()
self.analyze_skill = AnalyzeLogSkill()
# 给LLM看的工具定义
def get_tools(self):
return [
# MCP Tool
{
"type": "function",
"function": {
"name": "filesystem_read",
"description": "读取文件内容",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string"
}
},
"required": ["path"]
}
}
},
# Skill Tool
{
"type": "function",
"function": {
"name": "analyze_log_skill",
"description": "分析测试日志",
"parameters": {
"type": "object",
"properties": {
"log_text": {
"type": "string"
}
},
"required": ["log_text"]
}
}
}
]
# 真正执行 Tool
def execute_tool(self, tool_name, arguments):
if tool_name == "filesystem_read":
return self.filesystem.read_file(
arguments["path"]
)
elif tool_name == "analyze_log_skill":
result = self.analyze_skill.run(
arguments["log_text"]
)
return json.dumps(
result,
ensure_ascii=False,
indent=2
)
else:
raise Exception(f"Unknown tool: {tool_name}")
七、真正的 Agent(LLM参与)
main.py
这里:
真正让 LLM 自动决定:
调 MCP
还是调 Skill
python
import json
from openai import OpenAI
from runtime import AgentRuntime
from config import OPENAI_API_KEY, MODEL_NAME
client = OpenAI(
api_key=OPENAI_API_KEY
)
runtime = AgentRuntime()
messages = [
{
"role": "system",
"content": """
你是一个测试日志分析AI Agent。
你可以:
1. 读取日志文件
2. 分析日志错误
3. 给出建议
你应该自动决定调用哪个工具。
"""
},
{
"role": "user",
"content": "请分析 logs/test.log 的错误"
}
]
while True:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
tools=runtime.get_tools(),
tool_choice="auto"
)
msg = response.choices[0].message
# LLM 要调用工具
if msg.tool_calls:
messages.append(msg)
for tool_call in msg.tool_calls:
tool_name = tool_call.function.name
arguments = json.loads(
tool_call.function.arguments
)
print(f"\nLLM决定调用工具: {tool_name}")
print("参数:", arguments)
# Runtime 真正执行
tool_result = runtime.execute_tool(
tool_name,
arguments
)
print("\n工具返回结果:")
print(tool_result)
# 返回给LLM继续思考
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(tool_result)
})
else:
print("\n最终回答:\n")
print(msg.content)
break
八、日志文件
logs/test.log
text
[INFO] start test
[ERROR] timeout
[ERROR] serial disconnect
九、运行
bash
python main.py
十、真实运行过程(重点)
你会看到:
Step1:LLM调用 MCP
text
LLM决定调用工具: filesystem_read
这是:
MCP 调用
因为:
text
filesystem_read
操作了:
外部文件系统
Step2:LLM调用 Skill
text
LLM决定调用工具: analyze_log_skill
这是:
Skill 调用
因为:
它在做:
业务逻辑分析
Step3:最终回答
text
发现:
1. 存在 timeout 错误
2. 存在 serial disconnect 错误
建议:
- 检查串口超时配置
- 检查USB连接稳定性
十一、这里的核心本质
MCP
python
filesystem_read
作用:
text
连接现实世界
Skill
python
analyze_log_skill
作用:
text
执行业务能力
LLM
负责:
text
决定:
- 什么时候读文件
- 什么时候分析
- 下一步做什么
十二、真正的 Agent Loop 出现了
这里已经是真正的:
ReAct Agent Loop
text
LLM 思考
↓
Tool Call
↓
Runtime执行
↓
结果返回
↓
LLM继续思考
十三、你可以继续扩展
比如:
MCP
text
serial_open
mes_upload
database_query
browser_open
Skill
text
GenerateRepairPlan
AnalyzeCurrent
GenerateTestFlow
十四、工业自动化方向(你最适合)
你其实特别适合做:
AI 自动测试 Agent
因为你已经有:
- 测试平台
- MES
- 串口
- 自动化流程
- 工厂工具
你只差:
给系统接一个 LLM 大脑
十五、最关键的一句话
这个示例已经实现:
"LLM 自动决定调用 MCP 还是 Skill"
而不是:
python
if xxx:
call_tool()
这就是: