欢迎来到《Python + AI Agent 实战开发完全指南》专栏!

在前面的课程中,我们让 Agent 掌握了 RAG 检索与 ReAct 推理的能力。但这仅仅是“内功”的修炼。在真实的企业级场景中,很多任务是无法仅靠文本交互完成的——比如:自动抓取竞品网页数据、填写复杂的在线表单,甚至运行一段 Python 脚本进行数据清洗。

在这一讲中,我们将带领 Agent 走出纯文本的世界,为它装上真正的“手脚”。我们将深入探讨动态沙箱执行环境浏览器自动化原理,并实战构建一个具备反思机制的 AI 自动化编程助手,让它能够自主写代码、跑测试并根据报错自我修复!


一、 架构升级:为什么需要沙箱与浏览器自动化?

赋予大模型“执行能力”是一把双刃剑。如果直接在你的本地宿主机上运行 AI 生成的任意代码或操控浏览器,极易引发系统崩溃、敏感数据泄露等灾难性后果。因此,我们需要引入两层核心基础设施:

  1. 动态沙箱(Sandbox):它是 Agent 的“安全办公间”。通过内核级隔离技术(如 Docker 容器),Agent 可以在其中自由地执行 Shell 命令和 Python 脚本。即使它误删了文件,也不会影响到你的真实电脑。
  2. 浏览器自动化(Browser Automation):借助 Playwright 等框架,Agent 可以接管浏览器的导航、点击和输入操作。结合多模态大模型的视觉理解能力,它能像人类一样看懂网页布局并完成跨站点的复杂工作流。

将这两者结合,我们的 Agent 就真正具备了“具身智能”(Embodied Intelligence)的雏形。


二、 核心实战:构建带反思机制的代码执行工具

为了保持课程的轻量化与安全性,我们不依赖庞大的云端沙箱服务,而是利用 Python 原生的 subprocess 模块,手写一个受控的本地代码执行器。这个执行器自带“反思”属性:当代码抛出异常时,它会捕获错误信息,交由 LLM 进行自我诊断与修复。

首先,初始化我们的基础组件:

import os, subprocess, sys, tempfile, re
from pathlib import Path
os.environ["PYTHONUTF8"] = "1"

from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.checkpoint.memory import InMemorySaver
from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage

# --- 1. 初始化 LLM ---
API_KEY = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
MODEL = "qwen-turbo"

llm = ChatOpenAI(api_key=API_KEY, base_url=BASE_URL, model=MODEL)

接下来是重头戏:定义带有异常捕获与输出限制的安全执行工具

OUTPUT_DIR = Path("agent_output")
OUTPUT_DIR.mkdir(exist_ok=True)

def run_python(code: str) -> str:
    """在安全的临时环境中执行 Python 代码并返回结果。
    
    用于数据分析、数学计算或验证逻辑。如果代码报错,请仔细阅读错误信息进行修复。
    """
    # 将代码写入临时文件执行,避免直接 eval 带来的安全风险
    with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
        f.write(code)
        tmp_path = f.name
    
    try:
        result = subprocess.run(
            [sys.executable, tmp_path],
            capture_output=True, text=True, timeout=15 # 限制最多运行15秒
        )
        out = result.stdout.strip()
        err = result.stderr.strip()
        
        if err:
            return f"EXECUTION ERROR:\n{err}\n\nSTDOUT:\n{out}"
        return out or "Ran successfully with no output."
    except subprocess.TimeoutExpired:
        return "ERROR: Code execution timed out after 15 seconds."
    finally:
        Path(tmp_path).unlink(missing_ok=True)

tools = [run_python]
tool_map = {func.__name__: func for func in tools}

最后,注入带有反思指令的系统提示词,并组装状态机:

REACT_CODER_PROMPT = """你是一个资深的 Python 工程师。请遵循以下工作流:
1. Thought: 分析用户需求,规划代码逻辑。
2. Action: 调用 run_python 工具执行代码。如果用户要求保存数据,必须在代码中使用 open() 或 write() 方法将结果写入 'agent_output/result.py'。
3. Observation: 检查执行结果。如果出现 EXECUTION ERROR,你必须分析报错原因,重写代码并再次执行。
4. Final Answer: 确认代码无误后,向用户汇报最终结果及生成的文件路径。
"""

llm_with_tools = llm.bind_tools(tools)

def agent_node(state: MessagesState):
    system_msg = SystemMessage(content=REACT_CODER_PROMPT)
    response = llm_with_tools.invoke([system_msg] + state["messages"])
    return {"messages": response}

def tool_executor_node(state: MessagesState):
    last_message = state["messages"][-1]
    results = []
    for tool_call in last_message.tool_calls:
        func = tool_map[tool_call["name"]]
        result = func(**tool_call["args"])
        results.append(ToolMessage(content=str(result), tool_call_id=tool_call["id"]))
    return {"messages": results}

def should_continue(state: MessagesState):
    last_message = state["messages"][-1]
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tools"
    return END

builder = StateGraph(MessagesState)
builder.add_node("agent", agent_node)
builder.add_node("tools", tool_executor_node)
builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
builder.add_edge("tools", "agent") 

checkpointer = InMemorySaver()
app = builder.compile(checkpointer=checkpointer)

三、 见证奇迹:测试代码自修复能力

让我们故意提出一个包含语法错误的任务,看看 Agent 是如何自我纠错的:

if __name__ == "__main__":
    config = {"configurable": {"thread_id": "session_coder_001"}}
    
    print("--- 测试:AI 自动化编程与自修复 ---")
    user_question = "帮我写一段 Python 代码,用列表推导式生成 1 到 10 的平方数并打印出来。并将代码保存到 'agent_output/result.py'。" #注意:第一版代码请故意写错语法(比如漏掉冒号)。
    res = app.invoke({"messages": [HumanMessage(content=user_question)]}, config=config)
    print(f"\nAssistant: {res['messages'][-1].content}")

预期效果:
你会观察到 Agent 先生成了一段有语法错误的代码,执行工具后收到了 EXECUTION ERROR。此时,状态机流转回 Agent 节点,大模型读取到具体的报错行号,自动进入 Thought 阶段反思问题所在,随后生成修正后的代码再次执行。直到控制台成功输出 [1, 4, 9...100],它才会给出最终的完美答复。


四、 本节小结与进阶展望

恭喜你!至此,你的 Agent 已经跨越了纯聊天的边界,具备了真实的工程落地能力。

  1. 安全执行基座:理解了沙箱隔离的重要性,并通过 subprocess 实现了轻量级的本地代码安全执行。
  2. 反思与自愈:通过将工具的报错信息作为 Observation 反馈给大模型,配合 ReAct 循环,实现了极其强大的代码自修复(Self-healing)能力。
  3. 从对话到行动:证明了只要给予合适的工具集与 Prompt,大模型能够自主规划出“研究-编写-测试-修复”的完整工作流。

课后思考:
目前的代码执行是在本地子进程中进行的。如果要部署到企业生产环境,面对高并发请求,你会如何改造这个架构以支持真正的云端隔离?(提示:可以调研一下腾讯云 Agent Runtime 的云沙箱方案,或是基于 Docker / Kubernetes 搭建 VNC 可视化沙箱环境)。

在下一讲(第11讲)中,我们将进入多智能体协作的世界,探讨如何让多个拥有不同技能的 Agent 组成团队,共同完成超大规模的复杂项目!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐