【OpenClaw:认知启蒙】3、OpenClaw Agent执行循环(Lobster)深度拆解:从意图识别到工具调用的全流程

【核心引擎】OpenClaw Agent执行循环(Lobster)深度拆解:从意图识别到工具调用的全流程

引言:Agent是如何"思考"并"行动"的?------Lobster循环的意义

在大模型Agent(智能体)技术快速落地的当下,OpenClaw作为一款轻量级、可扩展的Agent框架,其核心执行逻辑------Lobster循环(龙虾循环)是支撑Agent完成复杂任务的"大脑中枢"。不同于传统程序"指令-执行"的线性逻辑,Agent需要模拟人类的"思考-观察-行动-反思"闭环:面对用户模糊的自然语言指令(如"帮我分析本地销售数据并生成可视化图表"),它需要先拆解任务、再获取环境信息、执行具体操作,最后根据结果调整策略,而这一整套逻辑都封装在Lobster循环中。

理解Lobster循环,不仅能帮开发者掌握OpenClaw Agent的核心运行机制,更能触类旁通理解所有ReAct模式Agent的设计思想------从意图识别到工具调用的全流程管控,是Agent区别于普通LLM调用的关键。本文将从理论到源码、从设计到实战,全方位拆解Lobster循环,让你既能理解"为什么这么设计",也能动手"改造循环逻辑"。

Lobster循环四阶段:Agent的"思考-行动"闭环

Lobster循环本质是对ReAct(Reasoning + Acting)模式的工程化实现,核心拆分为Plan(规划)、Observe(观察)、Act(执行)、Reflect(反思) 四个阶段,形成一个可迭代的闭环。整个循环的核心逻辑是:接收用户指令→拆解为可执行步骤→获取环境信息→调用工具执行→验证结果→调整计划(若未完成)→重复直至任务完成。

1. Plan(规划):把模糊指令拆成可执行步骤

Plan阶段是Agent的"思考环节",核心目标是将用户的自然语言指令(如"爬取某电商网站手机销量数据并分析Top10机型")拆解为结构化、可执行的步骤列表。

  • 输入:用户原始指令 + 历史上下文(前一轮循环的反思结果) + Agent的技能列表(可调用的工具);

  • 核心逻辑:通过Prompt引导LLM(如GPT-4、Claude、文心一言)进行思维链(Chain-of-Thought)推理,明确"需要做什么、先做什么、用什么工具做";

  • 输出 :结构化的任务步骤列表(如JSON格式),示例:

    json 复制代码
    [
      {"step_id": 1, "description": "爬取电商网站手机销量页面", "skill_name": "web_crawler", "parameters": {"url": "https://xxx.com/phone/sales", "method": "GET"}},
      {"step_id": 2, "description": "解析爬取的HTML数据,提取机型和销量", "skill_name": "html_parser", "parameters": {"target_tags": ["div.class='phone-name'", "span.class='sales-num'"]}},
      {"step_id": 3, "description": "统计销量并排序,筛选Top10机型", "skill_name": "data_analysis", "parameters": {"sort_field": "sales", "top_n": 10}},
      {"step_id": 4, "description": "生成可视化柱状图并保存到本地", "skill_name": "plot_generator", "parameters": {"chart_type": "bar", "save_path": "./sales_top10.png"}}
    ]

2. Observe(观察):获取环境状态与执行前置信息

Observe阶段是Agent的"感知环节",核心目标是为Act阶段的执行获取必要的环境信息或前置数据,解决"执行前需要知道什么"的问题。

  • 输入:Plan阶段生成的当前步骤 + Agent的环境上下文;

  • 核心逻辑

    • 主动拉取环境状态:如读取本地文件列表、获取数据库连接状态、调用API获取实时数据;
    • 被动接收外部输入:如用户补充的信息、前一步骤的执行结果;
    • 格式标准化:将获取的非结构化信息(如网页文本、日志)转换为LLM可理解的结构化数据;
  • 输出 :标准化的环境状态信息(如键值对、JSON),示例:

    json 复制代码
    {
      "env_status": {
        "file_system": {"./data": ["sales_raw.html", "temp.json"]},
        "api_response": {"status_code": 200, "content_length": 12580},
        "previous_step_result": "已成功爬取销量页面,保存至./data/sales_raw.html"
      }
    }

3. Act(执行):调用Skill完成具体操作

Act阶段是Agent的"行动环节",核心目标是执行Plan阶段规划的具体步骤,调用对应的Skill(工具/技能)完成操作。

  • 输入:Plan阶段的步骤参数 + Observe阶段的环境信息;

  • 核心逻辑

    • Skill路由:根据步骤中指定的skill_name匹配注册的工具函数;
    • 参数校验:验证输入参数是否符合Skill的要求(如必填参数、数据类型);
    • 执行调用:调用Skill并捕获执行结果(成功/失败、返回值、异常信息);
  • 输出 :结构化的执行结果,包含状态(success/fail)、返回数据、异常信息(若有),示例:

    json 复制代码
    {
      "step_id": 2,
      "skill_name": "html_parser",
      "execution_status": "success",
      "result": [
        {"phone_name": "iPhone 15", "sales": 125000},
        {"phone_name": "华为Mate 60 Pro", "sales": 118000},
        {"phone_name": "小米14", "sales": 98000}
      ],
      "error_msg": ""
    }

4. Reflect(反思):根据执行结果调整后续计划

Reflect阶段是Agent的"复盘环节",核心目标是验证当前步骤的执行结果是否符合预期,并决定"继续执行下一步""重试当前步骤""终止任务"或"请求用户帮助"。

  • 输入:Act阶段的执行结果 + Plan阶段的原始步骤 + 任务总目标;

  • 核心逻辑

    • 结果校验:对比执行结果与步骤预期目标(如"是否成功提取销量数据");
    • 异常判断:若执行失败,分析原因(参数错误、工具调用失败、环境问题);
    • 计划调整:生成调整后的步骤(如重试时修改参数、跳过失败步骤、新增纠错步骤);
  • 输出 :反思结论 + 调整后的步骤列表,示例:

    json 复制代码
    {
      "reflect_conclusion": "当前步骤执行成功,已提取3款机型销量数据,但未覆盖全部机型,需继续执行下一步统计排序",
      "adjusted_plans": [
        {"step_id": 3, "description": "统计销量并排序,筛选Top10机型", "skill_name": "data_analysis", "parameters": {"sort_field": "sales", "top_n": 10}},
        {"step_id": 4, "description": "生成可视化柱状图并保存到本地", "skill_name": "plot_generator", "parameters": {"chart_type": "bar", "save_path": "./sales_top10.png"}}
      ],
      "need_retry": false,
      "need_user_intervention": false
    }

Lobster循环整体流程(Mermaid流程图)

未完成
已完成


用户输入指令
初始化上下文/技能列表
Plan阶段:LLM拆解任务步骤
Observe阶段:获取环境/前置信息
Act阶段:调用Skill执行步骤
Reflect阶段:验证结果+调整计划
任务是否完成?
输出最终结果
执行失败且需重试?
需要用户干预?
暂停循环,请求用户输入

源码解析:agent/core/loop.py 中的核心函数(run_lobster_cycle

OpenClaw框架中,Lobster循环的核心逻辑封装在agent/core/loop.py文件的run_lobster_cycle函数中。以下是该函数的核心源码拆解(基于OpenClaw v1.2.0,关键部分添加注释):

1. 核心函数整体结构

python 复制代码
import json
import logging
from typing import Dict, List, Any
from openclaw.llm.client import LLMClient  # LLM客户端
from openclaw.skill.registry import SkillRegistry  # 技能注册器
from openclaw.memory.short_term import ShortTermMemory  # 短期记忆

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def run_lobster_cycle(
    user_instruction: str,
    llm_client: LLMClient,
    skill_registry: SkillRegistry,
    short_term_memory: ShortTermMemory,
    max_cycles: int = 10  # 最大循环次数,防止无限循环
) -> Dict[str, Any]:
    """
    运行Lobster循环的核心函数
    :param user_instruction: 用户原始指令
    :param llm_client: LLM客户端实例(用于调用大模型)
    :param skill_registry: 技能注册器(管理所有可调用的Skill)
    :param short_term_memory: 短期记忆(存储上下文)
    :param max_cycles: 最大循环次数
    :return: 最终执行结果
    """
    # 初始化循环状态
    cycle_count = 0
    task_completed = False
    final_result = {"status": "pending", "content": ""}
    
    # 循环执行直至任务完成或达到最大次数
    while cycle_count < max_cycles and not task_completed:
        try:
            logger.info(f"开始第{cycle_count+1}轮Lobster循环")
            
            # 1. Plan阶段:拆解任务步骤
            plan_result = _plan_stage(
                user_instruction=user_instruction,
                llm_client=llm_client,
                skill_registry=skill_registry,
                short_term_memory=short_term_memory
            )
            if not plan_result["success"]:
                raise Exception(f"Plan阶段失败:{plan_result['error_msg']}")
            current_plans = plan_result["plans"]
            logger.info(f"Plan阶段生成{len(current_plans)}个步骤")
            
            # 2. Observe阶段:获取环境信息
            observe_result = _observe_stage(
                current_plans=current_plans,
                short_term_memory=short_term_memory
            )
            if not observe_result["success"]:
                raise Exception(f"Observe阶段失败:{observe_result['error_msg']}")
            env_info = observe_result["env_info"]
            logger.info("Observe阶段获取环境信息完成")
            
            # 3. Act阶段:执行当前步骤
            act_result = _act_stage(
                current_plans=current_plans,
                env_info=env_info,
                skill_registry=skill_registry
            )
            logger.info(f"Act阶段执行完成,状态:{act_result['execution_status']}")
            
            # 4. Reflect阶段:反思并调整计划
            reflect_result = _reflect_stage(
                act_result=act_result,
                current_plans=current_plans,
                user_instruction=user_instruction,
                llm_client=llm_client
            )
            if reflect_result["need_user_intervention"]:
                final_result = {
                    "status": "need_intervention",
                    "content": f"需要用户干预:{reflect_result['reflect_conclusion']}"
                }
                break
            
            # 更新上下文记忆
            short_term_memory.add(
                content=json.dumps({
                    "cycle": cycle_count+1,
                    "act_result": act_result,
                    "reflect_result": reflect_result
                })
            )
            
            # 判断任务是否完成
            if reflect_result["task_completed"]:
                task_completed = True
                final_result = {
                    "status": "success",
                    "content": reflect_result["final_content"]
                }
            else:
                # 更新下一步计划
                current_plans = reflect_result["adjusted_plans"]
            
            cycle_count += 1
            
        except Exception as e:
            logger.error(f"第{cycle_count+1}轮循环出错:{str(e)}")
            final_result = {
                "status": "failed",
                "content": f"循环执行失败:{str(e)}"
            }
            break
    
    # 处理最大循环次数超限
    if cycle_count >= max_cycles and not task_completed:
        final_result = {
            "status": "timeout",
            "content": f"达到最大循环次数({max_cycles}次),任务未完成"
        }
    
    logger.info(f"Lobster循环结束,最终状态:{final_result['status']}")
    return final_result

2. 核心子函数拆解

(1)Plan阶段子函数 _plan_stage
python 复制代码
def _plan_stage(
    user_instruction: str,
    llm_client: LLMClient,
    skill_registry: SkillRegistry,
    short_term_memory: ShortTermMemory
) -> Dict[str, Any]:
    """Plan阶段:调用LLM拆解任务为可执行步骤"""
    # 1. 构造Prompt(包含思维链引导+技能列表+上下文)
    skill_list = skill_registry.list_skills()  # 获取所有注册的Skill
    skill_info = json.dumps([{"name": s.name, "description": s.description, "parameters": s.parameters} for s in skill_list], ensure_ascii=False)
    history_context = short_term_memory.get_all()  # 获取历史上下文
    
    prompt = f"""
    你是OpenClaw Agent的规划助手,需要将用户指令拆解为结构化的可执行步骤。
    要求:
    1. 步骤需匹配可用技能列表,每个步骤指定唯一的skill_name;
    2. 步骤参数需符合对应技能的参数要求;
    3. 步骤需按逻辑顺序排列,可迭代执行;
    4. 输出格式为JSON数组,仅返回JSON,无其他内容。
    
    可用技能列表:
    {skill_info}
    
    历史上下文(前序循环结果):
    {json.dumps(history_context, ensure_ascii=False) if history_context else "无"}
    
    用户指令:{user_instruction}
    """
    
    # 2. 调用LLM生成步骤
    try:
        llm_response = llm_client.complete(prompt=prompt)
        plans = json.loads(llm_response.content)
        return {
            "success": True,
            "plans": plans,
            "error_msg": ""
        }
    except json.JSONDecodeError:
        return {
            "success": False,
            "plans": [],
            "error_msg": "LLM返回结果非合法JSON格式"
        }
    except Exception as e:
        return {
            "success": False,
            "plans": [],
            "error_msg": f"调用LLM失败:{str(e)}"
        }
(2)Act阶段子函数 _act_stage
python 复制代码
def _act_stage(
    current_plans: List[Dict[str, Any]],
    env_info: Dict[str, Any],
    skill_registry: SkillRegistry
) -> Dict[str, Any]:
    """Act阶段:调用Skill执行当前步骤"""
    # 仅执行当前第一个步骤(循环迭代执行后续步骤)
    current_step = current_plans[0]
    skill_name = current_step["skill_name"]
    
    # 1. 查找注册的Skill
    skill = skill_registry.get_skill(skill_name)
    if not skill:
        return {
            "step_id": current_step["step_id"],
            "skill_name": skill_name,
            "execution_status": "failed",
            "result": "",
            "error_msg": f"未找到注册的技能:{skill_name}"
        }
    
    # 2. 合并步骤参数与环境信息
    execution_params = {**current_step["parameters"], **env_info}
    
    # 3. 参数校验
    if not skill.validate_params(execution_params):
        return {
            "step_id": current_step["step_id"],
            "skill_name": skill_name,
            "execution_status": "failed",
            "result": "",
            "error_msg": f"参数校验失败,缺少必填参数:{skill.required_params}"
        }
    
    # 4. 执行Skill
    try:
        execution_result = skill.execute(execution_params)
        return {
            "step_id": current_step["step_id"],
            "skill_name": skill_name,
            "execution_status": "success",
            "result": execution_result,
            "error_msg": ""
        }
    except Exception as e:
        return {
            "step_id": current_step["step_id"],
            "skill_name": skill_name,
            "execution_status": "failed",
            "result": "",
            "error_msg": f"技能执行失败:{str(e)}"
        }

3. 核心代码关键点说明

  • 循环终止条件 :通过max_cycles限制最大循环次数,避免Agent陷入无限循环;
  • 模块化设计:将四个阶段拆分为独立子函数,便于扩展和维护;
  • 异常处理:每个阶段都有异常捕获逻辑,保证循环的健壮性;
  • 上下文传递 :通过ShortTermMemory类存储每轮循环的结果,实现上下文的跨轮传递;
  • Skill解耦 :通过SkillRegistry管理所有工具,Act阶段仅需通过名称匹配,无需硬编码调用逻辑。

任务拆解算法:基于思维链(Chain-of-Thought)的Prompt设计

Plan阶段的核心是让LLM生成结构化的任务步骤,而实现这一目标的关键是Prompt设计------基于思维链(Chain-of-Thought,CoT)的Prompt能引导LLM像人类一样"一步步思考",而非直接输出结果。

1. 思维链Prompt的核心设计原则

  • 明确角色定位:告知LLM"你是OpenClaw Agent的规划助手",明确其任务;
  • 限定输出格式:强制返回JSON数组,避免LLM输出非结构化文本;
  • 提供上下文:包含可用Skill列表、历史循环结果,让LLM知道"能调用什么工具""之前做了什么";
  • 引导逻辑拆解:通过示例或指令引导LLM按"先做A、再做B、最后做C"的逻辑拆分任务;
  • 容错提示:提示LLM处理模糊指令(如用户未指定具体网址时,生成"请求用户补充网址"的步骤)。

2. 优化后的CoT Prompt模板(可直接复用)

python 复制代码
def get_plan_prompt_template() -> str:
    template = """
    角色:你是OpenClaw Agent的专业规划师,负责将用户的自然语言指令拆解为可执行的结构化步骤。
    核心规则:
    1. 步骤必须匹配【可用技能列表】中的技能,每个步骤仅调用一个技能;
    2. 步骤参数必须符合对应技能的参数要求(必填参数不可缺失);
    3. 步骤需按"先准备、再执行、后验证"的逻辑顺序排列;
    4. 若指令模糊(如缺少网址/文件路径),生成"请求用户补充信息"的步骤,而非直接执行;
    5. 若任务可拆分为子任务,每个子任务对应一个步骤,步骤ID连续递增;
    6. 输出格式为JSON数组,仅返回JSON,无任何解释性文字,示例:
       [{"step_id": 1, "description": "步骤描述", "skill_name": "技能名", "parameters": {"参数1": "值1", "参数2": "值2"}}]
    
    可用技能列表:
    {skill_info}
    
    历史上下文(前序循环执行结果):
    {history_context}
    
    用户指令:{user_instruction}
    
    请严格按照规则输出步骤列表:
    """
    return template

3. Prompt优化前后效果对比

优化前(普通Prompt) 优化后(CoT Prompt)
输出非结构化文本: "首先爬取数据,然后分析,最后生成图表" 输出结构化JSON: json<br>[<br> {"step_id": 1, "description": "爬取电商网站手机销量页面", "skill_name": "web_crawler", "parameters": {"url": "https://xxx.com/phone/sales"}},<br> {"step_id": 2, "description": "解析爬取的HTML数据", "skill_name": "html_parser", "parameters": {"target_tags": ["div.class='phone-name'"]}},<br> {"step_id": 3, "description": "生成可视化图表", "skill_name": "plot_generator", "parameters": {"chart_type": "bar"}}<br>]
未考虑技能参数要求,导致Act阶段参数校验失败 严格匹配技能参数,Act阶段可直接执行
无法处理模糊指令,直接报错 生成"请求用户补充信息"的步骤,提升容错性

工具调用规范:Skill的输入输出如何与LLM交互

Lobster循环中,Act阶段的核心是调用Skill(工具),而Skill与LLM的交互是否规范,直接决定循环能否稳定运行。OpenClaw框架定义了统一的Skill接口规范,确保LLM生成的步骤能被正确执行,执行结果能被LLM正确解析。

1. Skill核心接口规范(基类定义)

python 复制代码
from abc import ABC, abstractmethod
from typing import Dict, List, Any

class BaseSkill(ABC):
    """所有Skill的基类,定义统一接口"""
    def __init__(self, name: str, description: str, required_params: List[str], optional_params: List[str] = None):
        self.name = name  # 技能名称(唯一标识)
        self.description = description  # 技能描述(供LLM识别)
        self.required_params = required_params  # 必填参数
        self.optional_params = optional_params or []  # 可选参数
    
    def validate_params(self, params: Dict[str, Any]) -> bool:
        """校验参数是否符合要求"""
        # 检查必填参数是否存在
        missing_params = [p for p in self.required_params if p not in params]
        if missing_params:
            logger.error(f"缺少必填参数:{missing_params}")
            return False
        # 检查参数类型(可选,可重写)
        return True
    
    @abstractmethod
    def execute(self, params: Dict[str, Any]) -> Any:
        """执行技能,返回结构化结果"""
        pass

2. Skill输入输出规范

(1)输入参数规范
  • 命名规则 :使用小写蛇形命名(如save_path),避免大小写混合;
  • 数据类型:优先使用基础类型(str/int/float/bool),复杂类型使用JSON字符串;
  • 必填/可选分离:明确标注必填参数,LLM生成步骤时必须包含;
  • 默认值:可选参数设置合理默认值,降低LLM生成难度。
(2)输出结果规范
  • 结构化输出:优先返回JSON可序列化的数据(dict/list),避免返回复杂对象;
  • 状态标识 :包含execution_status(success/fail)字段,便于Reflect阶段判断;
  • 异常信息 :失败时返回error_msg字段,说明失败原因;
  • 结果描述:返回人类可读的结果描述,便于LLM在Reflect阶段理解。

3. 示例:实现一个符合规范的Skill

python 复制代码
from openclaw.skill.base import BaseSkill
import requests
from typing import Dict, Any

class WebCrawlerSkill(BaseSkill):
    """网页爬取技能,符合OpenClaw Skill规范"""
    def __init__(self):
        super().__init__(
            name="web_crawler",
            description="爬取指定URL的网页内容,支持GET/POST方法",
            required_params=["url"],
            optional_params=["method", "headers", "timeout"]
        )
    
    def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        # 设置默认参数
        method = params.get("method", "GET").upper()
        headers = params.get("headers", {"User-Agent": "OpenClaw Agent/1.0"})
        timeout = params.get("timeout", 10)
        url = params["url"]
        
        try:
            # 执行爬取
            response = requests.request(
                method=method,
                url=url,
                headers=headers,
                timeout=timeout
            )
            response.raise_for_status()  # 抛出HTTP异常
            
            # 返回结构化结果
            return {
                "execution_status": "success",
                "content": response.text,
                "status_code": response.status_code,
                "content_length": len(response.text),
                "error_msg": ""
            }
        except requests.exceptions.RequestException as e:
            return {
                "execution_status": "failed",
                "content": "",
                "status_code": 0,
                "content_length": 0,
                "error_msg": f"爬取失败:{str(e)}"
            }

# 注册Skill
skill_registry = SkillRegistry()
skill_registry.register_skill(WebCrawlerSkill())

4. Skill与LLM的交互流程(Mermaid流程图)

校验通过
校验失败
LLM生成步骤
步骤中指定skill_name+parameters
SkillRegistry根据name匹配Skill实例
调用validate_params校验参数
调用execute执行Skill
返回参数错误信息
Skill返回结构化执行结果
Reflect阶段LLM解析结果
调整后续步骤

上下文记忆注入:短期记忆如何在循环中传递

Agent要完成复杂任务,必须具备"记忆能力"------记住前一轮循环的执行结果、用户的补充指令、环境状态的变化,这就是短期记忆(ShortTermMemory)在Lobster循环中的核心作用。

1. 短期记忆的核心设计

OpenClaw的ShortTermMemory类本质是一个有序的上下文存储容器,具备"添加、查询、清空"三个核心方法,存储内容包括:

  • 用户原始指令;
  • 每轮循环的Plan/Observe/Act/Reflect结果;
  • 用户补充的干预信息;
  • 环境状态的关键变化(如文件创建/删除、API连接状态)。

2. 短期记忆实现代码

python 复制代码
from typing import List, Dict, Any
import json

class ShortTermMemory:
    """短期记忆类,存储Lobster循环的上下文信息"""
    def __init__(self):
        self.memory: List[Dict[str, Any]] = []  # 按时间顺序存储
    
    def add(self, content: str or Dict[str, Any], memory_type: str = "cycle_result") -> None:
        """添加记忆内容"""
        if isinstance(content, dict):
            content = json.dumps(content, ensure_ascii=False)
        self.memory.append({
            "timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "type": memory_type,
            "content": content
        })
    
    def get_all(self) -> List[Dict[str, Any]]:
        """获取所有记忆内容"""
        return self.memory
    
    def get_latest(self, count: int = 1) -> List[Dict[str, Any]]:
        """获取最近N条记忆"""
        return self.memory[-count:] if len(self.memory) >= count else self.memory
    
    def clear(self) -> None:
        """清空记忆"""
        self.memory = []

3. 短期记忆在循环中的注入流程

短期记忆主要在两个阶段注入:

(1)Plan阶段注入

将历史记忆(前序循环结果)拼接到Prompt中,让LLM知道"之前做了什么",避免重复执行已完成的步骤,示例:

python 复制代码
# 获取最近3轮循环的记忆
latest_memory = short_term_memory.get_latest(count=3)
# 拼接到Plan Prompt中
prompt = prompt.format(
    skill_info=skill_info,
    history_context=json.dumps(latest_memory, ensure_ascii=False),
    user_instruction=user_instruction
)
(2)Reflect阶段注入

将当前Act阶段的执行结果添加到记忆中,为下一轮循环提供上下文,示例:

python 复制代码
# 在Reflect阶段后添加记忆
short_term_memory.add(
    content={
        "cycle": cycle_count+1,
        "act_result": act_result,
        "reflect_result": reflect_result
    },
    memory_type="cycle_result"
)

4. 记忆注入的关键优化点

  • 记忆截断:只传递最近N轮的记忆(如3-5轮),避免Prompt过长导致LLM上下文溢出;
  • 记忆过滤:只保留关键信息(如执行结果、反思结论),过滤冗余日志;
  • 记忆分类:按类型(循环结果、用户输入、环境信息)存储,便于按需调用。

实战:修改Lobster循环,增加"人类确认"环节(高危操作前暂停)

在实际使用中,Agent执行高危操作(如删除文件、调用付费API、修改数据库)时,需要增加"人类确认"环节,避免误操作。以下是具体的改造步骤:

1. 定义高危技能列表

首先,在循环初始化时定义需要人类确认的高危技能:

python 复制代码
HIGH_RISK_SKILLS = ["file_delete", "database_write", "api_payment", "system_command"]

2. 修改Act阶段,增加确认逻辑

_act_stage函数中,添加高危技能的确认判断:

python 复制代码
def _act_stage(
    current_plans: List[Dict[str, Any]],
    env_info: Dict[str, Any],
    skill_registry: SkillRegistry,
    high_risk_skills: List[str] = HIGH_RISK_SKILLS
) -> Dict[str, Any]:
    current_step = current_plans[0]
    skill_name = current_step["skill_name"]
    
    # 新增:高危技能判断
    if skill_name in high_risk_skills:
        print(f"\n⚠️ 即将执行高危操作:{current_step['description']}")
        print(f"技能名称:{skill_name}")
        print(f"执行参数:{json.dumps(current_step['parameters'], ensure_ascii=False)}")
        # 等待用户确认
        user_confirm = input("是否确认执行?(y/n):")
        if user_confirm.lower() != "y":
            return {
                "step_id": current_step["step_id"],
                "skill_name": skill_name,
                "execution_status": "cancelled",
                "result": "",
                "error_msg": "用户取消执行高危操作"
            }
    
    # 原有逻辑(略)

3. 修改Reflect阶段,处理"用户取消"状态

_reflect_stage函数中,新增对cancelled状态的处理:

python 复制代码
def _reflect_stage(...):
    # 原有逻辑:获取执行状态
    execution_status = act_result["execution_status"]
    
    # 新增:处理用户取消状态
    if execution_status == "cancelled":
        return {
            "reflect_conclusion": "用户取消执行高危操作,任务终止",
            "adjusted_plans": [],
            "need_retry": False,
            "need_user_intervention": False,
            "task_completed": True,
            "final_content": "任务已终止:用户取消执行高危操作"
        }
    
    # 原有逻辑(略)

4. 完整改造后的run_lobster_cycle函数(关键修改)

python 复制代码
def run_lobster_cycle(...):
    # 新增:定义高危技能列表
    high_risk_skills = ["file_delete", "database_write", "api_payment", "system_command"]
    
    while cycle_count < max_cycles and not task_completed:
        try:
            # ... 原有Plan/Observe逻辑 ...
            
            # 3. Act阶段:执行当前步骤(传入高危技能列表)
            act_result = _act_stage(
                current_plans=current_plans,
                env_info=env_info,
                skill_registry=skill_registry,
                high_risk_skills=high_risk_skills  # 新增参数
            )
            
            # ... 原有Reflect逻辑 ...
            
        except Exception as e:
            # ... 原有异常处理 ...

5. 测试改造效果

当Agent执行"file_delete"技能时,控制台会输出以下内容并暂停,等待用户确认:

复制代码
开始第2轮Lobster循环
Plan阶段生成1个步骤
Observe阶段获取环境信息完成

⚠️ 即将执行高危操作:删除本地文件./data/sales_raw.html
技能名称:file_delete
执行参数:{"file_path": "./data/sales_raw.html"}
是否确认执行?(y/n):
  • 输入y:继续执行删除操作;
  • 输入n:终止任务,返回"用户取消执行高危操作"的结果。

面试考点:ReAct模式与Lobster循环的异同

在大模型Agent相关面试中,ReAct模式是高频考点,而Lobster循环作为ReAct的工程化实现,两者的异同是核心考察点:

1. 核心相同点

  • 核心思想一致:均遵循"推理(Reasoning)+ 行动(Acting)"的闭环逻辑,通过"思考-行动-反思"完成复杂任务;
  • 迭代执行:均支持多轮迭代,根据执行结果调整后续策略,而非一次性执行;
  • 环境交互:均强调Agent与外部环境的交互(如调用工具、获取环境信息),而非仅依赖LLM的内部推理。

2. 核心不同点

维度 ReAct模式(理论) Lobster循环(工程实现)
定义 一种Agent设计范式,描述"思考-行动"的核心逻辑 OpenClaw框架中具体的执行循环,是ReAct的落地实现
阶段划分 分为Reason(推理)和Act(行动)两个核心阶段 拆分为Plan/Observe/Act/Reflect四个阶段,更细化
执行边界 无明确的循环终止条件 定义max_cycles、"任务完成判断"、"用户干预"等终止条件
工程细节 不涉及具体的代码实现、参数校验、异常处理 包含Skill注册、参数校验、记忆管理、异常捕获等工程细节
灵活性 仅为理论框架,无固定实现方式 可通过修改代码扩展功能(如增加人类确认、自定义记忆规则)

3. 面试高频问题及参考答案

问题1:ReAct模式解决了传统LLM调用的什么问题?

答:传统LLM调用是"一次性输入-输出",无法处理需要多步交互的复杂任务(如需要多次调用工具、根据结果调整策略);ReAct模式通过"推理-行动"闭环,让Agent能像人类一样"边思考边行动",解决了LLM"纸上谈兵"的问题,同时通过与外部环境交互,避免了LLM的知识过期、计算能力弱等缺陷。

问题2:Lobster循环中Reflect阶段的核心作用是什么?

答:Reflect阶段是Lobster循环的"复盘环节",核心作用包括:① 验证当前步骤的执行结果是否符合预期;② 分析执行失败的原因(参数错误、工具问题、环境问题);③ 调整后续计划(重试、跳过、新增步骤);④ 判断是否需要用户干预或终止任务。Reflect阶段保证了循环的鲁棒性,避免Agent陷入无效执行。

问题3:如何优化Lobster循环的执行效率?

答:可从以下维度优化:① 记忆截断:只传递关键的历史上下文,减少LLM调用的Prompt长度;② 步骤合并:将连续的简单步骤合并为一个步骤,减少循环次数;③ 技能缓存:对重复调用的技能(如爬取同一网页)增加缓存,避免重复执行;④ 并行执行:对无依赖的步骤实现并行调用,提升执行速度;⑤ LLM选型:对简单步骤使用轻量级LLM(如GPT-3.5),复杂步骤使用GPT-4,平衡效率与效果。

总结

关键点回顾

  1. Lobster循环核心:作为OpenClaw Agent的执行引擎,拆分为Plan(规划)、Observe(观察)、Act(执行)、Reflect(反思)四个阶段,形成可迭代的"思考-行动"闭环,是ReAct模式的工程化实现;
  2. 核心设计要点 :通过思维链Prompt实现任务拆解、统一的Skill接口规范保证工具调用稳定性、短期记忆注入实现上下文传递,同时通过max_cycles和异常处理保证循环健壮性;
  3. 实战扩展:可通过修改核心函数扩展循环功能(如增加人类确认环节),优化方向包括记忆截断、步骤合并、技能缓存等,提升执行效率。

本文从理论到源码、从设计到实战,全方位拆解了Lobster循环的核心逻辑,希望能帮助你不仅理解Agent的"思考"机制,更能动手改造和优化循环逻辑,让OpenClaw Agent更好地适配实际业务场景。

相关推荐
穿过锁扣的风2 小时前
OpenCV 入门实战:图片与视频处理零基础教程
人工智能·opencv·计算机视觉
沪漂阿龙2 小时前
智能体:给大语言模型装上“手脚”,让它学会使用工具
人工智能·语言模型·自然语言处理
Fuxiao___2 小时前
RoboTwin2.0中训练OpenVLA-oft 全流程(bell + alarmclock)
人工智能·python·深度学习
天空属于哈夫克32 小时前
Java 企微机器人开发:高性能、可扩展的私域自动化集成方案
java·机器人·企业微信
Daydream.V2 小时前
Opencv——轮廓有关操作
人工智能·opencv·计算机视觉
golang学习记2 小时前
IDEA 2026.1 EAP 4 发布:git操作更加丝滑了!
java·git·intellij-idea
weiyvyy2 小时前
机器人数学基础补充
人工智能·决策树·机器学习·机器人·嵌入式软件开发·机器人嵌入式开发
一知半解仙2 小时前
AI加持下的IDEA让Java开发更高效
java·人工智能·intellij-idea
2401_865854882 小时前
腾讯云龙虾大模型API配置:一键解锁AI算力,赋能业务高效升级
大数据·人工智能·腾讯云