更新时间:2026-02-06 GMT+08:00
分享

基于函数创建插件

在AgentArts智能体平台中,当官方插件市场无法满足特定业务需求时,开发者需要自主创建插件。根据实现机制与运行形态的不同,自定义插件主要分为“API类型插件”和“函数类型插件”两种形态。API型插件介绍及创建请参考基于API创建插件

前提条件

函数形式插件

函数类型插件是指直接在AgentArts智能体平台中编写并运行的一段代码脚本(Python3.9或Node.js14.18脚本),它不依赖外部服务器,而是利用平台提供的算力即时执行。

典型适用场景:

  • 精确计算:利息计算、日期推算(下周三是几号)、单位换算。
  • 逻辑校验:身份证/手机号正则校验、JSON 格式修复。
  • 数据清洗:数据进行去重、排序、过滤。

不适用场景:大规模数据存储、重型计算(如视频渲染)、复杂的持久化状态管理。

插件调用链路:

  1. 用户输入:修复这段JSON:{'name': '张三', age: 25,}。
  2. Agent分析:Agent识别用户意图为“JSON修复”,命中代码插件fix_json_format。
  3. 参数生成:模型提取用户提供的原始文本,生成入参:{ "raw_text": "{'name': '张三', age: 25,}" }。
  4. 沙箱启动:Agent启动一个隔离的 Python 运行环境(Sandbox)。
  5. 代码执行:加载用户编写的修复逻辑,代码尝试解析并重新序列化数据,确保输出符合标准JSON规范。
  6. 返回结果:代码运行结束,返回结构化结果:{ "is_valid": true, "formatted_json": "{\"name\": \"张三\", \"age\": 25}" }。
  7. 最终回复:模型根据代码返回的结果,向用户输出:“已为您修复 JSON 格式,修复后的内容如下...”。

创建插件的流程

函数型插件是直接在平台提供的沙箱环境中的一段脚本代码,本文将直接通过具体示例进行演示,助您快速上手。

序号

流程环节

说明

1

创建插件

在函数插件中,“插件”仅作为管理和分类的容器,实现对同类工具的管理。

2

创建工具

创建工具

工具真正干活的实体。每一个工具都对应一个独立的函数实例。代码逻辑、依赖包、入参出参定义全部都在这里配置。

创建自定义依赖包(可选)

支持使用Python3.9或Node.js14.18创建工具代码。为了保持轻量和安全,平台只提供最基础的语言环境,即除了Python3.9、Node.js14.18本身自带的标准库外,其余依赖包均需要手动上传。

示例1

文本相似度计算插件,基于Python,不需上传依赖包。

示例2

网页HTML内容清洗插件(需上传依赖包),基于Python,需上传依赖包。

示例3

创建Python依赖包

附录1

Python编码规范

附录2

Node.js编码规范

示例1:文本相似度计算插件

该插件的主要作用是接收两个文本输入(text1 和 text2),并通过以下三种算法之一计算它们的相似程度(0.0 到 1.0 之间):

  • Cosine (余弦相似度):默认算法。通过词频向量计算文本在语义/内容上的重合度。
  • Jaccard (杰卡德相似系数):计算两个文本中相同字符(token)在总字符中的占比,适合集合重合度计算。
  • Edit Distance (编辑距离):计算将一个文本变成另一个文本需要变动多少字符,适合检测拼写错误或短文本的字面差异。

同时配置了停用词表(DEFAULT_STOPWORDS)、预处理配置(PREPROCESS_CONFIG)、文本预处理(preprocess_text)单元。

  • 停用词表:定义了一组常见的无实际意义的词(如“的”、“了”、“是”等),用于过滤。
  • 预处理配置:转小写;去除标点符号(只保留汉字、字母、数字);去除停用词;切分粒度。
  • 文本预处理:清洗:将文本转为小写,并使用正则表达式;分词:将文本打散成字符列表;过滤:移除在停用词表中的字符。

文本相似度计算插件创建步骤如下:

  1. 登录AgentArts智能体平台,在左侧导航栏“个人空间”区域,选择目标空间。
  2. 在左侧导航栏中选择“开发中心 > 组件库”,在“插件”页签,单击页面右上角“创建插件”。
  3. 选择“函数类型”类型的插件,然后根据以下步骤配置插件信息。

    表1 基本信息

    参数

    说明

    示例

    插件类型

    根据实现机制与运行形态的不同,插件分为“API类型”和“函数类型”两种形态。

    函数类型

    插件图标

    单击默认图标按钮,可上传本地图片作为插件的自定义图标。

    支持jpg、jpeg、png格式,不超过200KB。

    系统默认图标

    展示名称

    用于标识当前插件,在“组件库 > 插件”页面会展示该名称。

    命名规则:按照插件的实际功能命名,有助于Agent进行插件的精准识别和调度。

    命名要求:可以包含中文、英文、数字、特殊字符等;

    长度限制:1~64个字符。

    文本相似度计算

    名称

    插件的英文名称。

    命名规则:按照插件的实际功能命名,有助于Agent进行插件的精准识别和调度。

    命名要求:字母、数字和下划线(_)的组合,不允许使用其他特殊字符或空格;

    长度限制:1~64个字符。

    Text_similarity_calculation

    描述

    描述当前插件的类型、功能和适用场景。

    需要按照插件的实际功能填写描述,有助于Agent进行插件的精准识别和调度。

    使用 Python 内置库(re/math/difflib)计算两段文本的相似度(适配 Agent 意图匹配、问答匹配、文本查重等场景)。

  4. 配置完单击“确定”。

    平台会自动跳转至工具信息页面,请参考后续步骤创建工具,在创建工具阶段会配置代码脚本、输入、输出参数等信息。

  5. 在“工具信息”页面,单击“创建工具”,在“添加工具”弹窗单击添加函数。

    图1 添加函数

  6. 填写函数名称与描述。

    表2 函数基本信息

    参数

    填写示例

    名称

    Text_similarity_calculation

    描述

    使用 Python 内置库(re/math/difflib)计算两段文本的相似度(适配 Agent 意图匹配、问答匹配、文本查重等场景)。

  7. 设置函数的输入、输出参数。

    输入参数为2个待识别的文本,分别为text1、text2。

    输出参数在本次示例代码中,定义在body参数中,因此需要新增一个body参数。返回的JSON体会包含 similarity(相似度数值)。
    图2 设置输入、输出参数

  8. 执行语言选择“Python3.9”,复制如下代码脚本。

    当前平台已经支持AI写作代码功能,在后续使用过程中,填写好名称、描述、输入、输出参数后,可以使用AI模型自动写代码。

    # -*- coding:utf-8 -*-
    import json
    import base64
    import re
    import math
    import difflib
    
    # ===================== 平台官方函数(请勿修改) =====================
    def extractRequestParam(rawValue, encoded, defaultValue):
        """平台提供的参数解析函数,处理Base64编码和JSON解析"""
        if encoded and rawValue:
            try:
                rawValue = str(base64.b64decode(rawValue), "utf-8")
            except:
                rawValue = ""
        try:
            # 如果rawValue本身已经是dict(防止平台有时自动解析),直接返回
            if isinstance(rawValue, dict):
                return rawValue
            return json.loads(rawValue) if rawValue else defaultValue
        except:
            return defaultValue
    
    # ===================== 全局配置 =====================
    DEFAULT_STOPWORDS = {
        "的", "了", "是", "我", "你", "他", "她", "它", "们", "在", "有", "就", 
        "不", "和", "也", "都", "这", "那", "此", "彼", "之", "于", "及", "与",
        "哦", "啊", "呢", "吧", "吗", "哈", "哎", "哼", "嗨", "喂", "嗯", "一个",
        "一些", "一点", "一般", "一样", "怎么", "怎么样", "哪里", "什么", "多少"
    }
    DEFAULT_ALGORITHM = "cosine"
    PREPROCESS_CONFIG = {
        "lowercase": True,
        "remove_punctuation": True,
        "remove_stopwords": True,
        "split_granularity": "char"
    }
    
    # ===================== 文本处理工具函数 =====================
    def preprocess_text(text: str, config: dict = None) -> list:
        if text is None:
            text = ""
        config = config or PREPROCESS_CONFIG
        text = str(text).strip()
    
        if config.get("lowercase", True):
            text = text.lower()
        if config.get("remove_punctuation", True):
            text = re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\s]", "", text)
        if config.get("split_granularity", "char") == "char":
            tokens = list(text)
        else:
            tokens = text.split()
        if config.get("remove_stopwords", True):
            tokens = [t for t in tokens if t and t not in DEFAULT_STOPWORDS]
        return tokens
    
    def cosine_similarity(vec1: list, vec2: list) -> float:
        if not vec1 or not vec2:
            return 0.0
        dot_product = sum(v1 * v2 for v1, v2 in zip(vec1, vec2))
        norm1 = math.sqrt(sum(v * v for v in vec1))
        norm2 = math.sqrt(sum(v * v for v in vec2))
        if norm1 == 0 or norm2 == 0:
            return 0.0
        return round(dot_product / (norm1 * norm2), 4)
    
    def jaccard_similarity(tokens1: list, tokens2: list) -> float:
        set1 = set(tokens1)
        set2 = set(tokens2)
        intersection = len(set1 & set2)
        union = len(set1 | set2)
        return round(intersection / union, 4) if union != 0 else 0.0
    
    def edit_distance_similarity(text1: str, text2: str) -> float:
        text1 = str(text1).strip() if text1 is not None else ""
        text2 = str(text2).strip() if text2 is not None else ""
        return round(difflib.SequenceMatcher(None, text1, text2).ratio(), 4)
    
    # ===================== 平台入口函数 =====================
    def handler(event, context):
        """
        平台标准入口函数(核心)
        """
        # 1. 初始化返回结构
        result = {
            "headers": {"Content-Type": "application/json; charset=utf-8"},
            "body": "",
            "code": 200,
            "error": ""
        }
    
        try:
            # 2. 智能提取参数
            isBase64Encoded = event.get('isBase64Encoded', False)
    
            # 尝试从 body 获取 (标准HTTP模式)
            body_params = extractRequestParam(event.get('body'), isBase64Encoded, {})
    
            # 定义可能的参数来源列表,优先级:
            # 1. event['body'] 解析后的字典
            # 2. event 本身 (直接传参模式/测试模式)
            # 3. event['body'] 内部可能嵌套的 'body' (兼容错误嵌套)
            potential_sources = [body_params, event]
    
            if isinstance(body_params, dict):
                 potential_sources.append(body_params.get("body", {}))
    
            # 3. 遍历来源寻找 text1 和 text2
            text1 = ""
            text2 = ""
            algorithm = DEFAULT_ALGORITHM
    
            for source in potential_sources:
                if not isinstance(source, dict):
                    continue
                # 只要找到非空的 text1 就认为找到了正确的数据源
                if "text1" in source and source["text1"]:
                    text1 = source.get("text1", "").strip()
                    text2 = source.get("text2", "").strip()
                    algorithm = source.get("algorithm", algorithm).strip()
                    break # 找到后立即停止
    
            # 4. 调试打印 (保留以便查错)
            print(f"解析结果: text1={text1}, text2={text2}, algo={algorithm}")
    
            # 5. 非空校验
            if not text1 or not text2:
                # 只有当所有来源都找不到时才报错
                raise ValueError(f"text1/text2为空!请检查传参格式。收到event结构: {list(event.keys())}")
    
            # 6. 计算相似度
            algorithm = algorithm.lower()
            if algorithm == "jaccard":
                tokens1 = preprocess_text(text1)
                tokens2 = preprocess_text(text2)
                similarity = jaccard_similarity(tokens1, tokens2)
                used_algorithm = "jaccard"
            elif algorithm == "edit_distance":
                similarity = edit_distance_similarity(text1, text2)
                used_algorithm = "edit_distance"
            else:
                tokens1 = preprocess_text(text1)
                tokens2 = preprocess_text(text2)
                vocab = {token: idx for idx, token in enumerate(set(tokens1 + tokens2))}
                vec1 = [tokens1.count(token) for token in vocab]
                vec2 = [tokens2.count(token) for token in vocab]
                similarity = cosine_similarity(vec1, vec2)
                used_algorithm = "cosine"
    
            # 7. 组装成功响应
            # 注意:这里必须是 JSON 字符串,因为外层 result["body"] 要求是字符串
            response_body = json.dumps({
                "similarity": str(similarity),
                "status": "success",
                "used_algorithm": used_algorithm,
                "confidence": str(similarity),
                "error_msg": ""
            }, ensure_ascii=False)
    
            result["body"] = response_body
            result["code"] = 200
    
        except Exception as e:
            # 8. 组装错误响应
            error_body = json.dumps({
                "similarity": "0.0",
                "status": "failed",
                "used_algorithm": "",
                "confidence": "0.0",
                "error_msg": f"计算失败:{str(e)}"
            }, ensure_ascii=False)
    
            result["body"] = error_body
            result["code"] = 500
            result["error"] = str(e)
    
        # 9. 返回
        return json.dumps(result)

  9. 代码填写完成后,单击“确定”。返回“添加工具”弹窗,选择刚创建好的函数。单击右下角“确定”完成工具的创建。

    图3 添加函数

  10. 在“工具列表”页面,单击“调试”按钮,输入参数值,单击“开始调测”检查调测结果。

    在本示例中,输入text1、text2文本后,返回的body体中已经包含similarity(相似度数值)。
    图4 工具调试

  11. 调试成功后,工具状态随之变为“成功”,此时可单击右上角“发布”,发布插件。

    只有经过发布的插件可以给智能体使用。

示例2:网页HTML内容清洗插件

该插件的主要作用是解析和清洗网页HTML内容,该插件主要实现了以下功能。

  • 标签过滤:强制移除 script (JS脚本), style (CSS样式), meta, iframe (广告/视频), svg 等非文本标签。
  • 注释移除:删除HTML注释(往往包含无用信息)。
  • 安全机制:代码中有一个逻辑 if len(tag.get_text()) < 200。只有当这些区域字数很少时才删除。防止误删了被错误标记为 class="content-sidebar" 的正文长文。

由于不同的网页HTML内容与样式千差万别,本示例仅作为功能演示使用。正式场景中,一般会对HTML网页样式订制专属的清洗策略。

网页HTML内容清洗插件创建步骤如下:

  1. 登录AgentArts智能体平台,在左侧导航栏“个人空间”区域,选择目标空间。
  2. 在左侧导航栏中选择“开发中心 > 组件库”,在“插件”页签,单击页面右上角“创建插件”。
  3. 选择“函数类型”类型的插件,然后根据以下步骤配置插件信息。

    表3 基本信息

    参数

    说明

    示例

    插件类型

    根据实现机制与运行形态的不同,插件分为“API类型”和“函数类型”两种形态。

    函数类型

    插件图标

    单击默认图标按钮,可上传本地图片作为插件的自定义图标。

    支持jpg、jpeg、png格式,不超过200KB。

    系统默认图标

    展示名称

    用于标识当前插件,在“组件库 > 插件”页面会展示该名称。

    命名规则:按照插件的实际功能命名,有助于Agent进行插件的精准识别和调度。

    命名要求:可以包含中文、英文、数字、特殊字符等;

    长度限制:1~64个字符。

    网页HTML内容清洗

    名称

    插件的英文名称。

    命名规则:按照插件的实际功能命名,有助于Agent进行插件的精准识别和调度。

    命名要求:字母、数字和下划线(_)的组合,不允许使用其他特殊字符或空格;

    长度限制:1~64个字符。

    WebHtmlParser

    描述

    描述当前插件的类型、功能和适用场景。

    需要按照插件的实际功能填写描述,有助于Agent进行插件的精准识别和调度。

    解析网页HTML源码,支持智能清洗并提取正文文本。它能自动过滤脚本、样式及广告噪音,将杂乱代码转换为结构化数据。

  4. 配置完单击“确定”。

    平台会自动跳转至工具信息页面,请参考后续步骤创建工具,在创建工具阶段会配置代码脚本、输入、输出参数等信息。

  5. 在“工具信息”页面,单击“创建工具”,在“添加工具”弹窗单击添加函数。

    图5 添加函数

  6. 填写函数名称与描述。

    表4 函数基本信息

    参数

    填写示例

    名称

    WebHtmlParser

    描述

    解析网页HTML源码,支持智能清洗并提取正文文本。它能自动过滤脚本、样式及广告噪音,将杂乱代码转换为结构化数据。

  7. 设置函数的输入、输出参数。

    输入参数为content,表示待提取的网页文本。

    输出参数在本次示例代码中,定义在body参数中,因此需要新增一个body参数。返回的JSON体会包含清洗后的内容。

    图6 设置输入、输出参数

  8. 执行语言选择“Python3.9”,复制如下代码脚本。

    当前平台已经支持AI写作代码功能,在后续使用过程中,填写好名称、描述、输入、输出参数后,可以使用AI模型自动写代码。

    本示例中会使用Python的beautifulsoup4依赖包,打包上传方法请参见示例3:创建Python依赖包

    # -*- coding:utf-8 -*-
    import json
    import base64
    import re
    # 依赖包:beautifulsoup4 (需打包上传)
    from bs4 import BeautifulSoup, Comment
    
    # ===================== 平台官方函数 =====================
    def extractRequestParam(rawValue, encoded, defaultValue):
        if encoded and rawValue:
            try:
                rawValue = str(base64.b64decode(rawValue), "utf-8")
            except:
                rawValue = ""
        try:
            if isinstance(rawValue, dict):
                return rawValue
            return json.loads(rawValue) if rawValue else defaultValue
        except:
            return defaultValue
    
    # ===================== 业务逻辑工具函数 =====================
    def clean_text(soup):
        """
        深度清洗 HTML,提取纯净文
        """
        # 1. 移除脚本、样式、元数据
        for tag in soup(["script", "style", "meta", "head", "input", "iframe", "noscript", "svg", "link"]):
            tag.extract()
    
        # 2. 移除注释
        for comment in soup.find_all(text=lambda text: isinstance(text, Comment)):
            comment.extract()
    
        # 3. (可选) 尝试移除常见的导航栏、页脚、侧边栏,减少噪音
        # 这一步比较激进,如果发现误删了正文,可以注释掉下面这几行
        for tag in soup.find_all(class_=re.compile(r'(nav|footer|header|sidebar|menu|copyright)', re.I)):
            # 只有当该区域文本很少时才删除,防止误删正文包含相应class的情况
            if len(tag.get_text()) < 200: 
                tag.extract()
    
        # 4. 获取文本,使用换行符分隔
        text = soup.get_text(separator='\n')
    
        # 5. 核心清洗逻辑:去除多余空行和空白字符
        lines = []
        for line in text.splitlines():
            clean_line = line.strip()
            # 只有当行内有内容时才保留
            if clean_line:
                lines.append(clean_line)
    
        # 用单个换行符连接,保证紧凑
        return '\n'.join(lines)
    
    def extract_links(soup, base_url=""):
        links = []
        seen = set()
        for a in soup.find_all('a', href=True):
            href = a['href'].strip()
            text = a.get_text(strip=True)
            if not href or href.startswith(('javascript:', '#', 'mailto:', 'tel:')):
                continue
            if base_url and not href.startswith(('http', '//')):
                base_url = base_url.rstrip('/')
                if href.startswith('/'):
                    href = base_url + href
                else:
                    href = base_url + '/' + href
    
            # 去重且去除无文字的空链接
            key = (text, href)
            if text and key not in seen:
                links.append({"text": text, "url": href})
                seen.add(key)
        return links
    
    def extract_images(soup, base_url=""):
        images = []
        seen = set()
        for img in soup.find_all('img', src=True):
            src = img['src'].strip()
            alt = img.get('alt', '').strip()
            if base_url and src and not src.startswith(('http', '//', 'data:')):
                base_url = base_url.rstrip('/')
                if src.startswith('/'):
                    src = base_url + src
                else:
                    src = base_url + '/' + src
    
            if src and src not in seen:
                images.append({"alt": alt, "src": src})
                seen.add(src)
        return images
    
    # ===================== 平台入口函数 =====================
    def handler(event, context):
        # 1. 初始化平台要求的返回结构
        result = {
            "headers": {"Content-Type": "application/json; charset=utf-8"},
            "body": "",
            "code": 200,
            "error": ""
        }
    
        try:
            # 2. 参数解析
            isBase64Encoded = event.get('isBase64Encoded', False)
            body_params = extractRequestParam(event.get('body'), isBase64Encoded, {})
    
            potential_sources = [body_params, event]
            if isinstance(body_params, dict):
                 potential_sources.append(body_params.get("body", {}))
    
            html_content = ""
            mode = "text"
            base_url = ""
    
            for source in potential_sources:
                if isinstance(source, dict) and ("content" in source or "html" in source):
                    html_content = source.get("content") or source.get("html", "")
                    mode = source.get("mode", "text")
                    base_url = source.get("base_url", "")
                    break
    
            if not html_content:
                html_content = "<html><body>错误:未检测到 content 参数。</body></html>"
    
            # 3. 业务处理
            soup = BeautifulSoup(html_content, 'html.parser')
            data = {}
    
            if mode == "links":
                data["links"] = extract_links(soup, base_url)
                data["count"] = len(data["links"])
            elif mode == "images":
                data["images"] = extract_images(soup, base_url)
                data["count"] = len(data["images"])
            elif mode == "summary":
                title = soup.title.string if soup.title else ""
                desc = ""
                meta = soup.find('meta', attrs={'name': 'description'}) or soup.find('meta', attrs={'property': 'og:description'})
                if meta: desc = meta.get('content', '')
                full_text = clean_text(soup)
                data["title"] = title.strip()
                data["description"] = desc.strip()
                data["summary_text"] = full_text[:800] + "..." if len(full_text) > 800 else full_text
            else: # text
                cleaned = clean_text(soup)
                data["cleaned_text"] = cleaned
                data["length"] = len(cleaned)
    
            # 4. 组装响应 (CRITICAL FIX: ensure_ascii=False)
            response_body = json.dumps({
                "status": "success",
                "mode": mode,
                "result": data
            }, ensure_ascii=False) 
    
            result["body"] = response_body
            result["code"] = 200
    
        except Exception as e:
            error_body = json.dumps({
                "status": "failed",
                "error_msg": str(e)
            }, ensure_ascii=False)
            result["body"] = error_body
            result["code"] = 500
            result["error"] = str(e)
    
        # 5. 返回最终结果 (CRITICAL FIX: ensure_ascii=False)
        return json.dumps(result, ensure_ascii=False)

  9. 添加Python依赖包,本示例中会使用Python的beautifulsoup4依赖包,打包上传方法请参见示例3:创建Python依赖包

    图7 添加依赖包

  10. 将获取的依赖包上传至平台后,单击“确定”完成工具的创建。

示例3:创建Python依赖包

除了Python3.9、Node.js14.18本身自带的标准库外,其余依赖包均需要手动上传。

本小节结合示例2:网页HTML内容清洗插件作为演示,介绍制作Python的beautifulsoup4依赖包。Python3.9、Node.js14.18的制作方法均可在平台中查询。

图8 获取依赖包制作方法
  1. 准备一台Huawei Cloud EulerOS 2.0环境的服务器。

    制作函数依赖包推荐在Huawei Cloud EulerOS 2.0环境中进行。 使用其他系统打包可能会因为底层依赖库的原因,运行出问题,比如找不到动态链接库。

    本示例中创建一台EulerOS镜像的弹性云服务器进行后续操作的演示(创建一台按需计费、最低规格1u1g、EulerOS镜像的服务器,使用完成即可删除释放)。

  2. 创建完成后,远程登录至该服务器(可使用弹性云服务器默认的CloudShell方式登录)。
  3. 依次执行以下命令,下载Python的beautifulsoup4依赖包,并将其压缩为zip包。

    # 1. 创建临时目录,用于存放beautifulsoup4依赖包,该依赖包缩写为bs4,创建相同名称的目录
    mkdir -p /tmp/bs4
    # 2. 安装依赖(自动包含soupsieve)
    pip install beautifulsoup4 --root /tmp/bs4
    # 进入临时目录
    cd /tmp/bs4
    # 查找 site-packages 路径(Linux 下通用命令)
    find . -name "site-packages"
    # 示例输出:./usr/local/lib/python3.9/site-packages
    # 进入找到的 site-packages 目录(替换为上面步骤中查询的实际路径)
    cd ./usr/local/lib/python3.9/site-packages
    # -r:递归打包(包含 bs4、soupsieve 等所有文件);-q:静默模式
    # 将包生成到 /tmp 目录,方便后续下载
    zip -rq /tmp/bs4.zip *
    

  4. 打包完成后即可在tmp路径下查询到bs4.zip文件,下载该依赖包。

    图9 下载依赖包

Python编码规范

本小节主要说明平台预置Python函数模板的结构、参数定义及开发规范。开发者需基于此模板编写业务逻辑,实现插件的具体功能。

预置代码主要包含三个部分:

  • 公共库引用说明:代码顶部的注释展示了如何使用平台内置的 common 库发起 HTTP 请求。
  • 辅助工具函数:extractRequestParam 用于处理参数的解包与格式转换。
  • 主入口函数:handler(event, context) 是插件执行的核心,包含业务逻辑。

主入口函数:

def handler(event, context):
    # ...
  • 约束:请勿修改函数名 handler。平台通过此名称定位并执行函数。
  • 参数:
    • event (Dict):包含本次调用的所有输入数据。
    • context (Object):运行时上下文对象,提供系统级能力。

输入参数:

event 对象中包含了经过 Base64 编码的原始数据。模板代码通过 extractRequestParam 函数自动完成了解码和 JSON 反序列化,开发者可直接使用以下变量:

表5 变量说明

变量名

含义

用途

inputData

用户业务参数

对应插件定义中用户填写的入参(如查询关键词、日期等)。

mssiAuthData

连接器鉴权数据

包含调用第三方 API 所需的 host, header 等鉴权信息(由平台连接器配置自动注入)。

dataExtendConfig

扩展配置

流程步骤中的高级配置参数(通常用于低代码编排场景)。

代码示例
# 获取用户输入的 "city" 参数
city_name = inputData.get("city", "city_name")

# 获取连接器配置的主机地址
api_host = mssiAuthData.get("host")

上下文与安全凭证:

context 提供与运行环境交互的能力。

context.getToken(): 获取当前执行环境的安全令牌(Security Token)。

用法:模板代码已自动将 Token 注入到 mssiAuthData["securityToken"] 中,通常用于身份验证。

发起网络请求:

平台预置了 common 模块用于处理网络请求。请勿使用 Python 原生 requests 库,建议使用 common.httpRequest 以确保兼容性和安全性。

入参:

  • url (str):请求完整地址。
  • headers (dict):请求头。
  • body (str/json):请求体。
  • method (str):请求方法 ("GET", "POST", etc.)。

返回值 (data) 结构:

{
    "code": 200,          # HTTP 状态码
    "body": "...",        # 响应体字符串
    "headers": {...},     # 响应头
    "error": "..."        # 错误信息(如有)
}

返回值规范:

函数最终必须返回一个 JSON 格式的字符串。

代码示例
result = {
    "status": "success",
    "message": "查询成功",
    "data": { "temperature": 25 }
}
return json.dumps(result, ensure_ascii=False)

Node.js编码规范

本小节主要说明平台预置Node.js函数模板的结构、参数定义及开发规范。开发者需基于此模板编写业务逻辑,实现插件的具体功能。

预置代码采用 CommonJS 规范,主要包含以下部分:

  • 依赖引入:通过 require("./common.js") 引入平台内置的 HTTP 请求库。
  • 辅助工具:extractEventData 函数用于自动处理 Base64 解码与 JSON 反序列化,开发者通常无需修改此函数。
  • 主入口:exports.handler 是异步函数入口,承载核心业务逻辑。

主入口函数:

exports.handler = async function (event, context) {
    // 业务逻辑区域
}
  • 约束:必须保留 exports.handler 命名。
  • 特性:函数被定义为 async,您可以在函数体内使用 await 语法来处理异步操作(如网络请求)。

输入参数:

代码模板通过 extractEventData 帮助您从 event 中提取并格式化了以下关键对象,您可以直接在 handler 中使用:

表6 变量说明

变量名

类型

含义

用途

inputData

Object

用户业务参数

对应插件定义中用户填写的入参。

mssiAuthData

Object

连接器鉴权数据

包含调用第三方 API 所需的 host, header, query 等鉴权配置信息。

dataExtendConfig

Object

扩展配置

流程编排中的高级配置参数。

代码示例
// 获取用户输入的参数 "keyword"
const keyword = inputData.keyword || "default";

// 获取连接器配置的主机地址
const apiHost = mssiAuthData.host;

上下文与安全凭证

context 对象提供运行时的系统能力。

  • context.getToken():获取当前执行环境的安全令牌(Security Token)。
  • 自动注入:模板代码已执行 mssiAuthData.securityToken = context.getToken(),将令牌自动合并到鉴权数据中,方便后续调用使用。

发起网络请求:

平台提供了 common 模块用于发送 HTTP 请求。为了代码的可读性和维护性,强烈建议使用 await 方式(同步写法)进行调用。

接口定义
const common = require("./common.js");
// ...
const response = await common.httpRequest(url, headers, body, method);
响应结构
{
    "code": 200,          // HTTP 状态码 (Number)
    "body": "...",        // 响应体 (String),通常需要 JSON.parse 解析
    "headers": {},        // 响应头 (Object)
    "error": "..."        // 错误描述 (String)
}

相关文档