news 2026/5/7 4:49:28

Nylas Skills:为AI助手构建安全可控的“技能”框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nylas Skills:为AI助手构建安全可控的“技能”框架

1. 项目概述:当AI助手学会“打电话”——Nylas Skills的深度解构

如果你正在构建一个需要与外部世界“对话”的AI应用,比如一个能自动帮你预约会议、查询订单状态或者发送跟进邮件的智能助手,你可能会遇到一个核心难题:如何让这个AI助手安全、可靠地执行这些涉及用户隐私和第三方服务的具体操作?直接让AI模型去调用API,就像让一个刚学会说话的孩子去操作一台精密的机床,充满了不确定性和风险。这正是Nylas Skills项目要解决的核心问题。简单来说,Nylas Skills是一个开源的框架,它让开发者能够为大型语言模型(LLM)驱动的AI助手,安全地封装和提供一系列可执行的“技能”。你可以把它想象成给AI助手配备了一个标准化的、安全的“工具腰带”,腰带上挂着的每一件工具(Skill),都对应着一个具体的、可重复执行的任务,比如“发送邮件”、“创建日历事件”或“查询CRM联系人”。

这个项目源自Nylas,一家在开发者邮件、日历和联系人API领域深耕多年的公司。他们发现,尽管像GPT-4这样的LLM在理解和生成自然语言方面能力惊人,但让它们直接、自主地操作真实世界的系统(如你的Gmail或Outlook账户)是极其危险且不现实的。Nylas Skills的出现,正是在LLM的“思考能力”和现实世界的“执行能力”之间,架起了一座安全、可控的桥梁。它非常适合那些正在开发AI客服、智能个人助理、自动化工作流工具,或者任何需要将LLM的对话能力转化为具体、安全操作的开发者。通过使用Skills,你可以确保你的AI应用不仅能“说”,还能安全、准确地“做”。

2. 核心架构与设计哲学:为什么是“技能”而非“API直接调用”?

2.1 从“意图理解”到“安全执行”的鸿沟

要理解Nylas Skills的设计价值,我们首先要看清当前AI应用开发中的一个典型困境。假设我们构建了一个基于LLM的会议调度助手。用户对它说:“帮我跟王总约个下周二的会议,主题是项目复盘。” LLM可以完美地理解这个意图,解析出关键实体:参与者(王总)、时间(下周二)、主题(项目复盘)。问题出在下一步:如何执行?

一种 naive 的做法是,让LLM直接生成代码或API调用,比如一段调用Google Calendar API的Python脚本。这带来了几个致命问题:

  1. 安全性:让LLM直接接触含有用户OAuth令牌等敏感信息的API密钥,无异于将保险箱密码告诉了一个虽然聪明但不可预测的“孩子”。
  2. 可靠性:LLM生成的代码可能存在语法错误、逻辑缺陷,或者对API的误解,导致调用失败甚至产生副作用(如误删事件)。
  3. 可控性:你无法精细控制AI可以执行的操作范围。它可能“突发奇想”去执行一个你从未授权过的危险操作。

Nylas Skills的核心理念,就是将“意图解析”“安全执行”这两个环节解耦。LLM只负责前者——理解用户想做什么,并提取出结构化的参数。后者——具体怎么做——则交给预先定义好、经过充分测试和权限控制的“技能”去完成。

2.2 Skills框架的核心组件拆解

Nylas Skills的架构清晰地体现了这一理念,主要包含以下几个核心部分:

1. Skill(技能):这是框架的基本单元。每个Skill都是一个独立的、可执行的操作模块。它明确定义了:

  • description(描述):用自然语言描述这个技能是做什么的。这是给LLM看的,帮助LLM判断在什么情况下应该调用这个技能。例如:“发送一封电子邮件给指定的收件人。”
  • input_schema(输入模式):一个严格的JSON Schema,定义了执行这个技能所需的所有参数、它们的类型、是否必填以及描述。这相当于技能的“参数说明书”。对于“发送邮件”技能,其input_schema会定义recipient(字符串,必填)、subject(字符串)、body(字符串)等字段。
  • function(执行函数):一个具体的、实现技能逻辑的代码函数。这个函数接收解析好的参数,调用底层的API(如Nylas的Email API、Calendar API,或其他任何第三方服务),并返回结果。这里是安全边界所在,所有对外的网络请求、错误处理、数据格式化都在这个受控的函数内完成。

2. Skill Manager(技能管理器):这是一个中心化的注册和管理器。开发者将自己编写的多个Skill注册到Skill Manager中。当AI应用运行时,Skill Manager负责:

  • 向LLM提供所有已注册技能的描述和输入模式,供LLM进行“工具调用”决策。
  • 接收来自LLM的“工具调用”请求(其中包含技能名称和参数)。
  • 找到对应的Skill,验证参数是否符合schema,然后执行其function
  • 将执行结果(成功或错误)格式化后返回给LLM,由LLM生成最终的用户回复。

3. 与LLM的集成模式:Skills框架设计为与主流LLM的“Function Calling”(函数调用)或“Tool Use”(工具使用)能力无缝集成。例如,在OpenAI的Chat Completions API中,你可以将Skill Manager提供的技能列表以特定格式(tools参数)传递给GPT模型。当用户表达一个需求时,GPT会判断是否需要以及调用哪个技能,并返回一个结构化的调用请求。你的应用后端收到这个请求后,转交给Skill Manager执行即可。

这种架构带来的核心优势是“安全沙箱化”。LLM在“沙箱”外,它只能提议要执行哪个技能以及参数是什么,但无权接触任何实际的执行代码或敏感凭证。所有的执行逻辑、API密钥、错误处理都被封装在具体的Skill函数内部,由开发者完全掌控。这极大地降低了AI行动的风险,使其变得可预测、可审计、可调试。

3. 从零到一:构建你的第一个Nylas Skill实战

理解了理论,我们动手实现一个最经典的技能:“发送电子邮件”。我们将使用Python语言,基于Nylas Skills的开源代码进行构建。这个过程将清晰地展示一个Skill从定义到集成的完整生命周期。

3.1 环境准备与依赖安装

首先,确保你有一个Python环境(3.8+)。我们创建一个新的虚拟环境并安装核心依赖。

# 创建并激活虚拟环境(以venv为例) python -m venv nylas-skills-env source nylas-skills-env/bin/activate # Linux/macOS # 或 nylas-skills-env\Scripts\activate # Windows # 安装Nylas SDK和Skills框架 pip install nylas # 假设Nylas Skills的核心库可通过pip安装或其源码在本地 # 这里我们演示从源码安装(如果项目提供setup.py) git clone https://github.com/nylas/skills.git cd skills pip install -e .

除了代码库,你还需要一个Nylas开发者账户。前往Nylas官网注册,并创建一个新的应用。在应用设置中,你会获得关键的CLIENT_IDCLIENT_SECRET。同时,你需要配置OAuth重定向URI(例如http://localhost:3000/oauth/callback),用于后续的用户授权流程。这些凭证是Skill与真实邮箱服务(如Gmail、Outlook)通信的桥梁。

注意CLIENT_SECRET是高度敏感信息,必须像保护密码一样保护它。永远不要将其硬编码在客户端代码或提交到版本库中。务必使用环境变量或安全的密钥管理服务。

3.2 编写“Send Email” Skill的核心代码

现在,我们来创建技能文件send_email_skill.py

import os from typing import Any, Dict from nylas import Client from skills.skill import Skill, SkillTool # 从环境变量加载Nylas凭证 NYLAS_CLIENT_ID = os.getenv("NYLAS_CLIENT_ID") NYLAS_CLIENT_SECRET = os.getenv("NYLAS_CLIENT_SECRET") class SendEmailSkill(Skill): """一个用于发送电子邮件的Nylas Skill。""" def __init__(self): # 初始化Nylas客户端 self.nylas_client = Client( api_key=None, # 使用OAuth模式,API Key留空 client_id=NYLAS_CLIENT_ID, client_secret=NYLAS_CLIENT_SECRET, ) super().__init__( name="send_email", description="发送一封电子邮件到一个或多个收件人。需要提供收件人邮箱、主题和正文。", input_schema={ "type": "object", "properties": { "to": { "type": "array", "items": {"type": "string", "format": "email"}, "description": "收件人的电子邮件地址列表。", }, "subject": { "type": "string", "description": "邮件的主题。", }, "body": { "type": "string", "description": "邮件的正文内容,支持纯文本。", }, }, "required": ["to", "subject", "body"], } ) async def execute(self, input_data: Dict[str, Any], user_context: Dict[str, Any]) -> Dict[str, Any]: """ 执行发送邮件的核心逻辑。 Args: input_data: 从LLM传来的参数,已根据input_schema验证。 user_context: 用户上下文,这里应包含授权后的grant_id(访问令牌标识)。 Returns: 包含执行结果或错误信息的字典。 """ try: # 1. 从上下文中获取当前用户的访问授权(grant_id) # 在实际应用中,user_context通常由你的认证中间件注入,关联当前会话的用户。 grant_id = user_context.get("nylas_grant_id") if not grant_id: return {"success": False, "error": "用户未授权邮箱访问权限。"} # 2. 准备邮件数据 to_emails = [{"email": email} for email in input_data["to"]] email_data = { "to": to_emails, "subject": input_data["subject"], "body": input_data["body"], } # 3. 使用Nylas SDK发送邮件 # 这里假设使用Nylas的特定API方法,实际方法名请参考最新SDK文档 send_result = self.nylas_client.messages.send(grant_id, request_body=email_data) # 4. 返回成功结果 return { "success": True, "message": f"邮件已成功发送至 {', '.join(input_data['to'])}。", "message_id": getattr(send_result, 'id', None) # 返回邮件ID用于追踪 } except Exception as e: # 捕获并返回详细的错误信息,便于LLM或前端向用户解释 return {"success": False, "error": f"发送邮件时出错:{str(e)}"} # 将Skill包装成LLM可识别的Tool格式 def get_send_email_tool() -> SkillTool: skill_instance = SendEmailSkill() return skill_instance.as_tool()

代码关键点解析:

  1. 继承Skill基类:我们创建了SendEmailSkill类并继承自框架的Skill基类。这确保了我们的技能遵循统一的接口规范。
  2. 定义input_schema:我们使用了JSON Schema来严格定义输入。required字段指明了哪些参数是LLM必须提供的。format: "email"是一个提示,虽然框架可能不会做严格验证,但能帮助LLM更好地理解参数格式。
  3. execute方法:这是技能的心脏。它接收验证过的input_datauser_contextuser_context安全执行的关键,它包含了当前会话用户的身份标识(这里是nylas_grant_id),确保邮件是从该用户自己的邮箱账户发出,而不是一个全局的、高权限的账户。这实现了用户级的数据隔离和安全。
  4. 错误处理execute方法用try-except包裹,确保任何异常都能被捕获并转化为结构化的错误信息返回,而不是导致整个应用崩溃。这使AI助手能够优雅地处理失败,例如回复用户:“抱歉,发送邮件时遇到了网络问题,请稍后再试。”
  5. as_tool方法:框架提供的这个方法会将技能的描述和输入模式打包成LLM(如OpenAI GPT)要求的tool格式,方便集成。

3.3 集成Skill到AI应用流中

有了Skill,下一步是将其集成到一个简单的AI聊天后端中。这里以FastAPI为例,展示核心流程。

from fastapi import FastAPI, HTTPException, Depends from pydantic import BaseModel import openai import os from send_email_skill import get_send_email_tool from skills.manager import SkillManager app = FastAPI() # 配置 OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") openai_client = openai.OpenAI(api_key=OPENAI_API_KEY) # 初始化Skill Manager并注册技能 skill_manager = SkillManager() skill_manager.register_tool(get_send_email_tool()) # 未来可以在这里注册更多技能,如 create_calendar_event, find_contact 等 class ChatRequest(BaseModel): message: str user_id: str # 用于标识用户,关联其Nylas grant_id class ChatResponse(BaseModel): reply: str def get_user_context(user_id: str) -> Dict[str, Any]: """根据user_id获取用户上下文(例如从数据库查询其Nylas grant_id)。""" # 这里是模拟,实际应从数据库或会话存储中获取 # 假设用户之前已完成OAuth授权,我们将grant_id存储在数据库中 user_grants = { "user_123": {"nylas_grant_id": "grant_abc123"}, } return user_grants.get(user_id, {}) @app.post("/chat", response_model=ChatResponse) async def chat_endpoint(request: ChatRequest): user_context = get_user_context(request.user_id) # 步骤1:获取当前可用的工具(技能)列表 available_tools = skill_manager.get_tools_for_llm() # 步骤2:调用LLM(OpenAI),传入用户消息和工具定义 llm_response = openai_client.chat.completions.create( model="gpt-4-turbo-preview", # 或 gpt-3.5-turbo messages=[ {"role": "system", "content": "你是一个有帮助的AI助手,可以发送邮件。请根据用户需求判断是否需要调用工具。"}, {"role": "user", "content": request.message} ], tools=available_tools, # 关键:将技能作为工具提供给LLM tool_choice="auto", # 让LLM自行决定是否调用工具 ) message = llm_response.choices[0].message reply_content = message.content # 步骤3:检查LLM是否决定调用工具 if message.tool_calls: for tool_call in message.tool_calls: # 提取工具调用信息 skill_name = tool_call.function.name skill_args = json.loads(tool_call.function.arguments) # 步骤4:通过Skill Manager执行对应的技能 execution_result = await skill_manager.execute_skill( skill_name=skill_name, input_data=skill_args, user_context=user_context # 传入用户上下文! ) # 步骤5:将技能执行结果作为新的上下文,再次调用LLM生成最终回复 follow_up_response = openai_client.chat.completions.create( model="gpt-4-turbo-preview", messages=[ {"role": "system", "content": "你是一个有帮助的AI助手。"}, {"role": "user", "content": request.message}, message, # 包含第一次LLM回复和工具调用请求的消息 { "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(execution_result), # 工具执行结果 } ] ) reply_content = follow_up_response.choices[0].message.content return ChatResponse(reply=reply_content)

这个流程清晰地展示了AI助手、LLM、Skill Manager和具体Skill之间的协作舞蹈:

  1. 用户发送消息:“给alex@example.com发封邮件,说会议改到明天下午3点。”
  2. 后端将消息和已注册的技能列表(available_tools)发送给OpenAI。
  3. OpenAI的GPT模型识别出用户意图是“发送邮件”,于是返回一个tool_calls响应,指定调用send_email技能,并自动提取出参数:to: ["alex@example.com"],subject: “会议时间变更”,body: “会议改到明天下午3点。”
  4. 后端收到调用请求,通过SkillManager.execute_skill找到SendEmailSkill,传入参数和当前用户的user_context(包含其grant_id)。
  5. SendEmailSkill.execute()方法使用该用户的授权,通过Nylas API实际发送邮件。
  6. 技能返回执行结果({"success": True, "message": "..."})。
  7. 后端将此结果作为新的信息追加到对话历史中,再次请求OpenAI。
  8. OpenAI根据“邮件发送成功”这一事实,生成最终的用户回复:“好的,已成功将会议时间变更的邮件发送给alex@example.com。”

4. 高级技巧与生产环境考量

将Skills用于玩具项目很简单,但要将其投入生产环境,支撑起真实、高并发的AI应用,就需要考虑更多工程细节。

4.1 技能设计的“松耦合”与“可复用性”

一个好的Skill应该像乐高积木一样,职责单一且接口清晰。避免创建“巨无霸”技能。例如,不要做一个“处理客户跟进”的技能,它里面既包含查询CRM,又包含发送邮件,还包含创建待办事项。应该将其拆分为:

  • find_contact_in_crm
  • send_follow_up_email
  • create_task_in_project_tool

这样设计的好处是:

  • 可复用性高send_email技能可以被任何需要发邮件的场景调用。
  • 易于测试和维护:每个技能逻辑独立,可以单独进行单元测试和调试。
  • LLM理解更准确:LLM对于功能明确、描述清晰的简单工具,调用准确率远高于复杂模糊的工具。

在定义input_schema时,要像设计API接口一样严谨。为每个参数提供清晰、无歧义的description。例如,对于日期参数,不要只写"date",而应该写"会议的日期,格式为YYYY-MM-DD"。这能极大提升LLM填充参数的准确性。

4.2 用户上下文(User Context)与安全隔离

这是生产环境安全的重中之重。user_context参数是确保用户A的技能操作不会影响到用户B数据的关键。在实际系统中,你需要一个可靠的用户认证和会话管理机制。

  1. OAuth流程集成:在你的AI应用前端,需要集成Nylas的OAuth授权流程。用户首次使用邮件相关功能时,引导其跳转到Nylas的授权页面,授权你的应用访问其邮箱。授权成功后,Nylas会返回一个grant_id(或access_token)。
  2. 上下文关联:你需要将这个grant_id与该用户在你的系统中的唯一标识(如user_id)关联起来,并安全地存储(例如在加密的会话存储或数据库中)。
  3. 注入上下文:在处理每个用户请求时(如上面的/chat接口),你的认证中间件需要根据当前会话的user_id,从存储中取出对应的grant_id及其他必要信息(如用户时区、偏好设置),构建成user_context字典,然后传递给skill_manager.execute_skill
  4. 令牌刷新:访问令牌可能会过期。你的技能或一个独立的后台服务需要处理令牌刷新的逻辑,确保用户授权长期有效。Nylas SDK通常提供了令牌刷新的机制。

4.3 错误处理、日志与可观测性

技能的execute方法必须健壮。除了基础的try-except,生产环境还需要:

  • 分级错误处理:区分不同类型的错误(网络超时、API限流、权限不足、参数无效),并返回不同级别的错误信息。对于可重试的错误(如网络超时),可以在技能内部实现简单的重试逻辑。
  • 结构化日志:记录每一次技能调用的详细信息:技能名、输入参数(注意脱敏,如隐藏邮件正文中的敏感信息)、用户ID、执行时间、结果状态。这对于调试、审计和用量分析至关重要。可以使用像structlog这样的库来输出JSON格式的日志,方便接入ELK或Datadog等监控系统。
  • 指标监控:为关键技能定义监控指标,如调用次数、成功率、平均延迟。这能帮助你快速发现系统瓶颈或异常。例如,如果send_email技能的失败率突然飙升,监控警报能让你第一时间介入排查。

4.4 技能的版本管理与部署

随着应用迭代,技能本身也需要更新。你可能需要修改input_schema、优化execute逻辑或修复bug。如何平滑升级?

  1. 版本化技能:考虑在技能名称或注册时加入版本号,例如send_email_v2。这样,新旧版本的技能可以在一段时间内共存。
  2. 蓝绿部署:在Skill Manager的注册层面,可以通过配置开关,将流量逐渐从旧技能切换到新技能。例如,先向10%的用户开放新技能,观察错误率和效果,再逐步扩大范围。
  3. LLM提示词适配:如果你改变了技能的描述或参数,记得也要更新提供给LLM的descriptioninput_schema,否则LLM可能无法正确调用新版本的技能。

5. 典型问题排查与实战心得

在实际开发和运维中,你会遇到一些典型问题。以下是我总结的“避坑指南”。

5.1 LLM不调用或错误调用技能

这是最常见的问题。现象是用户提出了明确需求,但AI助手只是用文字回答“我可以帮你发邮件”,却没有实际调用send_email技能。

  • 排查点1:技能描述是否清晰?LLM完全依赖你提供的descriptioninput_schema中的参数描述来判断是否调用技能。确保描述是任务导向的、无歧义的。对比一下:
    • 差的描述:“处理邮件相关操作。”
    • 好的描述:“发送一封新的电子邮件。需要提供收件人邮箱地址、邮件主题和正文内容。”
  • 排查点2:系统提示词是否冲突?你在调用LLM时提供的system消息(role: “system”)可能包含了限制性指令,如“你是一个只负责回答问题的助手,不要执行任何操作。”这可能会覆盖工具调用的能力。确保系统提示词鼓励或至少不禁止工具使用,例如:“你是一个有帮助的AI助手,可以使用工具来帮助用户完成任务。”
  • 排查点3:参数格式是否匹配?检查LLM返回的argumentsJSON字符串是否能被正确解析,并符合你定义的schema。有时LLM可能会生成一个格式正确但值不合理的参数(比如一个无效的邮箱地址)。在技能的execute方法开始处,可以加入额外的参数验证逻辑。
  • 实战心得:在开发初期,可以暂时将LLM的tool_choice参数设置为“none”,观察LLM在不知道有工具的情况下会如何回复。然后再设置为“auto”或指定工具,对比回复变化。这能帮你判断问题是出在LLM理解上,还是出在技能定义或集成逻辑上。

5.2 技能执行超时或失败

技能执行涉及到网络I/O(调用Nylas API或其他第三方服务),超时是常态。

  • 设置合理的超时:在技能执行函数中,对任何外部HTTP请求都设置明确的超时时间。使用asyncio.wait_forrequests库的timeout参数。
    import asyncio async def execute(self, input_data, user_context): try: # 设置5秒超时 result = await asyncio.wait_for(self._call_external_api(input_data), timeout=5.0) return result except asyncio.TimeoutError: return {"success": False, "error": "请求外部服务超时,请稍后重试。"}
  • 实现重试机制:对于瞬时的网络抖动或可重试的错误(如HTTP 429限流、502 Bad Gateway),可以在技能内部实现带有退避策略的重试。可以使用tenacity等重试库。
  • 优雅降级:如果某个非核心的技能暂时不可用(例如,查询天气的服务挂了),你的Skill Manager或上层应用应该能处理这种情况。一种模式是,在注册技能时标记其“健康状态”,如果技能连续失败,可以暂时将其从提供给LLM的工具列表中移除,并让LLM告知用户“该功能暂时不可用”。

5.3 用户上下文管理混乱

在多用户环境中,错误地将用户A的grant_id用于用户B的技能操作,会导致严重的数据混乱和安全问题。

  • 建立强关联:确保你的会话管理系统坚如磐石。在Web应用中,通常通过加密的Cookie或Bearer Token来识别用户。这个Token必须与你数据库中的user_id以及存储的nylas_grant_id精确对应。
  • 中间件验证:在处理每个请求的管道中,尽早进行身份验证和上下文加载。如果加载失败(例如会话无效或未找到授权),应立即终止请求,返回明确的错误,而不是继续执行技能。
  • 日志记录用户轨迹:在技能执行的日志中,必须始终包含user_id。这样,一旦出现问题,你可以清晰地追踪到是哪个用户的操作链发生了错误。

5.4 技能响应格式不兼容

LLM期望工具执行后返回一个字符串格式的content。但你的技能可能返回一个复杂的字典。

  • 标准化响应格式:虽然Nylas Skills框架可能定义了基础的响应结构,但你最好在技能内部或Skill Manager层做一个标准化处理。确保返回给LLM的content是一个对用户友好的、描述性的字符串,同时可以在结构化的result字段中包含机器可读的详细信息。
    # 在SkillManager.execute_skill中或技能内部 execution_result = skill.execute(...) # 将结果格式化为LLM易读的字符串 if execution_result.get(“success”): llm_content = f“操作成功。{execution_result.get(‘message’)}” else: llm_content = f“操作失败。原因:{execution_result.get(‘error’)}” # 同时保留结构化结果供应用自身使用 final_output = { “content_for_llm”: llm_content, “structured_result”: execution_result }

6. 超越邮件:Skills的生态想象与扩展

Nylas Skills虽然由一家邮件API公司发起,但其设计是通用化的。它的真正威力在于成为任何AI助手的标准化“技能总线”。你可以为其编写连接任何服务的技能。

扩展思路1:集成内部业务系统为你的AI助手编写query_order_status技能,连接公司内部的订单数据库;编写create_support_ticket技能,连接Jira或Zendesk;编写generate_sales_report技能,连接数据仓库。这样,员工可以直接用自然语言向AI助手查询业务数据或触发流程,极大提升效率。

扩展思路2:连接物联网与硬件如果你有智能家居设备,可以编写turn_on_lightset_thermostat技能。AI助手在理解“我有点冷”之后,可以调用set_thermostat技能,将温度调高。这需要技能后端与你的IoT平台API进行通信。

扩展思路3:组合技能与工作流单个技能能力有限,但技能可以组合。LLM可以顺序调用多个技能来完成复杂任务。例如,用户说:“帮我找出去年联系过的所有客户,并给他们发一封新年问候邮件。” LLM可以规划并执行:1. 调用search_contacts_by_year技能(去年)。2. 对上一步的结果,循环调用send_email技能。这需要LLM具备一定的规划能力,或者由你的应用后端来编排这个多步骤的工作流。

开发你自己的技能库当你积累了多个技能后,可以将其模块化、库化。你可以创建一个内部的“技能商店”,让团队其他成员可以轻松发现、复用你开发的技能。Nylas Skills的开源协议也鼓励你回馈社区,将一些通用的、不涉及商业机密的技能(如search_webget_weather)开源出来,丰富整个生态。

在我自己的实践中,将AI助手从“聊天机器人”升级为“行动机器人”的最大挑战,从来不是语言模型本身的理解能力,而是如何安全、可靠地将它的“想法”落地。Nylas Skills框架提供了一套优雅的范式来解决这个问题。它迫使你将模糊的“AI能力”拆解成一个个边界清晰、安全可控的“技能单元”,这本身就是一个非常好的软件工程实践。开始可能只需要一个发送邮件的技能,但随着你不断添加新的技能模块,你会发现你的AI助手的能力在以积木式的方式增长,而整个系统的复杂度和风险却得到了有效的管理和隔离。这或许就是构建下一代AI原生应用所需要的基础设施思维。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 4:46:44

ESP32-S3驱动BLDC电机:FOCn模块解析与应用

1. FOCn模块:基于ESP32-S3的中功率BLDC驱动方案解析去年在调试一台六足机器人时,我遇到了无刷电机驱动的难题——市面上大多数驱动板要么功率不足,要么缺乏灵活的编程接口。直到发现PLab团队开发的FOCn模块,这个基于ESP32-S3的开源…

作者头像 李华
网站建设 2026/5/7 4:43:30

C++20终极指南:std::make_shared对数组的完整支持解析

C20终极指南:std::make_shared对数组的完整支持解析 【免费下载链接】modern-cpp-features A cheatsheet of modern C language and library features. 项目地址: https://gitcode.com/gh_mirrors/mo/modern-cpp-features C20标准为开发者带来了众多实用特性…

作者头像 李华
网站建设 2026/5/7 4:36:36

PM2-VSCode集成方案:在IDE内实现Node.js进程可视化与一键管理

1. 项目概述:一个为开发者定制的PM2-VSCode集成方案 如果你和我一样,长期在Node.js生态里摸爬滚打,那你对PM2这个进程管理器一定不陌生。它几乎成了Node.js应用在生产环境部署的“标配”,守护进程、负载均衡、日志管理&#xff0…

作者头像 李华
网站建设 2026/5/7 4:35:33

如何快速掌握高级机器学习:深度学习算法进阶的完整指南

如何快速掌握高级机器学习:深度学习算法进阶的完整指南 【免费下载链接】data-science 📊 Path to a free self-taught education in Data Science! 项目地址: https://gitcode.com/gh_mirrors/da/data-science GitHub 加速计划 / da / data-scie…

作者头像 李华
网站建设 2026/5/7 4:31:29

VisionFive 2 Lite:19.9美元RISC-V开发板评测与优化指南

1. VisionFive 2 Lite开箱:19.9美元起的RISC-V开发板新选择 当树莓派的价格逐渐攀升到让人犹豫的水平时,StarFive带着VisionFive 2 Lite杀入了低价开发板市场。这块信用卡大小的板子搭载了JH7110S四核RISC-V处理器,基础版仅售19.9美元&#x…

作者头像 李华