1. 项目概述Connery SDK一个为AI应用构建可执行“动作”的桥梁如果你正在开发一个AI应用比如一个聊天机器人或者一个智能助手你肯定遇到过这样的场景用户说“帮我查一下明天的天气”或者“给我的客户张三发一封邮件”你的AI模型能理解这个意图但如何让它真正去执行“查询天气API”或“调用邮件服务”这个具体的动作呢这就是Connery SDK要解决的核心问题。它不是另一个大语言模型而是一个专为AI应用开发者设计的工具包让你能快速、标准化地将各种后端能力我们称之为“动作”或Action封装成AI可以理解和调用的“插件”。简单来说Connery SDK是一个开源的NPM包它包含了一个命令行工具CLI和一个JavaScript软件开发工具包SDK。它的目标是把“想法”变成“可执行的动作”。CLI负责帮你快速搭建项目骨架、管理插件生命周期而SDK则提供了一套简洁的API让你用代码定义动作的逻辑、输入参数和输出结果。最妙的是它会自动帮你把这些代码打包成一个带有标准化REST API的“插件服务器”。这个服务器帮你处理了所有繁琐但必要的工作用户请求的鉴权、输入数据的校验、执行日志的记录等等。这样一来你只需要关心最核心的业务逻辑“发邮件”到底要怎么发“查数据库”的SQL语句怎么写。为什么这很重要因为在AI应用生态里一致性就是生产力。无论是OpenAI的GPTs、LangChain的应用还是你自研的Agent框架它们都需要一种统一的方式来发现和调用外部功能。Connery通过生成标准化的API让你的一个插件能够被多种不同的AI应用无缝集成避免了为每个平台重复造轮子的痛苦。你可以把它想象成AI世界的“USB接口标准”——只要设备动作符合这个标准就能插到任何支持该标准的电脑AI应用上使用。2. 核心概念与架构设计解析要玩转Connery首先得吃透它的几个核心概念这能帮你理解它为何这样设计以及在什么场景下它能发挥最大价值。2.1 核心四要素插件、动作、插件服务器与应用Connery的整个体系围绕着四个关键实体运转理解它们的关系是上手的第一步。动作Action这是最小的可执行单元代表一个具体的功能。比如“发送邮件”、“创建日历事件”、“查询数据库”。每个动作都由两部分组成元数据Metadata以代码形式定义描述这个动作“是什么”。包括动作的唯一标识符、显示名称、描述、输入参数每个参数的类型、是否必填、描述等以及输出结果的格式。这部分信息是AI理解该动作能力的依据。运行逻辑Run Function一个JavaScript函数包含具体的执行代码。它接收来自AI应用的、已经过验证的输入参数执行操作如调用第三方API、操作数据库并返回结果。插件Plugin一个或多个相关动作的集合。通常按照服务或领域来组织比如一个“Gmail插件”可能包含“发送邮件”、“标记为已读”、“搜索邮件”等多个动作。插件是分发和部署的基本单位。插件服务器Plugin Server这是Connery SDK的“魔法”所在。当你使用SDK开发完插件后通过CLI命令可以一键将其运行为一个独立的HTTP服务器。这个服务器会自动根据你定义的插件和动作元数据生成一套完整的RESTful API。任何符合Connery标准的AI应用都可以通过调用这些API来发现可用的动作、获取参数模式、以及触发动作执行。服务器内置了安全中间件确保了调用的可控性。应用App指任何集成了Connery客户端库或能够调用其标准API的AI应用。例如一个自定义的GPT、一个基于LangChain构建的智能体或者一个企业内部的工作流自动化平台。应用通过插件服务器提供的标准接口与动作交互无需关心动作背后的具体实现技术。它们之间的关系可以用一个简单的信息流来描述AI应用App向插件服务器发起请求 - 插件服务器进行认证和输入验证 - 调用对应的插件中的具体动作Action的执行函数 - 动作函数运行并访问外部服务 - 将结果返回给插件服务器 - 服务器记录日志并将结果返回给AI应用。2.2 架构优势为什么选择Connery市面上让AI调用工具的方案不少比如LangChain Tools、OpenAI的Function Calling那为什么还要考虑Connery它的设计有几点独特的优势1. 关注点分离开发者体验友好Connery强制性地将“动作定义”元数据和“动作执行”逻辑通过SDK规范化。开发者只需要写一个标准的JavaScript函数和它的描述剩下的“脏活累活”——构建API服务器、设计请求响应格式、处理错误——全部由Connery接管。这极大地降低了开发门槛让后端开发者甚至前端开发者都能快速为AI应用提供能力。2. 标准化与互操作性这是Connery的立身之本。它定义了一套通用的插件契约。这意味着一个为Connery开发的Gmail插件可以同时被接入到公司内部的Slack机器人、面向客户的ChatGPT插件市场以及一个自研的自动化平台中。这种“一次开发多处部署”的能力对于构建可复用的AI能力中台至关重要。3. 内置的生产级特性开箱即用的插件服务器并非一个简单的Express.js样板。它内置了请求验证、基本的身份认证可通过插件配置扩展、统一的错误处理和结构化日志。这些特性虽然基础但却是生产环境应用必不可少的Connery帮你做好了让你能更专注于业务创新。4. 灵活的部署模式插件服务器可以部署在任何能运行Node.js的地方你自己的云服务器、容器平台、Serverless函数。你可以完全掌控数据和网络流这对于需要连接内网服务或处理敏感数据的动作来说是比许多云托管方案更安全、可控的选择。3. 从零开始开发你的第一个Connery动作插件理论讲得再多不如动手一试。我们来一步步创建一个实际的插件。假设我们要做一个“工作日计算器”插件它包含一个动作输入开始日期和天数计算出排除周末后的结束日期。这个例子不依赖外部API能让我们聚焦于Connery SDK本身的使用。3.1 环境准备与项目初始化首先确保你的开发环境已安装Node.js建议版本18或以上和npm。打开终端创建一个新的目录并进入然后使用Connery CLI初始化项目# 使用npx直接运行最新版的connery初始化命令 npx connerylatest dev init这个命令会交互式地引导你创建项目。它会询问几个关键信息Plugin ID: 插件的唯一标识通常使用反向域名格式如com.yourcompany.workday-calculator。这将是你的插件在系统中的“身份证”。Plugin Title: 插件的显示名称如Workday Calculator。Plugin Description: 插件的简要描述。Plugin Runner URL: 插件服务器运行后的基础URL。在开发阶段可以先用默认的http://localhost:4201。命令执行完毕后你会得到一个结构清晰的项目文件夹。核心目录如下your-plugin/ ├── src/ │ ├── actions/ # 存放所有动作的定义文件 │ │ └── getWeather.ts # 初始化生成的示例动作 │ ├── index.ts # 插件的主入口文件用于注册所有动作 │ └── runner.ts # 插件服务器的启动入口 ├── package.json ├── tsconfig.json # TypeScript配置 └── .env # 环境变量文件注意初始化生成的示例动作如getWeather引用了不存在的API直接运行会报错。在开发自己的动作前可以先将其注释掉或删除避免干扰。接下来安装项目依赖npm install3.2 定义“计算工作日”动作现在我们来创建自己的动作。在src/actions/目录下新建一个文件calculateWorkdays.ts。首先我们需要从SDK中导入定义动作所需的类型和装饰器。Connery SDK主要使用TypeScript装饰器来声明元数据这使得代码非常清晰。// src/actions/calculateWorkdays.ts import { Action, IAction, Input, Output, } from connery-io/sdk; // 使用 Action 装饰器来定义动作的元数据 Action({ key: calculate-workdays, // 动作的唯一键在插件内必须唯一 title: Calculate Workdays, // 动作的显示标题 description: Calculate the end date by adding workdays (excluding weekends) to a start date., // 动作的详细描述 type: read, // 动作类型read查询、write写入、delete删除等帮助AI理解动作性质 }) export default class CalculateWorkdaysAction implements IAction { // 使用 Input 装饰器定义输入参数 Input({ key: startDate, title: Start Date, description: The start date (YYYY-MM-DD)., type: string, validation: { required: true, // 可以添加更复杂的正则校验这里简单要求格式 }, }) startDate: string; Input({ key: daysToAdd, title: Days to Add, description: Number of workdays to add., type: integer, validation: { required: true, min: 1, }, }) daysToAdd: number; // 使用 Output 装饰器定义输出结构 Output({ key: endDate, title: End Date, description: The calculated end date in YYYY-MM-DD format., type: string, }) endDate: string; // 这是动作的核心执行函数必须实现 run 方法 async run(): Promisevoid { // 1. 解析开始日期 const start new Date(this.startDate); if (isNaN(start.getTime())) { throw new Error(Invalid startDate format. Please use YYYY-MM-DD.); } let count 0; let currentDate new Date(start); // 避免修改原日期 // 2. 循环添加工作日 while (count this.daysToAdd) { // 将日期向前推进一天 currentDate.setDate(currentDate.getDate() 1); const dayOfWeek currentDate.getDay(); // 0 Sunday, 6 Saturday // 3. 判断是否为工作日周一至周五 if (dayOfWeek ! 0 dayOfWeek ! 6) { count; } } // 4. 格式化输出日期 const year currentDate.getFullYear(); const month String(currentDate.getMonth() 1).padStart(2, 0); // 月份从0开始 const day String(currentDate.getDate()).padStart(2, 0); this.endDate ${year}-${month}-${day}; } }代码解析与要点装饰器是核心Action、Input、Output这些装饰器不仅定义了元数据还会在运行时被Connery SDK用于自动生成API文档和验证逻辑。validation字段里的规则会在请求到达你的run方法前就被执行确保了输入数据的有效性。IAction接口强制要求实现run方法。这是你的业务逻辑唯一需要关注的地方。错误处理在run方法中如果遇到业务错误如日期格式错误应该抛出Error。插件服务器会捕获它并将其转化为标准化的错误响应返回给调用方。异步支持run方法是async的这意味着你可以在里面安全地进行网络请求如调用外部API或数据库操作。3.3 注册动作并启动插件服务器定义好动作后我们需要在插件入口文件中注册它。打开src/index.ts文件。// src/index.ts import { Plugin } from connery-io/sdk; import CalculateWorkdaysAction from ./actions/calculateWorkdays; // 注释掉或删除初始的示例动作 import GetWeatherAction from ./actions/getWeather; const plugin new Plugin({ title: Workday Calculator Plugin, // 与初始化时一致或可修改 description: A plugin to perform workday calculations., }); // 注册我们的动作 plugin.addAction(CalculateWorkdaysAction); // plugin.addAction(GetWeatherAction); // 注释掉示例动作 export default plugin;现在可以启动插件服务器了npm start如果一切顺利终端会显示服务器已在http://localhost:4201启动。打开浏览器访问这个地址你会看到一个自动生成的、简洁的插件管理界面。这里展示了你的插件信息、所有已注册的动作列表以及每个动作的详细输入输出模式。更重要的是它提供了一个交互式的界面让你可以手动输入参数测试动作这对于调试来说非常方便。3.4 在AI应用中调用你的动作插件服务器运行起来后就提供了一个标准的API端点。AI应用可以通过向http://localhost:4201/v1/actions/calculate-workdays/run发送POST请求来调用我们的动作。一个典型的请求体如下{ parameters: { startDate: 2024-05-20, daysToAdd: 5 } }服务器会返回类似这样的响应{ output: { endDate: 2024-05-27 }, status: success }对于像LangChain或OpenAI Assistant这样的AI框架你需要使用Connery提供的特定集成工具如ConneryTool来包装这个API端点从而让LLM能够规划和调用它。这通常涉及在AI应用代码中配置插件服务器的URL和认证信息如果有。4. 进阶实战开发一个集成外部API的插件只计算日期显然不够过瘾。让我们来点更实际的开发一个需要调用第三方API的动作。我们以获取指定城市天气为例使用一个免费的天气API如Open-Meteo。4.1 处理敏感信息环境变量与配置调用外部API通常需要密钥API Key。绝对不要将密钥硬编码在代码中。Connery项目初始化时已经生成了.env文件用于管理环境变量。首先在.env文件中添加你的API基础URL虽然Open-Meteo不需要Key但这是一个好习惯# .env WEATHER_API_BASE_URLhttps://api.open-meteo.com/v1然后在动作中通过process.env读取。为了更好的类型安全和结构我们可以在src目录下创建一个config文件夹来管理配置。4.2 实现“获取天气”动作在src/actions/下创建getWeather.ts替换掉之前的示例。// src/actions/getWeather.ts import { Action, IAction, Input, Output, } from connery-io/sdk; import axios from axios; // 需要先安装: npm install axios // 定义输出项的类型可选用于复杂输出 interface WeatherOutput { temperature: number; weatherCode: number; description: string; } Action({ key: get-weather, title: Get Weather, description: Get the current weather for a given city., type: read, }) export default class GetWeatherAction implements IAction { // 输入城市名称 Input({ key: city, title: City Name, description: The name of the city, e.g., London, Tokyo., type: string, validation: { required: true }, }) city: string; // 输出一个包含多个字段的对象 Output({ key: weather, title: Weather Information, description: The current weather conditions., type: object, properties: { // 定义对象内部的字段 temperature: { type: number, title: Temperature, description: Current temperature in Celsius., }, weatherCode: { type: integer, title: Weather Code, description: WMO weather interpretation code., }, description: { type: string, title: Description, description: Human-readable weather description., }, }, }) weather: WeatherOutput; async run(): Promisevoid { // 在实际项目中这里应该有一个从城市名到经纬度的地理编码服务。 // 为了简化我们使用一个预设的映射。生产环境请使用专业的地理编码API。 const cityCoordinates: Recordstring, { lat: number; lon: number } { london: { lat: 51.5074, lon: -0.1278 }, tokyo: { lat: 35.6762, lon: 139.6503 }, new york: { lat: 40.7128, lon: -74.0060 }, }; const cityKey this.city.toLowerCase(); const coords cityCoordinates[cityKey]; if (!coords) { throw new Error(Coordinates for city ${this.city} are not configured.); } try { // 调用外部API const response await axios.get(${process.env.WEATHER_API_BASE_URL}/forecast, { params: { latitude: coords.lat, longitude: coords.lon, current_weather: true, timezone: auto, }, timeout: 5000, // 设置超时避免长时间等待 }); const current response.data.current_weather; const weatherCodeMap: Recordnumber, string { 0: Clear sky, 1: Mainly clear, 2: Partly cloudy, 3: Overcast, // ... 其他代码映射 }; this.weather { temperature: current.temperature, weatherCode: current.weathercode, description: weatherCodeMap[current.weathercode] || Code: ${current.weathercode}, }; } catch (error: any) { // 细化错误信息便于排查 if (error.response) { // 请求已发出服务器返回了非2xx状态码 throw new Error(Weather API responded with status ${error.response.status}: ${error.response.data?.message || Unknown error}); } else if (error.request) { // 请求已发出但没有收到响应 throw new Error(No response received from the weather API. Network issue or server down.); } else { // 请求配置出错 throw new Error(Failed to call weather API: ${error.message}); } } } }进阶要点错误处理的艺术对外部API的调用必须有健壮的错误处理。区分网络错误、API错误、业务逻辑错误并抛出对终端用户或AI有意义的错误信息。输出结构复杂化当输出不是一个简单的字符串或数字时可以使用type: object并定义其properties。这能让AI更清晰地理解返回的数据结构。性能与超时务必为外部HTTP请求设置超时timeout防止一个缓慢的API拖垮整个插件服务器的响应。地理编码这是一个简化示例。真实场景中你需要集成一个地理编码服务如Google Geocoding API、OpenStreetMap Nominatim来将城市名转换为经纬度。这可以作为另一个独立的动作或者在此动作内部调用。4.3 添加插件级别的配置与安全插件本身也可以有配置比如全局的API Key或服务端点。这些可以在src/index.ts创建插件实例时传入并在动作中通过依赖注入或全局访问的方式使用。更重要的安全考虑是认证。为插件服务器添加基础认证 在开发环境你可能不需要。但在生产环境暴露一个无需认证即可执行动作的端点是非常危险的。Connery允许你通过插件配置来添加安全中间件。修改src/runner.ts这是npm start实际执行的文件// src/runner.ts import plugin from ./index; import { createRunner } from connery-io/sdk; import basicAuth from express-basic-auth; // 需要安装: npm install express-basic-auth types/express-basic-auth // 1. 定义认证中间件示例使用HTTP Basic Auth const authMiddleware basicAuth({ users: { [process.env.PLUGIN_USER || admin]: process.env.PLUGIN_PASSWORD || secret }, challenge: true, }); // 2. 创建Runner时传入配置 const runner createRunner(plugin, { // 可以在这里配置插件服务器的行为例如端口、日志级别等 beforeActionRunMiddlewares: [authMiddleware], // 在执行动作前加入认证中间件 }); // 3. 启动服务器 runner.start();然后在.env文件中设置用户名和密码PLUGIN_USERmyuser PLUGIN_PASSWORDaStrongPassword123!这样任何对插件服务器的请求都需要提供正确的HTTP Basic认证头。AI应用在集成时也需要配置这些凭据。5. 调试、测试与生产部署指南开发完成后如何确保动作可靠工作并顺利上线5.1 本地调试与测试Connery CLI提供了强大的开发时工具npm start启动开发服务器支持热重载。修改动作代码后服务器会自动重启。交互式控制台访问http://localhost:4201提供的Web界面是手动测试动作最直观的方式。你可以直接填参数、点运行、看结果和日志。结构化日志在动作的run方法中使用console.log或console.error输出的信息会被插件服务器捕获并以结构化的格式打印在终端和Web界面上方便追踪执行流程和排查问题。编写自动化测试 对于复杂的业务逻辑建议编写单元测试。你可以直接导入动作类实例化它设置输入参数然后调用run方法最后断言输出。// __tests__/calculateWorkdays.test.ts (使用Jest示例) import CalculateWorkdaysAction from ../src/actions/calculateWorkdays; describe(CalculateWorkdaysAction, () { it(should calculate end date correctly excluding weekends, async () { const action new CalculateWorkdaysAction(); action.startDate 2024-05-20; // 周一 action.daysToAdd 5; // 加到下周一 await action.run(); expect(action.endDate).toBe(2024-05-27); // 跳过中间的两个周末 }); });5.2 打包与生产部署当你完成开发并通过测试后就需要将插件部署到生产环境。1. 构建确保你的TypeScript代码编译成JavaScript。项目模板通常配置了npm run build命令它会将src下的代码编译到dist目录。2. 选择部署环境传统服务器/容器将dist目录、package.json、node_modules和.env文件打包在服务器上运行npm start。使用PM2、Docker等工具来管理进程。Serverless函数将插件服务器适配到云函数如AWS Lambda Vercel Serverless Functions。你需要编写一个简单的函数包装器来启动runner。Connery的轻量级设计使其非常适合Serverless场景。专用托管平台如果Connery未来提供官方的插件托管服务部署可能会更简单。3. 关键生产配置环境变量确保所有敏感信息API Keys、数据库连接串、认证密码都通过环境变量管理绝不上传至代码仓库。日志与监控插件服务器会输出JSON格式的访问日志和错误日志。你需要配置日志收集系统如ELK、Datadog来集中管理。同时考虑为关键动作添加应用性能监控APM。网络与安全生产环境的插件服务器应该运行在内部网络或配置了严格防火墙规则的VPC内仅允许可信的AI应用通过特定的认证方式如API Key、JWT、mTLS进行访问。前面提到的基础认证只是第一道防线根据安全要求可能需要更复杂的方案。5.3 集成到AI应用以LangChain为例最后你的插件需要被AI应用调用。这里以流行的LangChain框架为例展示如何集成。首先在你的AI应用项目中安装Connery的LangChain集成包如果存在或直接使用HTTP客户端。假设我们使用一个通用的HTTP工具包装器。// 在你的LangChain Agent构建代码中 import { DynamicTool } from langchain/tools; import { initializeAgentExecutorWithOptions } from langchain/agents; import { ChatOpenAI } from langchain/chat_models/openai; // 1. 创建一个工具来调用我们的“计算工作日”动作 const workdayCalculatorTool new DynamicTool({ name: workday_calculator, description: Calculates the end date by adding a specified number of workdays to a start date. Input should be a JSON string with startDate (YYYY-MM-DD) and daysToAdd (integer)., func: async (input: string) { try { const params JSON.parse(input); const response await fetch(http://your-production-server:4201/v1/actions/calculate-workdays/run, { method: POST, headers: { Content-Type: application/json, Authorization: Basic btoa(myuser:aStrongPassword123!), // 使用配置的认证 }, body: JSON.stringify({ parameters: params }), }); if (!response.ok) { throw new Error(Action failed: ${response.statusText}); } const result await response.json(); return The end date is ${result.output.endDate}.; } catch (error: any) { return Error calculating workdays: ${error.message}; } }, }); // 2. 类似地创建获取天气的工具... // 3. 将工具提供给Agent const tools [workdayCalculatorTool /*, other tools */]; const model new ChatOpenAI({ temperature: 0 }); const executor await initializeAgentExecutorWithOptions(tools, model, { agentType: openai-functions, verbose: true, }); // 4. 现在Agent可以使用这些工具了 const result await executor.run(如果我从2024-06-01开始加上10个工作日哪天结束); console.log(result);通过这种方式LangChain Agent就能理解你的工具描述并在需要时规划并调用你部署好的Connery动作了。6. 常见问题、排查技巧与最佳实践在实际开发和运维中你肯定会遇到各种问题。下面是一些我踩过坑后总结的经验。6.1 开发阶段常见问题问题1动作注册失败服务器启动时报错 “Action with key ‘xxx’ is already registered.”原因在src/index.ts中重复添加了同一个动作类或者两个不同的动作文件意外导出了相同的key。解决检查src/index.ts中的plugin.addAction()调用确保每个动作只注册一次。并检查所有动作装饰器Action({ key: ... })中的key值在插件范围内唯一。问题2调用动作时返回 “Validation failed for input parameter ‘xxx’.”原因输入数据没有通过Input装饰器中定义的validation规则。排查首先通过插件服务器的Web界面手动测试确保输入的JSON格式正确且参数名、类型、是否必填符合定义。其次检查validation中的regex或自定义验证逻辑是否过于严格。问题3动作run方法中的异步操作如API调用超时或失败。原因网络不稳定、外部服务不可用、未处理Promise拒绝。解决增加超时设置在调用外部API时如使用axios务必设置timeout参数。实现重试机制对于可能因网络抖动失败的请求可以封装一个带有指数退避的重试函数。全面的错误处理如前面示例所示在try...catch中区分不同类型的错误并抛出有意义的错误信息方便在日志中定位问题。6.2 生产环境运维要点问题4插件服务器内存使用率持续增长。原因可能是内存泄漏。常见于动作代码中未正确释放资源如未关闭数据库连接、创建了全局变量累积数据。排查使用Node.js内存分析工具如heapdump、clinic.js生成堆快照对比分析。重点检查动作run方法中是否有变量逃逸到了外层作用域。问题5如何监控动作的执行情况方案Connery插件服务器会输出标准格式的日志。你可以将日志接入到像ELK或Splunk这样的集中式日志系统。在关键动作的run方法开始和结束时打印带有唯一请求ID的日志便于追踪整个链路。考虑在动作中集成遥测数据收集向监控系统如Prometheus发送指标如执行耗时、成功/失败次数。问题6如何更新已部署的插件流程对于无状态的动作逻辑更新通常只需替换代码并重启服务。但如果更新涉及输入/输出模式的变更例如删除了一个旧的必需参数或改变了返回结构这就是一个破坏性变更。处理破坏性变更必须谨慎。建议采取版本化策略为插件定义语义化版本号如1.0.0。非破坏性变更如新增可选参数、新增动作可以升级小版本号1.1.0。破坏性变更如删除参数、修改参数类型必须升级主版本号2.0.0并考虑并行运行新旧版本一段时间给AI应用留出迁移时间。6.3 设计动作的最佳实践保持动作的原子性与单一职责一个动作只做一件事并且把它做好。不要创建像handleCustomerRequest这样庞大模糊的动作而应拆分为getCustomerInfo、createSupportTicket、sendUpdateEmail等小动作。这能让AI更准确地理解和调用。提供丰富、准确的元数据description字段是AI理解动作能力的关键。用自然语言清晰描述动作的功能、适用场景以及输入输出的具体含义。好的描述能大幅提升AI调用动作的准确率。设计健壮的错误处理动作应能处理各种边界情况和异常输入。错误信息应足够友好既能帮助终端用户理解也能让AI根据错误进行后续决策例如“城市未找到”可以提示用户重新输入。考虑性能与副作用动作的执行时间应尽可能短。对于长时间运行的任务应考虑设计为异步动作触发后立即返回一个任务ID然后通过另一个查询动作获取结果。明确动作是否具有副作用如修改数据并在描述中注明。安全性是第一要务输入验证除了Connery内置的验证在run方法内部也要进行业务逻辑验证。权限控制在插件服务器层面实施认证如API Key、JWT。在动作内部可以根据调用上下文如通过请求头传递的用户信息进行更细粒度的授权。敏感信息动作日志中切勿记录密码、密钥等敏感信息。Connery默认不会记录输入输出但你在代码中手动打印日志时需格外小心。开发Connery插件的体验很像是在为AI世界编写一套微服务API。它抽象了网络和协议的细节让你能回归到最纯粹的业务逻辑实现上。随着你创建的动作越来越多你会逐渐积累起一个属于自己或团队的“AI能力库”这个库可以灵活地装配到各种不同的AI应用中去这种复用性和一致性带来的效率提升在长期项目中会体现得越来越明显。