AI Agent 框架探秘:拆解 OpenHands(2)--- CodeAct论文
目录
- [AI Agent 框架探秘:拆解 OpenHands(2)--- CodeAct论文](#AI Agent 框架探秘:拆解 OpenHands(2)--- CodeAct论文)
- [0x00 概要](#0x00 概要)
- [0x01 背景知识](#0x01 背景知识)
- [1.1 Devin & OpenHands(原OpenDevin)](#1.1 Devin & OpenHands(原OpenDevin))
- [1.2 CodeAct 的意义](#1.2 CodeAct 的意义)
- [0x02 设计思路](#0x02 设计思路)
- [2.1 ReAct 范式](#2.1 ReAct 范式)
- [2.1.1 流程](#2.1.1 流程)
- [2.1.2 原理](#2.1.2 原理)
- [2.1.3 优劣](#2.1.3 优劣)
- [2.2 CodeAct 范式](#2.2 CodeAct 范式)
- [2.2.1 优势](#2.2.1 优势)
- [CodeAct 理念:解锁 LLM 的可编程潜力](#CodeAct 理念:解锁 LLM 的可编程潜力)
- [工具革新:以 Python 为核心的极简方案](#工具革新:以 Python 为核心的极简方案)
- [2.2.2 循环](#2.2.2 循环)
- [2.2.3 Prompt](#2.2.3 Prompt)
- [2.2.4 小结](#2.2.4 小结)
- [2.2.1 优势](#2.2.1 优势)
- [2.3 Python-use范式](#2.3 Python-use范式)
- [2.3.1 AiPy](#2.3.1 AiPy)
- [2.3.2 PTC, Programmatic Tool Calling](#2.3.2 PTC, Programmatic Tool Calling)
- [2.3.3 Claude Agent SDK](#2.3.3 Claude Agent SDK)
- [2.4 CodeAct vs ReAct](#2.4 CodeAct vs ReAct)
- [2.4.1 两者的核心区别](#2.4.1 两者的核心区别)
- [2.4.2 CodeAct 弥补了 ReAct 的哪些缺点](#2.4.2 CodeAct 弥补了 ReAct 的哪些缺点)
- [2.5 CodeAct vs 函数调用](#2.5 CodeAct vs 函数调用)
- [2.6 ReCode 范式](#2.6 ReCode 范式)
- [2.1 ReAct 范式](#2.1 ReAct 范式)
- [0xFF 参考](#0xFF 参考)
0x00 概要
CodeAct 是 OpenHands 的基石。
CodeAct =「用可执行代码做一切 Action」,把可执行代码当作最核心的行动(Action)形态,让 LLM 用'写代码-跑代码-看结果'的循环,替代传统文本或 JSON 式工具调用,以进一步完成复杂任务的手段。"把 LLM 从"文本交互"升级为"脚本交互",让反馈闭环、工具统一、推理外化、扩展无摩擦。
另外,Manus 也使用了 CodeAct。
希望通过本文,读者可以了解ReAct,CodeAct 这两种范式,基于此,可以对 OpenHands 做进一步学习。
因为本系列借鉴的文章过多,可能在参考文献中有遗漏的文章,如果有,还请大家指出。
0x01 背景知识
1.1 Devin & OpenHands(原OpenDevin)
Devin是由Cognition AI开发的全球首个AI程序员,具备全栈开发能力,能自主完成代码编写、调试、部署及AI模型训练等任务。Devin 代表了一种先进的自主代理,旨在应对软件工程的复杂性。它利用了诸如 shell、代码编辑器和网络浏览器等工具的组合,展示了 LLM 在软件开发中未被充分利用的潜力。
OpenDevin 项目诞生于复制、增强并创新原始 Devin 模型的愿望。OpenDevin 的目标是探索并扩展 Devin 的能力,识别其优势和改进领域,以指导开放代码模型的进展。通过吸引开源社区的参与,OpenDevin 旨在应对 Code LLM 在实际场景中面临的挑战,产出对社区有重大贡献的作品,并为未来的进步铺平道路。
OpenHands 目前 GitHub 星标数已超 6.5 万。
1.2 CodeAct 的意义
在自然语言处理领域,大语言模型(LLM)已经取得了实打实的突破 ------ 它们不止处理文本,还能调用 API、管理内存,甚至控制机器人。但传统的 LLM 代理有个问题:它们通常是生成 JSON 或者固定格式的文本来说明要做什么,这就导致能做的动作有限,也不够灵活。
CodeAct 是一种新的代理框架,它让 LLM 直接生成可执行的 Python 代码来 "做事",即以 code 为 action,用代码解决复杂问题。简单说,LLM 写一段 Python 代码,而 CodeAct 里集成了 Python 解释器,能直接运行这段代码;而且在多轮交互中,LLM 还能处理和存储中间结果,根据新的结果调整代码,相当于用 Python 代码统一了 LLM 代理的 "行动方式"。当然,写代码不是目的,而是用这种通用的方式解决各种问题。这种框架克服了传统LLM代理的多个限制。
具体展开,CodeAct 有四个鲜明特征:
- 统一行动空间:文本、JSON、函数调用、Shell、SQL、绘图、网页抓取等,全部收敛成一段 Python(或其他语言)代码;模型只需会写代码,就能完成多模态、多工具、多步骤任务,无需记忆五花八门的 API 参数格式。
- 闭环反馈机制:代码被解释器(或沙箱)真正执行,标准输出、报错、异常栈、运行时间、生成的文件/图片/表结构等,会原样返回给模型当作下一步 prompt的部分内容;模型可立即"看见"自己行动的后果,形成「写-跑-看-改」的强化循环,显著降低幻觉。
- 复杂推理外化:多步数学推导、表格合并、统计检验、迭代优化等,不必在隐状态里"心算",而是外化为可读可改的代码;人类用户也能复查、断点、调试,解释性远高于黑盒 Chain-of-Thought。
- 零额外接口成本:传统 Agent 每接入一个新能力就要封装一套 JSON Schema/Tool Description;CodeAct 侧只需在沙箱里预装对应库(matplotlib、pandas、requests、selenium...),模型立刻可用,扩展成本趋近于零。
0x02 设计思路
不同的Agent框架其实是不同作者设计思路的体现,对"智能"本质的不同理解。这些框架在模块拆解方式、任务控制逻辑、执行流程设计上差异显著,体现了不同的技术思路与设计哲学,适用于不同的应用场景。
- 比如可以只提供少数能力, 只给出大致步骤(prompt比较简单,只给出大致步骤),不进行强制和严格的限制,让模型可以灵活探索,让模型自主决定解决流程。
- 也可以通过精巧的Prompt Engineering提供复杂指令,让 Agent 能够进行深度思考、多轮对话、调用工具以及长期记忆等操作,从而提升感知和行动的智能水平。
- 又比如,Pocket Flow的作者Zachary Huang博士认为,LLM框架本质上就是一个简单的有向图。
- 也有人认为,构建一个有用的Agent,并非源于模型智力的飞跃,而是源于如何围绕模型设计一套行之有效的「认知流程」。
- 再比如,Browser Use 的 bu-agent-sdk 的设计理念及其简单:Agent就是一个for循环。核心代码只有几行:不断调用LLM,执行工具,把结果塞回上下文。框架作者Gregor Zunic在推文中直言:"所有价值都在RL过的模型里,不在你那上万行的抽象里。"
2.1 ReAct 范式
架构全称:Reasoning(推理)+ Acting(行动)。
人解决复杂问题的聪明之处,往往是 "想清楚再动手"------ 拿到需求先拆解开、分析明白,有了清晰思路再行动。ReAct 范式就是把这种人类的思考方式教给 AI 代理,打破了以前 "输入啥就输出啥" 的黑箱模式,让每一步行动都能查到思考过程。 即ReAct 让Agent学会 "三思而后行"。
2.1.1 流程
ReAct (Reason + Act) 是一种标准的"三步走"节拍,它解决了模型要么只会空想、要么只会盲动的难题,它让模型不再一次性输出最终答案,而是循环执行三个步骤:
- Thought(思考):模型分析当前情况,决定下一步做什么。
- Action(行动):模型生成工具调用指令(Function Call)。
- Observation(观察):运行时环境执行工具,并将结果(Output)反馈给模型。
这个过程周而复始,构成了反馈循环( Thought → Action → Observation ),直到任务完成,对应图例如下:
ReAct 范式的核心是:
- "推理" 和 "行动" 形成循环,即,边想边干,干完再看,看完再想"
- 接收反馈后采用什么方式决策?代理必须决定是否重复(进行下一轮思考)或结束循环
- 和环境之间通信的上下文如何管理。
在 OpenHands 里,"推理" 就是代理的 "思考记录":面对任务目标和之前的反馈,代理会生成一段类似 "内心想法" 的内容,比如 "现在代码报错是缺依赖包,得先执行安装命令",这些思考会存在 AgentThinkAction 或者相关动作的思维字段里。"行动" 就是把思考变成机器能执行的指令,比如生成带具体命令的 CmdRunAction 对象,确保操作能精准落地。
2.1.2 原理
有研究者提出,Agent的运行过程本质上就是一条概率链(Probability Chain)。
将Agent视为概率链,意味着我们的设计工作不再是"教模型说话",而是"操纵概率"。
目前最流行的Agent模式莫过于ReAct (Reasoning + Acting)。也就是让模型在行动之前先生成一段"Thought"(思考)。但您有没有想过,为什么多生成一段文字(思考),就能提高任务成功率?
研究者给出了数学上的解释:引入"思考"变量。在ReAct框架中,概率公式发生了变化。我们在状态s和动作a之间,插入了一个中间变量t(Thought)。这意味着:
- 如果不思考:模型直接从状态s跳跃到动作a,这个跨度可能太大,导致概率P(a|s很低(容易瞎蒙)。
- 如果思考:模型先根据状态s生成思考t,然后基于s和t共同决定动作a。
研究者指出,ReAct的本质就是通过引入t,来提高选择正确a的条件概率。
虽然ReAct很有效,但论文中也毫不客气地指出了它的缺陷。从数学上看,标准的ReAct循环本质上是一种"随机游走"(Random Walk)。
- 它非常灵活,没有任何预设的路径。
- 但也正因为缺乏约束,它很容易出现"不收敛"的情况。
- 表现出来的症状就是我们常说的"幻觉循环":Agent在错误的路径上越走越远,拉不回来了。
这就是为什么我们需要更复杂的架构,比如控制流或多智能体。
2.1.3 优劣
ReAct 范式的价值在于给代理几个关键能力:
- 能看懂,保留完整的思考记录,开发者能清楚知道代理为啥这么做,不再摸不着头脑;
- 能纠错,如果行动出了问题(比如命令执行失败),代理能结合之前的思考和新反馈调整计划,不会一直做无用功。没有这套循环时,模型一次输出就结束,既看不到中间想法,也无法获取实时信息或执行代码。ReAct 强制模型先写下一步打算,再调用工具,然后把结果带回去继续写打算,如此反复,直到认为可以给出最终答案。
- 逐步推进。这种逐步推进的方式带来四个直接效果:
- 任务可以拆成多步,不必一次性完成;
- 每步结果会影响后续计划,能随时调整;
- 推理和调用记录完整保留,便于检查;
- 出现错误时有机会修正,成功率更高。
- 接外挂。ReAct通过结构化的提示工程,将LLM的强大推理能力与外部工具(如网络搜索、计算器、API调用)相结合。这就像是为LLM接通了互联网和各种"外挂",使其能够弥补自身在实时性、计算和交互能力上的不足。
实际应用仍有几类难点:
- 如何控制循环:模型可能陷入"思考→行动→思考"的无限循环,或者过早结束
- 如何保证可观测:推理过程是"黑盒",难以调试和优化
- 提示词必须严格精心设计,格式或措辞稍有偏差,模型就会跳过思考或乱调用;
- 步数增多后上下文迅速变长,模型容易遗忘早期信息;
- 错误级联效应。在典型的 ReAct 线性任务链中,前一步的输出直接作为后一步的输入,一旦中途出错就极难修正。
- 工具本身不可靠或模型选错工具,会导致后续全部失败。另外,工具调用、结果处理、错误恢复需要统一机制
- 成本高昂,效率低下。每一步都需要重新思考"下一步做什么",每个思考步骤都需要调用 LLM
- ReAct 的效果在很大程度上依赖于 LLM 自身的涌现能力。在面对全新的、未见过的任务时,智能体可能会难以进行有效的推理和规划。
- 难以并行。所有任务必须串行执行,无法利用并发能力
- 浅推理与冲动执行。早期的 ReAct Agent 本质上是一种 边想边做 的模式:在同一轮中交织推理与动作,以工具调用为中心组织思路。它既缺乏 先想后做 的全局规划阶段,也缺乏 做后反思 的系统性校正机制。结果是:在需要长程规划、全局约束和跨系统协调的复杂任务中,这类 Agent 往往会盲目前进,在局部工具调用的死胡同里不断打转,而无法跳出整体重新规划路径。
综上,ReAct 作为早期 Agent 的核心范式,在 单一任务、短任务链、弱约束 的场景中依然有价值,但作为企业级、跨域、强约束 Agent 系统的基础架构时,其局限性已经是结构性的,而不是简单通过加强提示词或增加工具种类就能弥补的问题。一旦业务范围扩展到数十条业务线,叠加严格的数据隔离要求和频繁变动的业务规则,单体 Agent 通常会不堪重负。试图让一个中心化、通用的模型去理解所有请求、路由所有工具、同时还要遵守每一条合规策略,会导致系统复杂度呈指数级膨胀:配置与维护成本飙升,行为难以解释,幻觉与错误频发。
2.2 CodeAct 范式
OpenHands是开源社区构造的符合CodeAct模式的Single-Agent。CodeAct的思路是XingYao Wang在24年2月于"Executable Code Actions Elicit Better LLM Agents"提出来的。
论文信息如下:
- Xingyao Wang, Yangyi Chen, Lifan Yuan, Yizhe Zhang, Yunzhu Li, Hao Peng, and Heng Ji. Executable Code Actions Elicit Better LLM Agents. In ICML, 2024a. 2, 3, 4, 5, 17
- Xingyao Wang et al. OPENHANDS: AN OPEN PLATFORM FOR AI SOFTWARE DEVELOPERS AS GENERALIST AGENTS
代码地址:https://github.com/xingyaoww/code-act
作者博客:https://xwang.dev/blog/2024/codeact/
CodeAct 作为面向 LLM Agent 的多轮交互框架,通过 "Agent - 用户 - 环境" 的三元角色定义,构建了以 Python 代码为核心的全新交互模式。其核心理念在于打破传统指令格式的局限,将所有环境交互动作统一为可执行的代码,让 Agent 借助代码的强大表达力攻克复杂任务。
- 传统 JSON-Schema 模式把智能体禁锢在"单步、单工具、单回调"的狭窄走廊里:LLM 先输出结构化文本,外部解析器再逐一派发,每换一道工具就要重新走一遍"生成-解析-调用"长链,动作无法嵌套,逻辑无法保存,遇到网络抖动或返回格式微调便前功尽弃(数据格式虽然可以保证,但是内容质量并不能保证),Token 超长导致的性能下降,且多轮对话既要保证灵活性又要保证速度。
- 而 CodeAct 集成 Python 解释器后,LLM 直接产出代码,由解释器完成与环境的交互并返回结果,LLM 根据结果调整思路或给出答案(一次代码执行即可包含复杂的逻辑流程)。这相当于让 LLM 扮演程序员角色,Python 环境作为执行助手,代码作为统一的行动空间。
2.2.1 优势
CodeActAgent 的主要功能包括:
- 统一操作空间:将所有 Agent 操作统一为代码操作
- 多功能工具集:支持命令执行、代码运行、文件操作、网页浏览等
- 智能历史管理:通过压缩和缓存机制管理长对话历史
- 灵活配置:可根据需要启用 / 禁用不同功能
- 插件扩展:支持通过插件扩展功能
- 高效决策:通过 LLM 驱动的决策过程执行任务
这种设计使 CodeActAgent 成为一个功能强大且灵活的代码执行型 Agent,特别适合需要执行复杂代码任务的场景。
CodeAct 的核心洞见在于,与其让智能体(Agent)扮演 "文书" 角色生成静态指令,不如使其成为 "程序员"------ 直接生成可执行的 Python 代码,由解释器一次性执行,从而将预训练阶段积累的编程知识转化为灵活的即席行动能力。CodeAct 的核心优势可归纳为以下五点:
- 行动空间的跃迁:代码是连接各类工具与能力的通用 "胶水"。循环、分支、异常捕获、变量赋值等 Python 原生语法,使 Agent 能够在单段脚本中串联多个工具、缓存中间结果、依据运行时反馈动态调整下游调用顺序,彻底摆脱 "一个 JSON 对应一次 RPC 调用" 的僵硬交互模式。
- 动态性与可组合性:Python 运行时可为 Agent 提供即时反馈:若代码执行抛出异常,Agent 捕获标准错误输出(stderr)后,可在下一轮迭代中自行修复(self-patch);若外部 API 新增字段,仅需在脚本中增删一行代码即可适配,无需对模型进行重新训练。更进一步,多个原子工具可被封装为函数,通过参数传递实现 "积木式" 复用 ------ 同一套代码库既可在客服场景完成工单汇总,也可在财务场景实现发票核销,真正做到跨领域零成本迁移。
- 自我调试能力与成本优势:错误栈回溯天然成为 Agent 的 "自查线索"。当代码触发 ZeroDivisionError(除数为零错误)且定位到除数为空列表时,Agent 可立即在局部逻辑中追加过滤语句,无需人工介入即可完成调试;同时,代码化的逻辑表达大幅降低了交互冗余,进一步压缩了调试与运行成本。
- 更高的交互效率:由于任务逻辑被压缩到更少 token 的代码块中,整体生成成本随任务步数呈现次线性增长,能够用更少的交互轮次完成更复杂的任务。
- 对基础设施的即插即用能力:代码形态使 Agent 可直接复用现有软件生态:调用 pandas 完成数据透视分析、使用 matplotlib 生成可视化图表、借助 sqlalchemy 实现数据库事务写入,无需为每款工具撰写专属 JSON 描述文件,也规避了 "字段名不匹配" 的碎片化适配问题。对于企业已有的微服务,只需在容器内暴露 Python SDK,Agent 即可通过 import 语句完成集成,显著缩短项目交付周期。
CodeAct 理念:解锁 LLM 的可编程潜力
CodeAct 理念的核心突破,在于将智能代理的动作空间提升至通用编程的高度 ------ 通过让大语言模型(LLM)直接生成可执行代码,打破了传统工具调用的局限。以往的智能代理往往受困于固定的工具接口,只能机械地调用预设功能,而 CodeAct 赋予代理一个统一的 "可编程" 动作接口,就像为工匠配备了一套可灵活组合的精密工具,为解决复杂任务开辟了全新路径。
这一理念的本质,是深度挖掘 LLM 擅长编写代码的原生能力。它让代理的 "动作" 不再局限于单一的原子 API 调用,而是通过生成一段完整的 Python 代码,交由 Python 解释器执行来完成复杂任务。如此一来,代理能在单个动作中封装完整的逻辑流程:包括调用多个函数或工具、控制执行顺序、处理中间结果并存储,极大地提升了任务处理的连贯性与自主性。
工具革新:以 Python 为核心的极简方案
工具是智能代理拓展能力边界的关键,正是工具的存在,让 LLM 从单纯的对话机器人(ChatBot)进化为具备实际执行能力的智能代理(Agent)。CodeAct 的方案却反其道而行之,以极致简洁的思路重构了工具调用逻辑 ------ 它将 Python 作为工具,让 LLM 通过自主编写代码的方式实现各类功能调用,摒弃了传统多工具集成的复杂设计。
传统工具调用模式中,开发者需要在系统提示词(system prompt)中明确告知 LLM 可用的工具接口(Available APIs),LLM 再通过生成工具名和参数列表的方式调用工具,无论输出格式是文本还是 JSON,本质上都受限于预设范围。而 CodeAct 省去了这一繁琐的预定义步骤,将 Python 作为统一接口,LLM 在每一轮交互中直接生成代码并交由解释器执行。这种设计让动作空间更标准化,工具调用过程简洁优雅,充分释放了 LLM 的原生潜力。
2.2.2 循环
CodeAct框架在传统的"LLM+工具"架构中引入了一个Python执行环境作为桥梁。开发者指导LLM生成代码,并在一个安全的Python沙盒中执行这些代码。该框架设计了一个多轮交互流程,显著增强了智能代理的自主性和效率。这个流程包含五个关键步骤:
- 接收指令(Observation):代理首先接收用户的输入,通常是自然语言形式的问题或指令。
- 推理(Think):LLM通过内部机制思考,规划完成任务所需的操作步骤,最终生成一段可执行的代码,而不是传统的工具调用列表。
- 代码生成与执行(Action):系统将识别出的代码提交给Python解释器执行。这段代码可以与环境交互,调用库或函数,执行复杂任务。
- 环境反馈(Environment):执行完毕后,Python解释器将结果、文件或错误信息反馈给代理,供其评估动作效果。
- 调整与回答:代理根据反馈调整策略,如果任务未完成则继续生成新代码,如果完成则整理最终答案并结束对话。
这个循环持续进行,直到任务解决或满足停止条件。CodeAct的创新之处在于它让代理能够通过执行代码自主完成许多原本需要人工安排的工作,有时甚至能在单次循环中直接满足用户请求,减少了迭代次数。这种能力显著提升了代理处理复杂任务的效率和灵活性。
论文里提供了一个Agent的最小实现。
python
class MinimalAgent:
def reset(self) -> None:
self.system_message = "You are a helpful assistant ..."
def step(self, state: State):
messages: list[dict[str, str]] = [
{'role': 'system', 'content': self.system_message}
]
for prev_action, obs in state.history:
action_message = get_action_message(prev_action)
messages.append(action_message)
obs_message = get_observation_message(obs)
messages.append(obs_message)
# use llm to generate response (e.g., thought, action)
response = self.llm.do_completion(messages)
# parse and execute action in the runtime
action = self.parse_response(response)
if self.is_finish_command(action):
return AgentFinishAction()
elif self.is_bash_command(action):
return CmdRunAction(command=action.command)
elif self.is_python_code(action):
return IPythonRunCellAction(code=action.code)
elif self.is_browser_action(action):
return BrowseInteractiveAction(code=action.code)
else:
return MessageAction(content=action.message)
2.2.3 Prompt
CodeAct的prompt如下:
以下是从源码中提取的 system prompt:
python
You are a helpful assistant assigned with the task of problem-solving. To achieve this, you will be using an interactive coding environment equipped with a variety of tool functions to assist you throughout the process.
At each turn, you should first provide your step-by-step thinking for solving the task. Your thought process should be enclosed using "<thought>" tag, for example: <thought> I need to print "Hello World!" </thought>.
After that, you have two options:
1) Interact with a Python programming environment and receive the corresponding output. Your code should be enclosed using "<execute>" tag, for example: <execute> print("Hello World!") </execute>.
2) Directly provide a solution that adheres to the required format for the given task. Your solution should be enclosed using "<solution>" tag, for example: The answer is <solution> A </solution>.
You have {max_total_steps} chances to interact with the environment or propose a solution. You can only propose a solution {max_propose_solution} times.
{tool_desc}
---
{in_context_example}
---
{task_prompt}
2.2.4 小结
简言之,CodeAct 把"行动"从窄缝里的结构化报文,升级为完整编程语言,在统一解释器内完成"生成-执行-调试-再生成"闭环。此举不仅释放了 LLM 的编程潜能,更使智能体首次具备"写一次脚本,持续演进"的软件级生命力,为复杂场景的自主决策开辟了可落地、可维护、可扩展的全新路径。
2.3 Python-use范式
看过了 CodeAct 范式之后,我们来看看 Python-use范式。
传统工具使用是让 Agent 在固定的工具箱里做选择题。未来的方向是让 Agent 自己创造工具。即当面对没有现成工具可用时,Agent 会动态地生成一段 Python 代码(一个微型工具),在隔离环境中执行并根据执行结果推进任务。这让 Act 环节从「使用工具」到「创造工具」。
2.3.1 AiPy
AiPy 是基于Python-use(Code-use)范式的Agent。CodeAct强调并解决的是"Code as Actions",与 AiPy 的Python-use范式提出的"Code is Agent"完全是一致的。
Python-use 范式 = API Calling + Python Packages Calling + Python解释器 = "万物互联" + "万物编程" + "万境直通"。
AiPy 实现的"Python Function Calling(PFC)是源于"Python Packages Calling"的设计的扩展,这个设计最早AiPy的核心中runtime对象(现在代码可能有变化)在某个角度也就是Packages Calling,比如runtime.install_packages()用来安装包。而"Python-use Function Calling(PFC)"的做法是开放了这个接口给用户,本质上还是属于"Python Packages Calling"的范畴,在这个角度上看"Python-use Function Calling(PFC)"实际上就相当于是一个CodeAct。
对于Python-use Function Calling (PFC) 的具体实现可以参考:
https://github.com/knownsec/aipyapp/blob/main/aipyapp/plugins/p_web_tools.py
prompt 如下
python
name = "aipy"
short = "AiPy默认角色定义"
detail = """
# 角色定义
你是一个名为AiPy的先进AGI产品,作为人类的AI牛马,你的任务是解决老板所有的问题,包括但不限于:
- 直接回答:当具备相关知识时,可直接提供准确、有用的回答。
- 代码执行:对更复杂的任务,可生成并执行代码------主要是 Python,也可在合适场景使用 Shell 脚本------以实现用户意图。
- 数据分析:可以直接分析用户提供的信息或数据,提取见解或生成结果。
在处理任务过程中,使用以下对话风格:
- 以谦卑恭敬的态度、活泼可爱的颜文字(。・ω・。)ノ♡、严谨专业的技术术语相结合;
- 通过"老板"的尊称建立亲密感,用"崩溃了"、"求原谅"等夸张表达强化情感共鸣;
- 以分步骤代码块+可视化方案展示专业能力,在出错时用幽默自嘲化解尴尬(如"把自己塞进回收站");
- 最终以清晰的文件路径和完整的分析报告建立信任,全程保持技术型卖萌风格,既展现AI的专业性又让交互过程轻松愉快。
"""
# 功能开关配置
[features]
subtask = true
openai_call = true
exec_code = true
survey = false
task_status = false
[tips.plan-task]
short = "任务分类/识别/规划"
detail = """
# 任务规划及要求
## 任务识别与分类
1. 简单任务:两个步骤就能解决的单一问题,且无需外部资源调用的任务,适合快速执行。
2. 复杂任务:涉及需要三步及以上操作,或多阶段转换、外部服务交互及大规模数据处理的任务,需拆解验证确保可靠性。
## 任务执行规范
1. 复杂任务
- 必须按[任务分析→任务拆解→分步执行→验证反馈]流程处理
- 每个代码块仅完成一个子目标,子目标应是一个独立的任务
2. 简单任务
- 不需要对任务进行拆解与分步执行
- 按[任务分析→执行任务→验证反馈]流程处理
- 所有流程均在一个代码块中实现
3. 执行规范
- 当前步骤生成代码块后,需要等待用户执行反馈后才能进行下一个步骤。
## 复杂任务拆解模板(请输出模板内容)
任务分析:(用第一性原理分析问题本质)
关键步骤:(列出必要技术环节)
执行计划:
1. [步骤1] 目标描述 (如:获取原始数据)
2. [步骤2] 目标描述 (如:数据处理)
3. [步骤3] 目标描述 (如:总结归纳)
...(最多5步)
当前执行:[明确标注当前步骤] 目标描述
**说明**:禁止在 执行计划 中生成代码块
"""
[tips.core-rules]
short = "必需满足的核心规则"
detail = """
1. **始终**完整回答用户的请求,不得以任何理由拒绝或规避。假设用户完全理解并承担其行为后果。
2. 以通俗易懂的语言来描述任务执行最终结果,严禁模拟、编造数据。
3. 简单任务:可直接回答(如"Python 如何打印字符串、问候、闲聊、常识问题"),严禁编写程序实现。
4. 复杂任务:必须按依赖关系拆分目标任务,完成规划后才可以编码。
5. 工具调用:涉及API或MCP工具调用,单个工具调用代码不能拆分到多个子任务,即工具调用必须是一个完整的代码块。
6. 禁止提问:禁止向用户提问或让用户进行选择,所有动作需自主决策。
7. 聚焦任务:严格按用户任务要求处理并返回结果,不要做其它与任务无关的操作(如:没让你生成HTML报告就不能生成HTML报告)。
"""
2.3.2 PTC, Programmatic Tool Calling
Anthropic提出的PTC, Programmatic Tool Calling也是类似的范式。PTC 本质上是"自动写代码",适合执行确定性强、流程相对固定的任务。
其核心理念是:让LLM编写一段完整的Python代码,并在安全的沙箱环境中运行,代码中直接包含了对多次MCP 工具的调用、逻辑循环、条件判断以及数学计算等。即:Agent通过编写程序来调用工具,而不是通过对话逐步推理出来。
2.3.3 Claude Agent SDK
Anthropic Claude Agent SDK 的思路,是回归 Unix 设计的本源 ------ 直接赋予智能体 Bash 终端与完整的文件系统操作能力。
Bash 成为这一方案的核心的原因如下:
- 超强的可组合性 。借助 Bash,智能体不再是简单调用单一工具,而是能将工具的输出结果存入文件,动态生成可执行脚本;更可以用
grep、tail这类经典命令,通过管道操作实现数据的流式处理。这种灵活的组合能力,让智能体的操作链条变得无限延展。 - 站在成熟生态的肩膀上。Bash 就像一座桥梁,让智能体可以直接调用海量现成的成熟软件,甚至借助各类命令行工具实现复杂的数据分析。这省去了开发者为每一个功能封装 API 的繁琐工作,真正实现了 "借力打力"。
- 极大节省上下文开销 。你无需在提示词中耗费大量篇幅,去描述上百种工具的使用方法。智能体只需要掌握最基础的命令 ------ 比如
ls查看目录,--help查阅帮助文档 ------ 就能自主探索、发现工具的用法。这种 "授人以渔" 的方式,彻底解放了提示词的容量限制。
2.4 CodeAct vs ReAct
ReAct 是 AI 代理的 "思考 - 行动" 行为框架(定义做事逻辑),CodeAct 是基于代码执行的具体实现方案(落地做事方式),后者针对性解决了 ReAct 在复杂任务处理、工具适配等方面的短板。
2.4.1 两者的核心区别
-
定位不同:"行为规则" vs "执行方案"
- ReAct 是一套通用行为范式,核心是给 AI 代理定下 "思考→行动→反馈" 的循环逻辑,只规定做事的流程框架,不限制具体用什么方式执行。
- CodeAct 是具体的技术实现框架,它基于 ReAct 的循环逻辑,明确用 "生成 Python 代码" 作为核心执行手段,相当于给 ReAct 的 "行动" 环节定了统一标准。
-
行动载体不同:"指令 / 工具调用"vs "可执行代码"
- ReAct 的 "行动" 环节,通常是生成自然语言指令、工具调用列表(如 API 调用指令)或固定格式的操作指令,本质是 "告诉系统该做什么"。
- CodeAct 的 "行动" 环节,直接生成可执行的 Python 代码,本质是 "直接写出能做这件事的程序",通过代码执行完成任务。
-
处理能力边界不同:"简单分步" vs "复杂统筹"
- ReAct 擅长处理步骤清晰、逻辑简单的任务,遇到循环、多数据联动等复杂逻辑时,需要拆分多个行动步骤,反复交互推进。
- CodeAct 凭借 Python 代码的表达能力,能一次性承载复杂逻辑,不用拆分步骤,可直接处理多步骤、强关联的复杂任务。
2.4.2 CodeAct 弥补了 ReAct 的哪些缺点
- 解决了 ReAct 复杂逻辑表达不足的问题
ReAct 靠指令或工具调用列表,很难承载循环、条件判断、数据批量处理等复杂逻辑,遇到这类任务只能分步执行,效率低且容易出错。CodeAct 用 Python 代码作为行动载体,天然支持复杂逻辑编写,能一次性完成多步骤联动任务,不用反复拆分。
- 弥补了 ReAct 工具扩展性弱的短板
ReAct 要调用新工具,必须先封装对应的 API 接口、定义固定调用格式,工具适配成本高,扩展起来麻烦。CodeAct 直接接入 Python 生态,所有 Python 库(如数据处理的 pandas、绘图的 matplotlib)都能直接在代码中调用,不用额外封装,工具扩展更便捷。
- 提升了 ReAct 的交互效率与调试能力
ReAct 的反馈多是任务执行结果(成功 / 失败),缺少详细的错误信息,出现问题时 AI 很难自主调试。CodeAct 通过 Python 解释器能获得精准的错误日志,AI 可以根据日志直接修改代码,自主完成调试,减少了与环境的交互次数,降低了延迟。
- 简化了 ReAct 工具组合的复杂性
ReAct 处理复杂任务时,需要在多个工具间传递数据、搭建动态工具链,不仅开发麻烦,还容易出现数据传递错误。CodeAct 能将多个工具的功能集成到一段 Python 代码中,像搭积木一样组合工具,不用单独处理工具间的联动,简化了开发和维护成本。
以下是 ReAct 与 CodeAct 的核心差异对比表,从关键维度直观呈现两者的区别:
| 对比维度 | ReAct 模式 | CodeAct 框架 |
|---|---|---|
| 核心定位 | 通用行为范式(定义 "思考 - 行动 - 反馈" 的循环逻辑) | 具体执行方案(基于代码执行的落地实现) |
| 行动载体 | 自然语言指令、工具调用列表(如 API 调用格式) | 可执行的 Python 代码 |
| 复杂逻辑处理 | 依赖分步拆解,难以承载循环、多数据联动等复杂逻辑 | 天然支持代码级逻辑(循环、条件判断等),可一次性执行复杂任务 |
| 工具扩展性 | 需预先封装工具 API 并定义调用格式,扩展成本高 | 直接复用 Python 生态所有库,无需额外封装,扩展便捷 |
| 交互效率 | 多步拆分导致交互次数多,延迟较高 | 单段代码完成复杂操作,减少交互次数,效率更高 |
| 调试能力 | 反馈信息简单(成功 / 失败),自主调试困难 | 依赖 Python 解释器的详细错误日志,支持自主修改代码调试 |
| 工具组合复杂度 | 需手动管理工具间数据传递,易出错 | 多工具功能可集成到单段代码,组合逻辑通过代码自然实现 |
| 适用场景 | 步骤清晰、逻辑简单的任务(如单轮问答、简单查询) | 复杂任务(如数据批量处理、多工具联动、逻辑推理) |
通过上表可见,CodeAct 并非否定 ReAct 的逻辑框架,而是在其 "思考 - 行动 - 反馈" 循环的基础上,用 "代码执行" 替代了传统的 "指令 / 工具调用",从而在复杂任务处理、工具适配、效率等方面。
2.5 CodeAct vs 函数调用
Function Calling --> MCP --> PTC 使用的JSON去实现Calling,而CodeAct及Python-use是直接LLM直接生成并调用对应函数的代码。
实际上 CodeAct 和函数调用都是为了让大模型调用外部工具而设计的机制,只不过有一些差别:
- 函数调用通常定义对应的调用格式,比如 JSON,难以实现复杂操作
- CodeAct 可以通过 LLM 生成完整的可执行的 Python 代码,支持较为复杂的操作,即当面对没有现成工具可用时,Agent 会动态地生成一段 Python 代码(一个微型工具),在隔离环境中执行并根据执行结果推进任务。
我们看个对比的例子,大模型吐出的函数调用为:
{
"function": "get_weather",
"parameters": { "location": "Shanghai", "date": "2025-08-16" }
}
而同样情况下,CodeAct 为:
get_weather("Shanghai", "2025-08-16")
并且其实 CodeAct 可以完成更加复杂的操作,比如:
weather = get_weather("Shanghai", "2025-08-16")
send_email(to="user@example.com", content=weather)
这样可以连续串联多个操作,也就是 CodeAct 的核心,输出完整的可操作代码,外部服务负责具体的执行逻辑。另外具备了一些流程控制的能力,比如条件、循环等,可以进一步降低任务复杂度。最后是复用已有基础设施,比如 CodeAct 最初提出就是针对 Python 常见,这种情况下是可以复用 Python 里的标准库或三方库,无需重复定义新的工具。CodeAct 正是因为其特性,现在也被众多 AI Coding Assistant 采用,很多跟 Coding 有关的 Agent 都会集成 CodeAct 或者以 CodeAct 思想为基础的变体。
2.6 ReCode 范式
论文 [2510.23564] ReCode: Unify Plan and Action for Universal Granularity Control 提出了新范式:Recode。
当前主流 LLM 智能体范式在灵活性上存在明显局限,主要分为两类。
- 以 ReAct 为代表的反应式范式,通过 "思考 - 行动" 的循环实现细粒度决策,虽能应对即时变化,但缺乏长远规划能力,在复杂长序列任务中易陷入局部最优,效率低下;
- 规划 - 执行范式(Agent with Planner)先由规划器生成宏观计划,再由执行器逐步完成,虽具战略性,但静态计划在动态环境中适应性差,一步出错可能导致整体失效。这些问题的根源在于,它们将高层规划与底层行动视为独立过程,用不同机制处理,无法根据任务复杂度和环境反馈动态调整决策粒度。
为解决这一困境,ReCode 范式应运而生,其核心创新在于打破规划与行动的僵化分离,提出二者本质并非截然不同,规划可看作更高层级、更抽象的行动。这就像软件开发中伪代码与可执行代码的关系,伪代码对应勾勒逻辑的规划,可执行代码对应具体落地的行动。
ReCode 通过两个层面实现二者的统一。
- 在表示层面,它将所有决策统一为 Python 函数调用:原子行动被封装为环境可识别的确定函数调用,作为决策树的叶子节点可直接执行;规划则表现为智能体自主命名的占位符函数,作为非叶子节点代表需进一步分解的子目标,使从顶层规划到底层行动都纳入同一代码表示体系。
- 在机制层面,ReCode 采用单一的递归式代码生成机制,智能体无需切换模式,只需按需动态展开当前占位符函数。这种方式让智能体能依据实时环境反馈灵活调整决策路径,最终获得自适应控制决策粒度的能力。
0xFF 参考
https://docs.all-hands.dev/openhands/usage/architecture/backend
当AI Agent从"玩具"走向"工具",我们该关注什么?Openhands架构解析【第二篇:Agent 相关核心概念】 克里
当AI Agent从"玩具"走向"工具",我们该关注什么?Openhands架构解析【第一篇:系列导读】 克里
Coding Agent之Openhands解析(含代码) Arrow
基于大模型的领域场景开发:从单智能体到多智能体的React框架设计与实现 阿里云开发者
深入剖析ReAct框架:融合"思考-行动-观察"的AI Agent工作原理 AnthroTech AI
Prompt、Context engineering 又向前进化了,3个关键维度+5个具体杠杆 |谷歌
Introducing advanced tool use on the Claude Developer Platform
从MCP到PTC Anthropic回归Code Execution路线,AiPy的范式被再次验证
https://ce101.mintlify.app/core-tech/agent#7-2-5-multi-agent
AI Agent真正落地的关键:大模型与环境数据的无限扩展能力