Agent 脚本开发指南

结合 Agent 脚本执行工具与 Sandbox 沙箱服务,开发可在 Agent 对话中运行的 Python / JavaScript 脚本

概述

EasyAI 平台支持在 Agent 对话中执行用户脚本,实现数据处理、数学计算、API 调用等能力。该能力由两部分组成:

  1. Agent 脚本执行工具:在 Agent 创建时启用 enable_script_execution 后,模型可获得 execute_script 工具,用于调用沙箱执行代码
  2. Sandbox 沙箱服务:独立的执行环境容器,负责在隔离环境中运行 Python 和 JavaScript 代码

架构说明

┌─────────────────────────────┐
│  业务服务 (easyai-backend)   │
│  Agent / OpenAI API         │
│                             │
│  execute_script 工具        │
└──────────────┬──────────────┘
               │ HTTP POST /execute
               ▼
┌─────────────────────────────┐
│  Sandbox 沙箱服务            │  ← 独立容器 (sandbox 项目)
│  (Python FastAPI)           │
│                             │
│  ├─ Python 执行器            │
│  ├─ JavaScript 执行器        │
│  └─ 资源/超时控制            │
└──────────────┬──────────────┘
               │
               ▼
      Python 3.12 / Node.js 运行时

前置条件

1. 配置沙箱服务

在业务服务(easyai-backend)的环境变量中配置沙箱地址:

# .env 或环境变量
SANDBOX_SERVICE_BASE_URL=http://localhost:8000

生产环境需填写实际沙箱服务地址(如 http://sandbox:8000)。

2. 启动 Sandbox 服务

Sandbox 项目为独立 Python 服务,需单独启动:

# 进入 sandbox 项目
cd sandbox

# 安装依赖
pip install -r requirements.txt
npm install

# 启动服务(默认 8000 端口)
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000

Docker 部署时,Sandbox 通常以单独容器运行,通过 Docker 网络与业务服务互通。

3. 启用 Agent 脚本执行

在创建/编辑 Agent 时,将 features.enable_script_execution 设为 true。此时模型会获得 execute_script 工具,并可在对话中调用。


脚本开发规范

支持的语言

语言取值说明
PythonpythonPython 3.12
JavaScriptjavascriptjsNode.js,支持 CommonJS 与 ESM

返回值约定

脚本的执行结果通过以下方式返回,按优先级:

  1. 入口函数:若定义了 mainrunhandler,则调用 entry(args) 的返回值作为 data
  2. result 变量:若无入口函数,使用脚本中的变量 result

入口函数优先级main > run > handler

多函数情况:若脚本中仅有一个顶层函数,会自动将该函数作为入口;若多个函数并存,需在请求中通过 entry 指定入口函数名。

参数传递

请求体中的 args 数组会注入到脚本中,脚本内通过变量 args 访问:

  • Python:args 为 list
  • JavaScript:args 为数组,若无参数则可能是 []undefined

沙箱 API 说明

POST /execute

执行脚本的统一接口。

请求体

{
  "language": "python",
  "code": "def main(args):\n    return sum(args)",
  "timeout": 5000,
  "memory": 256,
  "args": [1, 2, 3, 4],
  "entry": "main"
}
字段类型必填说明
languagestringpythonjavascript
codestring要执行的源代码
timeoutnumber超时时间(毫秒),默认 5000,范围 100–60000
memorynumber内存限制(MB),默认 256
argsarray传给脚本的参数,支持数字、字符串、对象等
entrystring入口函数名,默认 main

响应体

{
  "ok": true,
  "stdout": "",
  "stderr": "",
  "data": 10,
  "message": ""
}
字段说明
ok是否执行成功
stdout标准输出
stderr标准错误
data脚本返回结果(入口函数返回值或 result 变量)
message错误或附加说明

技能脚本(SkillScript)

可在「技能」中预置脚本,供开启脚本执行的 Agent 调用。技能脚本会出现在 Agent 的指令中,模型可根据描述选择并调用。

脚本结构(在技能中配置):

{
  "name": "求和计算",
  "description": "计算一组数字的和",
  "language": "python",
  "code": "def main(args):\n    return sum(args)"
}
字段说明
name脚本名称(标识符)
description描述,帮助模型理解用途
languagepythonjavascript
code脚本源码

示例脚本

Python 示例

1. 使用 result 变量

result = 1 + 2

2. 使用 main 函数

def main(args):
    return args[0] * args[1]
# args = [6, 7] 时返回 42

3. 使用 run 作为入口

def run(args):
    return sum(args)
# args = [1, 2, 3, 4] 时返回 10

4. 主函数调用子函数

def add(a, b):
    return a + b

def main(args):
    return add(args[0], args[1])

5. 使用标准库

import json

def main(args):
    return json.dumps(args)

6. 使用 math

import math

def main(args):
    return round(math.sqrt(args[0]), 2)
# args = [2] 时返回 1.41

7. 读取配置文件(data 目录)

import json

with open('data/model_config.json') as f:
    cfg = json.load(f)

def main(args):
    return {'model': cfg['name'], 'output_dir': cfg['output_dir']}

JavaScript 示例

1. 使用 result 变量

result = [1, 2, 3].length;

2. 使用 main 函数

function main(arr) {
  return arr.reduce((a, b) => a + b, 0);
}
// args = [1, 2, 3, 4] 时返回 10

3. 使用 handler 作为入口

function handler(a) {
  return a[0] + a[1];
}
// 请求中需指定 "entry": "handler"

4. 使用 lodash(需先安装)

const _ = require('lodash');

function main(arr) {
  return _.sum(arr);
}

5. 使用 dayjs(需先安装)

const dayjs = require('dayjs');

function main() {
  return dayjs().format('YYYY-MM-DD');
}

6. ESM import

import _ from 'lodash';

function main(arr) {
  return _.sum(arr);
}

依赖管理

查看已安装包

curl -s http://localhost:8000/packages

返回 Python 与 Node 的系统包和自定义包列表及版本。

安装 Python 包

curl -X POST http://localhost:8000/install \
  -H "Content-Type: application/json" \
  -d '{"package_manager":"python","packages":["requests==2.32.0","numpy"]}'

安装 Node 包

curl -X POST http://localhost:8000/install \
  -H "Content-Type: application/json" \
  -d '{"package_manager":"node","packages":["dayjs@1.11.10"]}'

卸载包(仅卸载自定义目录中的包)

curl -X POST http://localhost:8000/uninstall \
  -H "Content-Type: application/json" \
  -d '{"package_manager":"python","packages":["requests"]}'

沙箱默认已预装部分常用库(如 lodash、axios、dayjs 等),详见 sandbox 项目的 package.json 和镜像内 Python 环境。


沙箱脚本生成文件与下载

脚本可将生成的文件写入沙箱的 data/output 目录,随后通过沙箱服务的 /download 接口下载。

写入输出目录

脚本执行时工作目录为沙箱项目根目录。将文件写入 data/output 或其子目录即可供下载:

Python 示例

def main(args):
    output_path = 'data/output/result.csv'
    with open(output_path, 'w') as f:
        f.write('name,value\na,1\nb,2')
    return {'output': output_path, 'message': '文件已生成'}

JavaScript 示例

const fs = require('fs');

function main(args) {
  const outputPath = 'data/output/result.json';
  fs.writeFileSync(outputPath, JSON.stringify(args));
  return { output: outputPath, message: '文件已生成' };
}

下载接口

沙箱服务提供 GET /download/{path:path},可下载 data/output 下的文件:

# 下载 data/output 下的文件(path 为 output 下的相对路径)
curl -O "http://localhost:8000/download/result.csv"
# 或带子目录
curl -O "http://localhost:8000/download/2024/01/report.png"
说明
pathdata/output 下的相对路径,如 result.csvsubdir/file.txt
仅允许访问 data/output 目录内文件,禁止路径穿越

下载后同步到文档

若需将沙箱生成的内容同步到本开发文档(easyai-doc/content/4.develop/3.script-development.md),建议流程:

  1. 使用 /download 或浏览器访问沙箱下载地址获取生成文件
  2. 将需要纳入文档的片段复制到 3.script-development.md 的对应章节(如示例脚本、输出说明等)
  3. 提交文档变更到版本库

注意事项

超时

  • 默认超时 5 秒,可通过 timeout 调整
  • 超时后脚本会被终止,返回 ok: falsemessage 含「执行超时」

转义

Agent/LLM 传入的代码可能包含 \\n\\" 等转义序列。沙箱服务会在执行前将其还原为真实字符,无需在脚本中重复转义。

安全

  • 脚本在沙箱容器内执行,与业务服务隔离
  • 建议对敏感操作、文件访问、网络请求做好限制
  • 生产环境建议使用 Docker 或类似方案隔离沙箱

Agent 工具返回格式

execute_script 工具会将沙箱返回结果序列化为 JSON 字符串返回给模型,格式为:

{"ok":true,"stdout":"","stderr":"","data":<结果>,"message":""}

模型会据此理解执行成功与否及返回数据。


相关项目

  • easyai-backend:业务服务,内含 SandboxServiceexecute_script 工具实现
  • sandbox:独立沙箱执行服务,提供 /execute/download/install/uninstall/packages 等接口

更详细的沙箱设计说明见 sandbox 项目中的 脚本执行沙箱服务设计.md