前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9786
  • AWS 开源 2B 决策模型,专做选项判断
  • AI 代码审查太吵,会让真问题被忽略
  • Gemini 视频转仿真演示打通机器人训练
  • RAG 检索不准,先评测嵌入模型
  • 实测 agent-hooks:演示不等于兼容认证
  • 让 Claude Code 直接查询 Grafana 排障
  • Copilot 正式接入 Gemini 4 Argon
  • AI 写码的回报取决于审查与反馈
  • 128GB 苹果芯片 Mac 的 oMLX 部署调优
  • CodeAct 用可执行代码组织 Agent 行动
  • 实测 agent-hooks 在执行前拦截超额退款
  • 用 Python 与 Claude 搭建文本清洗流水线
  • 长任务 Agent 如何保存和恢复工作状态
  • 谷歌旗舰 Argon 开放全球 API 接入
  • GitHub 用上下文模型改进密钥扫描
  • 自动化管理 Bedrock 跨账号定价授权
  • AI Studio个人应用可直接经Play安装
  • 企业问答如何选型:检索增强还是微调
  • 日志与搜索结果如何成为提示注入入口
  • Gemini CLI 自动化为何受终端环境影响
  • Gemini 夜间优化二十万行 Python 项目
  • Gemini 4 Argon 将物理推理接入机器人开发
  • n8n 接入 Gemini 4,串联 MCP 与智能体
  • 自然语言安全查询如何降低成本与延迟
  • DeepMind 发布 Gemini 4 Argon 前沿模型
  • Gemini 4 付费上线,API 限时半价
  • Gemini 4 Argon统一百万Token额度
  • Gemini 4 发布,宣称提升编程与复杂推理
  • Google 向开发者开放 Gemini 4 Argon
  • 用 Slack 智能助手打通 IT 支持流程
  • Grok 4.7 智能体如何平衡推理成本
  • MoE 内核优化提升 H200 推理性能
  • SparseEngine 统一接入十五种稀疏注意力
  • 小模型提示测试:输出格式比文风更关键
  • 用运行状态自动推动编程 Agent 完成任务
  • 微调指标持平,却漏掉更多关键样本
  • 用大模型提取工程图纸中的控制点位
  • 用提交钩子约束编程 Agent 的调用
  • BitNet 提供低比特模型本地推理框架
  • Open WebUI 统一管理本地与云端模型
  • 已加载 40 / 9786
8.0
热点
AI SCORE
技术实践2026-10-14 02:32

CodeAct 用可执行代码组织 Agent 行动

dev.to · AI#Agent#CodeAct#工具调用
Editor brief · 编辑速览

文章解读 ICML 2024 的 CodeAct 研究,让模型通过可执行代码表达行动。该方式可以组合工具操作、处理中间结果并控制执行流程,为 Agent 提供更灵活的行动表达方式。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

可执行代码动作能够激发更强的 LLM 智能体——探索一种构建更强大 AI 智能体的新方式。

引言:我们是否把构建 AI 智能体这件事做复杂了?

构建 AI 智能体时,我们往往专注于添加更多工具、集成更多 API,以及连接更多 MCP 服务器。

背后的假设很直接:智能体拥有的工具越多,能力就越强。

但如果真正的限制并不是智能体可用的工具数量,而是它使用这些工具的方式呢?

这正是 ICML 2024 上发表的研究论文《可执行代码动作能够激发更强的 LLM 智能体》所探讨的问题。

论文提出了 CodeAct:一种让 LLM 通过可执行代码来表达动作的方法,而不是完全依赖传统的工具调用格式。

智能体可以编写代码,将多个操作组合起来、处理中间结果、控制执行流程,并与执行环境交互,而不只是发起彼此独立的工具调用。

这个想法很简单,但它对智能体式 AI 的意义深远。

📄 阅读原始研究论文

传统的 LLM 智能体通常通过预定义接口与工具交互。

模型选择一个工具,生成参数,接收结果,然后决定下一步做什么。

例如,智能体可能需要获取客户记录、筛选记录并生成报告。

采用工具调用的工作流可能涉及几次独立调用:

{
  "tool": "get_customers",
  "arguments": {}
}

随后,模型接收结果,并生成另一次工具调用:

{
  "tool": "filter_customers",
  "arguments": {
    "status": "active"
  }
}

最后,它可能再调用一个工具来生成报告。

这种方法适用于许多任务。不过,协调多个相互依赖的操作,可能需要模型反复做出决策、传递中间消息,并借助编排逻辑。

CodeAct 提供了另一种可能。

智能体可以将工作流表达为可执行代码:

customers = get_customers()

active_customers = [
    customer
    for customer in customers
    if customer["status"] == "active"
]

report = generate_report(active_customers)

print(report)

上述函数代表环境向智能体提供的工具。

关键区别在于,智能体可以直接用代码表达操作之间的关系。

它可以使用变量、循环、条件、函数和异常处理来协调自己的动作。

CodeAct 将可执行代码视为一种动作格式,而不只是展示给用户的文本。

2. 从单次工具调用到可执行工作流

考虑一个需要从三个服务收集信息的任务。

传统的编排层可能会明确规定操作顺序:

accounts = call_tool("get_accounts")
cards = call_tool("get_cards")
transactions = call_tool("get_transactions")

result = call_tool(
    "combine_financial_data",
    {
        "accounts": accounts,
        "cards": cards,
        "transactions": transactions
    }
)

基于代码的方法可以组合相同的操作,并在执行环境中进行额外的本地处理:

accounts = get_accounts()
cards = get_cards()
transactions = get_transactions()

summary = {
    "account_count": len(accounts),
    "card_count": len(cards),
    "transaction_count": len(transactions),
    "total_spending": sum(
        transaction["amount"]
        for transaction in transactions
        if transaction["amount"] > 0
    )
}

print(summary)

这个示例假设工具会以预期格式返回数据,并且正数交易金额代表支出。

优势不只是代码行数更少,而是能够动态定义数据流和控制流。

智能体可以自行决定如何处理结果,无须为每一种可能的操作组合都提供一个单独的工具。

将差异可视化

flowchart TD
    A[User Task] --> B[Traditional Agent]
    B --> C[Tool Call 1]
    C --> D[Observe Result]
    D --> E[Tool Call 2]
    E --> F[Observe Result]
    F --> G[Tool Call 3]
    G --> H[Final Answer]

A --> I[CodeAct-Inspired Agent]
    I --> J[Generate Executable Code]
    J --> K[Execute Multiple Operations]
    K --> L[Observe Execution Result]
    L --> M{Task Complete?}
    M -- No --> J
    M -- Yes --> N[Final Answer]

这张图展示了概念上的区别。实际架构各不相同,传统智能体也可以支持批量调用、循环和多步执行。

3. 为什么可执行代码是一种强大的动作空间

3.1. 动态控制流

并非所有任务都遵循相同的路径。

设想一个获取客户数据的智能体。如果请求成功,它就分析结果;如果请求失败,它就调查错误。

response = fetch_customer_data()

if response["status"] == "success":
    customer = response["data"]

analysis = analyze_customer(customer)

print(analysis)

else:
    error_details = response.get(
        "error",
        "Unknown error"
    )

investigation = investigate_error(error_details)

print(investigation)

在固定的工作流中,这种分支逻辑可能需要在编排层中定义。

使用可执行代码时,智能体可以直接在生成的动作中表达这个分支。

3.2. 重复操作

假设智能体必须检查多个代码仓库或服务。

repositories = [
    "frontend",
    "backend",
    "shared-libraries"
]

results = {}

for repository in repositories:
    results[repository] = search_repository(
        repository,
        query="payment"
    )

for repository, matches in results.items():
    print(repository, len(matches))

循环可以协调重复操作,同时保留结果,以供后续分析。

这些工具仍然需要在执行环境中可用。CodeAct 不会自动创造新的外部能力。

3.3. 复用中间结果

智能体可能需要先处理某个操作返回的数据,再将其传递给另一个操作。

transactions = get_transactions()

high_value_transactions = [
    transaction
    for transaction in transactions
    if transaction["amount"] >= 10000
]

customer_ids = {
    transaction["customer_id"]
    for transaction in high_value_transactions
}

customers = [
    get_customer(customer_id)
    for customer_id in customer_ids
]

print({
    "high_value_transactions": len(
        high_value_transactions
    ),
    "related_customers": len(customers)
})

在这里,智能体可以通过一个可执行工作流完成记录筛选、标识符提取和关联实体获取。

在真实的金融应用中,这些操作需要适当的授权、隐私控制,以及明确定义的金额语义。

3.4. 将操作组合成可复用的函数

代码还可以让一个动作更容易理解和复用。

def investigate_customer(customer_id):
    customer = get_customer(customer_id)

transactions = get_transactions(customer_id)

flagged_transactions = [
        transaction
        for transaction in transactions
        if transaction.get("flagged", False)
    ]

return {
        "customer": customer,
        "transaction_count": len(transactions),
        "flagged_transactions": flagged_transactions
    }

result = investigate_customer("customer-123")

print(result)

当多个操作构成一个逻辑工作单元时,这种方式很有用。

它也带来了一项新的责任:环境必须控制生成的代码可以调用哪些函数。

4. 执行反馈循环

可执行动作最有意思的特点之一,是能够观察运行时反馈。

智能体不必在生成代码后就停下来。它可以执行代码、检查结果,再根据观察到的信息决定下一步做什么。

生成 → 执行 → 观察 → 修订

来看这个例子。

第一次尝试假设某个字段存在:

response = fetch_customer()

print(response["customer_name"])

假设执行时返回了 KeyError。

智能体可以检查返回的数据结构:

response = fetch_customer()

print("Available fields:", list(response.keys()))

它可能会发现,这个字段实际叫作 name。

下一次尝试就可以适配实际的数据结构:

response = fetch_customer()

customer_name = response.get(
    "customer_name",
    response.get("name", "Unknown")
)

print(customer_name)

这展示了执行反馈如何指导后续动作。

这并不意味着模型会从每一次错误中永久学到东西。错误会成为一条观察信息,为当前任务的下一步提供依据。

一个简化的智能体循环

task = "Retrieve and analyze customer data"

while not task_is_complete(task):
    code = llm.generate_code(
        task=task,
        observations=get_observations()
    )

result = sandbox.execute(code)

record_observation(result)

if result.error: task = update_task_with_error( task, result.error )

print(get_final_answer())


这是概念性伪代码,并非研究论文中描述的具体实现。

生产系统需要明确的终止条件、执行限制、观测结果处理机制,以及防止无限重试的保护措施。

## 5. 研究人员发现了什么?

论文提出了 M³ToolEval,这是一个用于评估工具使用能力的基准,涵盖需要使用多个工具、进行多轮交互的任务。

研究人员评估了 17 种不同的 LLM,以研究可执行代码动作如何影响智能体的表现。

论文报告的改进幅度最高达到:

- 任务成功率提升 20%
- 在所报告的实验中,动作数量减少 30%

这些是论文报告的最大改进幅度,并不意味着所有模型、基准或任务都能获得同样的收益。

研究结果表明,智能体表示和执行动作的方式,可能显著影响其完成复杂任务的能力。

这里的启示并不只是 Python 比 JSON 更好。

更重要的是,可执行代码提供了灵活的动作空间,让智能体能够协调操作、复用中间结果,并表达条件逻辑。

对于需要执行多个相互依赖的操作的任务,这种灵活性可以减少显式编排的工作量。

## 6. CodeActAgent 和 CodeActInstruct

这项研究还推出了支持这一方法的相关资源。

CodeActAgent 展示了一种智能体架构,通过可执行代码与工具及执行环境交互。

CodeActInstruct 是一个包含约 7,000 条多轮交互的数据集,旨在支持训练模型使用代码作为动作格式。

研究还包含基于 Llama 2 和 Mistral 的模型,探索如何训练模型生成可执行动作,而不是完全依赖传统的工具调用格式。

这很有意义,因为这项工作同时研究了采用这一方法所需的架构和模型行为。

可以在 GitHub 上查看 CodeAct 的官方实现。

## 7. CodeAct 与 MCP:天然的组合?

MCP 提供了一种标准化方式,让 AI 应用能够发现并调用外部服务器提供的工具。

但能够访问大量工具,并不自动意味着智能体可以高效地组合使用它们。

假设一个智能体可以使用以下工具:

search_codebase(query) read_file(path) find_references(symbol) get_file_structure(path)


传统智能体可以逐个调用这些工具。

受 CodeAct 启发的智能体则可以通过程序协调它们:

query = "GET_CREDIT_CARD_DETAIL_DOCUMENT"

matches = search_codebase(query)

investigation = []

for match in matches: file_path = match["file"]

source = read_file(file_path)

investigation.append({ "file": file_path, "match": match, "source_excerpt": source })

print(investigation)


上面的代码假设这些工具返回的数据结构彼此兼容。

需要明确区分:

- MCP 标准化了工具的提供和调用方式。
- CodeAct 探索的是使用可执行代码作为智能体动作的格式。
- 编排框架负责管理执行、状态、权限,以及智能体更完整的生命周期。

这些理念可以相互补充,但不能互相替代。

受 CodeAct 启发的架构可以将 MCP 工具作为构建模块,并生成代码来协调它们。

## 8. 开发者智能体的实际示例:从端点追踪到前端页面

考虑一个银行应用,其架构包含前端、GraphQL、服务于前端的后端(BFF),以及多个微服务。

给定一个服务端点,找出哪些前端页面依赖它。

一种有效的排查方式是沿着以下链路追踪:

REST endpoint ↓ Backend service ↓ BFF service or resolver ↓ GraphQL operation ↓ Frontend hook or data layer ↓ Component ↓ Screen


受 CodeAct 启发的智能体可以组合使用代码仓库搜索工具,追踪这些关系。

endpoint = "/creditcards"

service_matches = search_codebase(endpoint)

graphql_operations = set()

for match in service_matches: operations = find_related_graphql_operations( match["file"], match["line"] )

graphql_operations.update(operations)

screens = set()

for operation in graphql_operations: consumers = find_frontend_consumers(operation)

screens.update(consumers)

print({ "endpoint": endpoint, "graphql_operations": sorted(graphql_operations), "screens": sorted(screens) })


这里的搜索和追踪函数是假设存在的工具,并非 CodeAct 的内置函数。

当结果不完整时,智能体可以进一步展开排查。

例如,它可以搜索某个操作的名称,检查匹配到的文件,然后沿着导入关系追踪到前端。

operation = "GET_CREDIT_CARD_DETAIL_DOCUMENT"

matches = search_codebase(operation)

frontend_files = []

for match in matches: if match["path"].startswith("apps/"): frontend_files.append(match["path"])

elif match["path"].startswith("libs/"): frontend_files.append(match["path"])

unique_files = sorted(set(frontend_files))

print(unique_files)


这个简化示例仅按路径筛选搜索结果。实际实现需要理解代码仓库的结构,区分声明与使用位置,并追踪导入关系和数据依赖。

### 一种可能的排查流程

flowchart TD A[User provides endpoint] --> B[Search repository] B --> C[Find service implementation] C --> D[Trace BFF and resolver] D --> E[Find GraphQL operation] E --> F[Find frontend consumers] F --> G{Evidence complete?} G -- No --> H[Generate another search action] H --> B G -- Yes --> I[Return evidence-backed report]


这展示了一种可能的、受 CodeAct 启发的架构,并非论文中实现或评估过的工作流。

其价值在于,智能体能够动态组合现有的搜索能力,无须为每个端点单独编写硬编码的工作流。

不过,CodeAct 并不能替代代码索引、语义搜索或可靠的代码仓库导航能力。对于大型代码库,这些能力仍然必不可少。

## 9. 并行操作与数据聚合

有些排查任务包含可以并行执行的独立操作。

例如,智能体可以在前端、BFF 和共享库中搜索同一个操作。

import asyncio

async def investigate_repository(repository, query): return await search_repository_async( repository, query )

async def investigate_all(query): repositories = [ "frontend", "bff", "shared-libraries" ]

tasks = [ investigate_repository(repository, query) for repository in repositories ]

results = await asyncio.gather(*tasks)

return { repository: result for repository, result in zip( repositories, results ) }

results = await investigate_all( "GET_CREDIT_CARD_DETAIL_DOCUMENT" )

print(results)


这是一个示意性示例,假设工具函数支持异步调用,且执行环境支持顶层 await。

CodeAct 不会自动让工具调用并行执行。生成的程序、运行时和可用接口都必须支持并发。

当操作相互独立时,并行执行可以降低延迟,但也需要合理的并发限制、错误处理和资源管理。

## 10. CodeAct 会取代传统工具调用吗?

当操作简单、定义明确,并且需要严格校验参数时,传统工具调用仍然很有用。

当任务涉及以下情况时,可执行代码会更具吸引力:

- 多个相互依赖的操作
- 条件执行或重复执行
- 工具之间的数据转换
- 复杂的多步骤排查

混合设计可以对定义明确的操作使用结构化工具调用,在需要组合多个操作时使用基于代码的编排。

A structured tool provides a trusted operation.

account = get_account(account_id)

Generated code handles task-specific processing.

if account["status"] == "active": transactions = get_transactions(account_id)

result = summarize_transactions( transactions ) else: result = { "message": "Account is not active" }

print(result)


工具层可以保留访问控制和输入校验,而智能体则使用代码来协调任务。

最合适的架构取决于任务、可用工具、模型,以及所需的安全保障。

## 11. 安全挑战

赋予智能体执行代码的能力,会提高它的灵活性,但也会引入风险。

生成的代码不得不受限制地访问宿主机、生产数据库或敏感文件系统。

生产环境中的实现应考虑:

执行时间和内存限制

受限的文件系统和网络访问

明确的工具权限

对敏感操作的校验

高影响操作的审批要求

一个假设的沙箱接口可能如下所示:

result = sandbox.execute( code=generated_code, timeout_seconds=10, network_access=False, filesystem_access="restricted" )


这只是用于说明的 API,并非真实的 CodeAct 函数。实际的安全控制措施取决于执行平台。

核心原则很简单:

让智能体灵活选择完成任务的方式,同时严格限定它被允许执行的操作。

代码执行应当相互隔离、可观测,并受明确的权限约束。

## 12. CodeAct 能解决什么,又不能解决什么

CodeAct 并不能全面解决智能体面临的所有问题。

它不会自动提供:

可靠的代码库索引

正确的工具实现

从以往失败中持续学习的能力

任务完成保证

默认安全的执行环境

这种方法改变了智能体可用的动作空间。结果的质量仍然取决于模型、工具、执行环境以及任务的评估方式。

在决定是否将 CodeAct 应用于实际应用时,明确这一区别非常重要。

## 结论:更强大的智能体可能需要更好的行动方式

CodeAct 的吸引力并不只是让 LLM 能够编写 Python。模型生成代码的能力已经存在多年。

更重要的理念是,将可执行代码作为 AI 智能体的通用动作格式。

我们可以为智能体提供一组能力,让它们将这些能力组合成可执行的工作流,而不必提前设计每一种可能的工具调用序列。

这项研究提供了实验证据,表明这种方法能够提升某些多工具任务的表现,同时减少所需的动作次数。

对于构建 MCP 集成、智能体编排平台以及 AI 驱动的开发工具的开发者而言,CodeAct 提供了一个有价值的架构视角。

也许,构建更强大智能体的下一步,并不只是增加更多工具。

也许,我们需要让智能体更好地使用它们已经拥有的工具。

原始研究论文:可执行代码动作催生更出色的 LLM 智能体

GitHub 上的 CodeAct 实现

如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。
Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
128GB 苹果芯片 Mac 的 oMLX 部署调优
下一篇
实测 agent-hooks 在执行前拦截超额退款