前两天阿里发了个大招——「悟空」,号称全球首个企业级 Agent 平台。刷了一圈掘金和知乎,全是"震撼""王炸""颠覆",搞得我以为外星科技降临了。

抱着"别人吹你信,自己试了才知道"的心态,我花了一下午研究了悟空的架构思路,然后动手用 Python 撸了个 mini Agent 框架。结论是:悟空的 CLI 化思路确实聪明,但核心技术你自己也能实现,而且没那么玄乎。

先说结论

维度阿里悟空自建 Agent
上手难度开箱即用,钉钉内直接用需要写代码,100 行起步
灵活性绑定钉钉生态想接啥接啥
成本企业版收费(具体没公布)API 调用费,按量付
数据安全阿里云托管数据在自己手里
定制能力用它的 Skill 模板完全自定义
适合谁不想写代码的团队想掌控一切的开发者

如果你是开发者,自己搞一个可能更香。 下面我把完整代码和踩坑记录都放出来。

悟空到底做了什么?

抛开营销话术,悟空的核心思路其实就三件事:

1. CLI 化改造——让 AI 能"操作"而不是"模拟"

钉钉把自己的 GUI 功能拆解成了一套 CLI 指令。AI Agent 不用像 Playwright 那样模拟鼠标点击,而是直接调用命令行接口。

这个思路其实跟 MCP(Model Context Protocol)异曲同工——把工具变成函数,让 AI 直接调用。

2. Skill 市场——预制工具包

悟空的 OPT(One Person Team)方案,本质上就是把多个 AI 工具编排成一个工作流。比如跨境电商场景:选品雷达 → AI 找同款 → 供应链匹配,这些都是预制好的 Skill。

3. 沙箱隔离——企业级安全

每个 Agent 跑在独立的容器沙箱里,权限最小化。这个在企业场景确实重要,但对个人开发者来说,本地跑就完事了。

说白了,悟空 = Function Calling + 工具编排 + 企业权限管理。前两个你自己就能搞,第三个大多数场景用不上。

动手:100 行 Python 搞个 AI Agent

废话不多说,直接上代码。我要实现一个能自动执行多步任务的 Agent:给它一个目标,它自己决定调哪些工具、按什么顺序执行。

第一步:定义工具

import json
import requests
import subprocess
from datetime import datetime

# 工具定义——Agent 能调用的函数
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "搜索互联网获取最新信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "run_command",
            "description": "在终端执行命令(如 curl, python, git 等)",
            "parameters": {
                "type": "object",
                "properties": {
                    "command": {"type": "string", "description": "要执行的命令"}
                },
                "required": ["command"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "read_file",
            "description": "读取本地文件内容",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "文件路径"}
                },
                "required": ["path"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "write_file",
            "description": "将内容写入文件",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "文件路径"},
                    "content": {"type": "string", "description": "文件内容"}
                },
                "required": ["path", "content"]
            }
        }
    }
]

第二步:实现工具函数

def execute_tool(name: str, args: dict) -> str:
    """执行工具并返回结果"""
    if name == "search_web":
        # 这里用 DuckDuckGo 做演示,生产环境建议用 Tavily 或 Serper
        try:
            resp = requests.get(
                "https://api.duckduckgo.com/",
                params={"q": args["query"], "format": "json"},
                timeout=10
            )
            data = resp.json()
            return data.get("AbstractText") or f"搜索完成,请根据关键词 '{args['query']}' 进行分析"
        except Exception as e:
            return f"搜索失败: {e}"

    elif name == "run_command":
        try:
            result = subprocess.run(
                args["command"], shell=True,
                capture_output=True, text=True, timeout=30
            )
            output = result.stdout or result.stderr
            return output[:2000]  # 截断避免 token 爆炸
        except subprocess.TimeoutExpired:
            return "命令执行超时(30s)"

    elif name == "read_file":
        try:
            with open(args["path"], "r") as f:
                return f.read()[:5000]
        except FileNotFoundError:
            return f"文件不存在: {args['path']}"

    elif name == "write_file":
        with open(args["path"], "w") as f:
            f.write(args["content"])
        return f"已写入 {args['path']}{len(args['content'])} 字符)"

    return f"未知工具: {name}"

第三步:Agent 主循环

这是核心——一个 ReAct 风格的循环,让 AI 自己决策下一步:

def run_agent(task: str, model: str = "claude-sonnet-4-20250514", max_steps: int = 10):
    """
    运行 AI Agent
    给它一个任务,它自己决定怎么完成
    """
    # 兼容 OpenAI 协议的 API(我用的 ofox.ai,改个 base_url 就行)
    api_base = "https://api.ofox.ai/v1"
    api_key = "你的 API Key"

    messages = [
        {
            "role": "system",
            "content": (
                f"你是一个能力很强的 AI Agent。当前时间:{datetime.now().isoformat()}n"
                "你可以使用工具来完成任务。每次只调用必要的工具,完成后直接回复最终结果。n"
                "如果任务已完成,直接回复结果,不要再调用工具。"
            )
        },
        {"role": "user", "content": task}
    ]

    print(f"n 任务: {task}n{'='*50}")

    for step in range(max_steps):
        print(f"n--- Step {step + 1} ---")

        resp = requests.post(
            f"{api_base}/chat/completions",
            headers={"Authorization": f"Bearer {api_key}"},
            json={
                "model": model,
                "messages": messages,
                "tools": TOOLS,
                "tool_choice": "auto"
            },
            timeout=60
        )
        result = resp.json()
        choice = result["choices"][0]
        msg = choice["message"]
        messages.append(msg)

        # 如果 AI 决定调用工具
        if msg.get("tool_calls"):
            for call in msg["tool_calls"]:
                fn_name = call["function"]["name"]
                fn_args = json.loads(call["function"]["arguments"])
                print(f" 调用工具: {fn_name}({fn_args})")

                tool_result = execute_tool(fn_name, fn_args)
                print(f" 结果: {tool_result[:200]}...")

                messages.append({
                    "role": "tool",
                    "tool_call_id": call["id"],
                    "content": tool_result
                })
        else:
            # AI 认为任务完成,直接返回
            print(f"n 完成!n{msg['content']}")
            return msg["content"]

    print("️ 达到最大步数限制")
    return messages[-1].get("content", "未完成")

跑起来试试

if __name__ == "__main__":
    # 例子1: 让 Agent 查看项目结构并生成说明
    run_agent("查看当前目录的项目结构,生成一份简要的 README")

    # 例子2: 让 Agent 搜索最新技术动态并写摘要
    run_agent("搜索 '阿里悟空 AI Agent' 的最新信息,写一段 200 字的技术分析")

输出长这样:

 任务: 查看当前目录的项目结构,生成一份简要的 README
==================================================

--- Step 1 ---
 调用工具: run_command({'command': 'find . -maxdepth 2 -type f | head -30'})
 结果: ./src/main.py ./src/utils.py ./tests/test_main.py ...

--- Step 2 ---
 调用工具: read_file({'path': './src/main.py'})
 结果: import asyncio ...

--- Step 3 ---
 调用工具: write_file({'path': './README.md', 'content': '# MyProjectn...'})
 结果: 已写入 ./README.md(456 字符)

--- Step 4 ---
 完成!
已为你生成 README.md,包含项目结构、安装方式和使用示例。

整个过程 AI 自己决定了要先看目录、再读代码、最后写文件。 这就是 Agent 的核心——不是写死流程,而是让 AI 自己规划执行路径。

进阶:加上多模型切换

悟空底层用的是通义千问,但实际做 Agent 开发你会发现,不同任务用不同模型效果差异巨大

  • 规划/推理任务:Claude Opus 4.6 或 GPT-5.4 效果最好,但贵
  • 简单工具调用:GPT-5.4 mini 或 Gemini 3 Flash 就够了,便宜 10 倍
  • 代码生成:GPT-5.2-Codex 专门优化过,写代码最稳
# 一套代码切换多个模型,只要 API 兼容 OpenAI 协议就行
MODELS = {
    "planning": "claude-opus-4-6-20250901",     # 复杂推理
    "execution": "gpt-5.4-mini",                # 日常执行
    "coding": "gpt-5.2-codex",                  # 代码生成
    "fast": "gemini-3-flash",                    # 快速响应
}

def run_agent(task, task_type="execution", max_steps=10):
    model = MODELS.get(task_type, MODELS["execution"])
    # ... 其余代码不变,model 参数传进去就行

这里有个小技巧:用兼容 OpenAI 协议的聚合接口,换模型只需要改一个 model 字段,base_urlapi_key 都不用动。我自己用的 ofox.ai,50 多个模型一个 Key 搞定,省得每家都去申请。

踩坑记录

坑 1:tool_calls 的 arguments 是字符串不是字典

#  错误写法
fn_args = call["function"]["arguments"]  # 这是个 JSON 字符串!

#  正确写法
fn_args = json.loads(call["function"]["arguments"])

第一次写的时候忘了 json.loads,直接把字符串当字典用,报错信息还特别迷惑——"string indices must be integers"。找了半小时才发现是这么个低级错误。

坑 2:工具结果太长会让模型"失忆"

如果工具返回了几万字的内容,塞进 messages 里会直接把上下文撑爆。模型不是崩就是忘了之前的任务。

# 解决方案:截断 + 摘要
def execute_tool(name, args):
    result = _do_execute(name, args)
    if len(result) > 3000:
        result = result[:2000] + f"nn... 省略 {len(result)-2000} 字符 ..."
    return result

坑 3:模型疯狂循环调用同一个工具

有时候模型会陷入死循环——比如一直重复搜索同一个关键词。加个简单的去重就行:

recent_calls = []
for step in range(max_steps):
    # ... 获取 AI 响应 ...
    if msg.get("tool_calls"):
        call_sig = f"{fn_name}:{json.dumps(fn_args, sort_keys=True)}"
        if call_sig in recent_calls[-3:]:  # 最近 3 次有重复就跳过
            messages.append({
                "role": "tool",
                "tool_call_id": call["id"],
                "content": "你已经调用过这个工具了,请尝试其他方式或直接回答。"
            })
            continue
        recent_calls.append(call_sig)

坑 4:并发请求被限流

跑多个 Agent 任务时,API 请求太密集会被限流。加个简单的指数退避:

import time

def api_call_with_retry(url, **kwargs):
    for attempt in range(3):
        resp = requests.post(url, **kwargs)
        if resp.status_code == 429:
            wait = 2 ** attempt
            print(f"限流了,等 {wait}s 重试...")
            time.sleep(wait)
            continue
        return resp.json()
    raise Exception("重试 3 次仍然失败")

小结

阿里悟空的定位很明确——给不想写代码的企业用户做一站式 Agent 平台。但如果你是开发者,自己用 100 行 Python + 一个兼容 OpenAI 协议的 API,就能搞出功能差不多的东西。

核心就三步:

  1. 定义工具(Function Calling 格式)
  2. 写个 ReAct 循环(AI 决策 → 执行工具 → 反馈结果 → 继续决策)
  3. 处理边界情况(截断、去重、重试)

代码已经全部贴在文章里了,复制就能跑。觉得有用的话点个赞,我后续会写多 Agent 协作和 MCP 集成的实战。


用到的模型:Claude Sonnet 4.6 / GPT-5.4 mini / GPT-5.2-Codex,通过 ofox.ai 聚合接口统一调用

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com