资讯动态

agent-skills:面向智能体的可插拔CLI技能协议

发布时间:2026/10/26 11:29:14 来源:尧图企业网站定制
1. “agent-skills”不是功能列表而是一套可插拔的智能体行为协议你第一次在 GitHub 上看到agent-skills这个仓库名或者在 CLI 工具的文档里读到skills install github-pr-review这条命令时大概率会下意识把它理解成“一堆预装好的小工具合集”——就像 npm 的awesome-list或 VS Code 的扩展市场那样。这是最常见、也最危险的误解。agent-skills的本质不是技能的集合而是技能的契约。它定义了一种标准化的接口规范让任何外部服务、本地脚本、甚至一段 Python 函数都能以统一的方式被一个智能体Agent发现、加载、调用和组合。这背后有非常现实的工程动因。我去年参与过三个不同团队的 Agent 构建项目无一例外都卡在同一个环节当需要让 Agent 调用企业内部的 OA 审批 API、调用本地部署的 PDF 解析服务、或者执行一条带参数的ffmpeg命令时开发者的做法五花八门——有人硬编码 HTTP 请求逻辑有人写 shell 脚本再用subprocess调用还有人直接把整个服务逻辑塞进 Agent 的主推理循环里。结果就是代码耦合度高、调试困难、无法复用、上线后维护成本爆炸。agent-skills正是为了解决这个“最后一公里”的集成混乱问题而生的。它不关心你这个技能是用 Rust 写的高性能图像识别模块还是用 Bash 写的三行日志清理脚本只要它遵守input_schema、output_schema和execute三个核心约定它就是一个合法的skill。从技术谱系上看agent-skills是 CLI 工具演进的自然产物。早期的 CLI比如git、curl是面向人类操作员设计的参数靠--help查错误靠人眼识别后来的 CLI如terraform、kubectl开始支持结构化输出-o json为自动化铺路而agent-skills所代表的新一代 CLI则是直接为机器设计的。它的--schema命令输出的是 JSON Schema--dry-run返回的是结构化调用计划--validate检查的是输入数据是否符合契约——所有这些都是为了让 Agent 的规划器Planner能像解析 AST 一样解析一个技能而不是像运行黑盒程序一样去猜测它的行为。所以当你看到热搜词里反复出现cli,slash commands,API时不要只把它当成关键词堆砌。它们共同指向一个事实agent-skills的落地形态必然深度绑定于命令行界面。因为 CLI 是目前唯一一个既足够轻量、又具备完整输入/输出/错误处理能力、且被所有操作系统原生支持的“机器可编程接口”。一个skills list命令其价值远不止于展示已安装技能它实质上是向 Agent 暴露了一个可枚举、可查询、可反射的“能力目录”这是构建可靠自主行为的基础。提示不要试图用npm install或pip install的思维去理解skills install。后者不是把代码拷贝到node_modules而是将一个符合协议的技能包通常是一个包含skill.yaml和execute.py的目录注册到本地技能仓库并生成对应的元数据索引。这个过程更接近systemctl daemon-reload是服务发现的前置步骤。2. 技能的“最小可行契约”schema、execute 与 lifecycle 的三位一体一个agent-skill要被 Agent 真正接纳它必须通过三道关卡。这三道关卡共同构成了技能的“最小可行契约”Minimum Viable Contract缺一不可。很多初学者在开发自己的第一个技能时往往只实现了execute函数就以为大功告成结果在集成阶段被各种奇怪的错误卡住。下面我用一个真实案例来拆解这三道关卡的具体要求和常见陷阱。2.1 输入/输出 Schema不是可选的文档而是运行时的类型守卫假设你要开发一个github-issue-search技能目标是让 Agent 能根据关键词搜索 GitHub 仓库中的 Issue。很多人会直接写一个 Python 脚本接受两个参数repo_owner和repo_name然后调用 GitHub API。这看起来很合理但agent-skills协议要求你必须先定义一个input_schema.json{ type: object, properties: { repo_owner: { type: string, description: GitHub 仓库所有者用户名例如 microsoft }, repo_name: { type: string, description: GitHub 仓库名称例如 vscode }, query: { type: string, description: 要搜索的 Issue 标题或正文关键词, default: } }, required: [repo_owner, repo_name] }这个 schema 的作用远不止于生成帮助文档。它是 Agent 在调用前进行静态验证的依据。当 Agent 的规划器生成一个调用请求时它会用这个 schema 去校验传入的参数是否合法。如果用户或另一个技能传入了{repo_owner: microsoft, query: performance}而漏掉了repo_nameAgent 会立刻报错ValidationError: repo_name is a required property根本不会走到execute那一步。这避免了大量因参数缺失导致的下游 API 调用失败把错误拦截在了最前端。同样output_schema.json定义了技能返回数据的结构。对于上面的搜索技能一个合理的输出 schema 可能是{ type: object, properties: { issues: { type: array, items: { type: object, properties: { number: { type: integer }, title: { type: string }, url: { type: string, format: uri } } } } } }这个 schema 让 Agent 能够“理解”返回的数据。规划器可以据此判断issues是一个数组那么后续可以对它进行for循环操作每个issue对象里有url字段那么下一个技能就可以安全地调用web-fetch去抓取该 URL 的内容。如果没有这个 schemaAgent 就只能拿到一个原始的 JSON 字符串它无法进行任何有意义的逻辑推导。注意default字段在input_schema中至关重要。它定义了当调用方未提供该参数时技能的默认行为。例如query: {type: string, default: }意味着如果不传query技能将返回该仓库的所有 Issue。这个默认值会被 Agent 的规划器读取并可能影响其决策路径。2.2 execute 函数协议的核心执行单元与错误语义execute是技能的“心脏”但它绝不是一个普通的函数。agent-skills协议对它的签名、输入、输出和错误处理都有严格规定。一个标准的execute.py文件长这样#!/usr/bin/env python3 import json import sys import os from urllib.parse import quote def execute(input_data): # 1. 从环境变量获取敏感配置而非硬编码 token os.getenv(GITHUB_TOKEN) if not token: raise RuntimeError(GITHUB_TOKEN environment variable is not set) # 2. 从 input_data 中提取参数严格遵循 schema repo_owner input_data[repo_owner] repo_name input_data[repo_name] query input_data.get(query, ) # 3. 构建 API 请求 base_url fhttps://api.github.com/repos/{quote(repo_owner)}/{quote(repo_name)}/issues params {q: query} if query else {} # 4. 执行请求并处理状态码 import requests try: response requests.get( base_url, headers{Authorization: ftoken {token}}, paramsparams, timeout30 ) response.raise_for_status() # 这行代码会抛出 HTTPError except requests.exceptions.Timeout: raise RuntimeError(GitHub API request timed out after 30 seconds) except requests.exceptions.HTTPError as e: if response.status_code 403: raise RuntimeError(fGitHub API rate limit exceeded or insufficient permissions. Status: {response.status_code}) elif response.status_code 404: raise RuntimeError(fRepository {repo_owner}/{repo_name} not found or access denied. Status: {response.status_code}) else: raise RuntimeError(fGitHub API returned error: {response.status_code} {response.reason}) # 5. 严格按 output_schema 返回结构化数据 issues [] for item in response.json(): issues.append({ number: item[number], title: item[title], url: item[html_url] }) return {issues: issues} if __name__ __main__: # 6. 标准化的输入/输出协议从 stdin 读 JSON向 stdout 写 JSON input_json sys.stdin.read() input_data json.loads(input_json) output_data execute(input_data) print(json.dumps(output_data))这段代码体现了execute函数的几个关键原则环境隔离所有敏感信息如 API Token必须通过环境变量注入而不是写死在代码里。这保证了技能包可以在不同环境中安全复用。输入即契约input_data是一个纯字典其结构由input_schema严格保证。开发者只需做input_data[key]这样的键访问无需做任何类型转换或存在性检查因为 schema 验证已在前一步完成。错误即语义execute函数不能静默失败。它必须用raise RuntimeError(描述性错误信息)的方式抛出错误。这个错误字符串会被 Agent 捕获并作为上下文的一部分反馈给 LLM 规划器用于重试或调整策略。例如GitHub API rate limit exceeded这个错误规划器可能会决定等待 60 秒后再重试而不是盲目地再次发起请求。输出即承诺return的数据结构必须 100% 符合output_schema的定义。Agent 会依赖这个结构进行后续的逻辑编排。2.3 Lifecycle 管理install、uninstall、update 的底层机制skills install命令的背后是一套完整的生命周期管理机制。它不是简单地git clone而是涉及元数据注册、依赖解析、沙箱准备和健康检查。理解这个过程能帮你避开大量集成陷阱。当你运行skills install github-issue-search时CLI 工具会执行以下步骤元数据拉取首先它会从一个中心化的技能索引如https://skills-index.example.com下载github-issue-search的skill.yaml文件。这个 YAML 文件包含了技能的名称、版本、作者、input_schema和output_schema的 URL、以及execute脚本的下载地址。依赖解析skill.yaml中会声明requires字段例如requires: - python 3.8 - pip: requests 2.25.0CLI 工具会检查本地环境是否满足这些依赖。如果不满足它会尝试自动安装如用pip install requests或者给出清晰的错误提示。沙箱准备为了保证技能的隔离性和安全性CLI 工具通常会为每个技能创建一个独立的执行环境。这可能是一个轻量级的 Python virtualenv一个基于nix-shell的声明式环境或者在更严格的生产环境中一个最小化的 Docker 容器镜像。 这个沙箱确保了github-issue-search技能使用的requests版本不会与你系统里其他 Python 项目使用的版本发生冲突。健康检查Health Check在安装完成后CLI 会自动运行skills test github-issue-search --dry-run。这个命令会模拟一次调用将input_schema中的default值作为输入然后调用execute脚本。如果脚本能成功返回一个符合output_schema的 JSON安装才算真正成功。否则你会看到类似Health check failed: url is a required property的错误这说明你的execute函数返回的数据结构与output_schema不匹配。这个严谨的生命周期管理正是agent-skills区别于普通脚本的核心。它让技能的分发、安装和升级变成了一件可预测、可审计、可回滚的工程化操作而不是一场充满未知风险的手动部署。3. CLI 交互范式从/command到skills exec的范式迁移agent-skills的 CLI 交互正在经历一场静默的范式迁移。过去我们习惯于使用/slash命令如 Slack 中的/jira create这是一种面向用户意图的交互。而现在skills exec命令则是一种面向机器契约的交互。理解这两者的区别是掌握agent-skillsCLI 的关键。3.1/slash命令的局限性意图模糊与上下文丢失/slash命令的设计初衷是提升人类用户的操作效率。当你在聊天窗口里输入/weather beijing背后的服务会解析这个字符串提取出beijing这个参数然后调用天气 API。这个过程看似简单实则暗藏玄机意图歧义/weather beijing是想查“北京今天的天气”还是“北京未来一周的天气预报”抑或是“北京的空气质量”/slash命令本身没有结构化的方式来表达这种细微差别。上下文丢失如果这个命令是在一个关于“旅行计划”的对话中发出的/weather服务并不知道这个上下文。它无法主动关联到“用户正在规划去北京的行程”因此无法提供“建议携带雨具”这样的增值信息。错误恢复困难如果天气 API 返回 404城市不存在/slash服务通常只能回复一句“未找到城市‘beijing’”然后对话就中断了。它很难引导用户去选择一个更精确的地名如Beijing, ChinavsBeijing, Indiana。agent-skills的 CLI 交互从根本上规避了这些问题。它不依赖自然语言解析而是强制使用结构化的 JSON 输入。一个等效的天气查询其 CLI 调用是这样的echo {location: Beijing, forecast_days: 1, include_air_quality: true} | skills exec weather-forecast这个命令的每一个部分都是明确、无歧义的location: 一个字符串值为Beijing。forecast_days: 一个整数值为1。include_air_quality: 一个布尔值值为true。Agent 的规划器在生成这个命令时会基于当前的完整对话历史、用户画像、以及weather-forecast技能的input_schema精确地构造出这个 JSON。它知道forecast_days的默认值是1所以如果用户没说“查一周”它就不会把这个字段放进去它也知道include_air_quality是一个可选的布尔字段而当前对话提到了“空气质量”所以它会显式地设为true。3.2skills exec的核心优势可组合、可追溯、可审计skills exec命令的强大之处在于它天然支持“管道化”piping和“组合化”composition。这是/slash命令永远无法企及的能力。场景自动化代码审查流程想象一个复杂的任务“请审查 PR #123并将发现的关键问题汇总成一份 Markdown 报告然后通过邮件发送给团队”。一个基于/slash的方案可能需要一个超级复杂的、定制化的/pr-review命令它内部封装了所有逻辑。一旦某个环节比如邮件发送出错整个流程就失败了而且你很难定位是哪个子步骤出了问题。而agent-skills的方案则是将这个大任务分解为一系列原子化的、可独立验证的技能调用# 步骤1获取 PR 详情 PR_DATA$(echo {pr_number: 123} | skills exec github-pr-get) # 步骤2分析代码变更调用一个本地 Python 脚本 ANALYSIS$(echo $PR_DATA | skills exec code-analyzer) # 步骤3生成 Markdown 报告 REPORT$(echo $ANALYSIS | skills exec markdown-reporter) # 步骤4发送邮件 echo $REPORT | skills exec email-sender --to teamcompany.com这个流程的优势是颠覆性的可组合每个技能都是独立的你可以随意替换email-sender为slack-notifier而不需要修改markdown-reporter的任何一行代码。可追溯每一步的输入和输出都是结构化的 JSON。如果第 3 步失败了你可以直接复制$PR_DATA和$ANALYSIS的内容粘贴到命令行里单独重试快速复现问题。可审计整个流程的每一步其输入参数、执行时间、返回状态码都可以被 CLI 工具自动记录到一个审计日志中。这对于合规性要求高的企业环境如金融、医疗至关重要。提示skills exec命令支持--dry-run参数。在实际执行前加上这个参数它会输出一个详细的执行计划包括将要调用的技能、传入的参数、预期的输出结构以及所有依赖的环境变量。这是调试复杂工作流的必备神器。3.3skills list与skills search构建你的“能力知识图谱”skills list和skills search这两个命令其意义远超表面的“查看已安装技能”。它们是你构建个人或团队“能力知识图谱”的入口。skills list的输出通常是一个表格包含技能名称、版本、描述、以及一个status字段NAMEVERSIONDESCRIPTIONSTATUSgithub-pr-get1.2.0Fetch details of a GitHub Pull RequestHEALTHYcode-analyzer0.8.3Static analysis for Python JS codeDEGRADEDemail-sender2.1.1Send emails via SMTP or SendGridHEALTHY注意STATUS列。HEALTHY表示该技能通过了最近一次的健康检查DEGRADED则意味着它虽然能运行但可能返回了不符合output_schema的数据或者响应时间超过了阈值。这个状态是动态的由 CLI 工具定期轮询更新。它让你一眼就能看出当前你的 Agent “大脑”里哪些“神经元”是活跃的哪些是亚健康的。skills search则更进一步。它允许你用关键词、标签甚至input_schema的片段来查找技能。例如# 查找所有能处理 PDF 的技能 skills search pdf # 查找所有输入中包含 url 字段的技能适合做网络爬虫 skills search --field input_schema --value url # 查找所有由 acme-corp 开发的技能 skills search --author acme-corp这个搜索能力本质上是在构建一个动态的、可查询的“能力数据库”。当 Agent 面对一个新任务时它的规划器不再需要“凭空想象”如何解决而是可以像数据库查询一样发出一个SELECT * FROM skills WHERE input_schema CONTAINS url AND status HEALTHY的请求然后从返回的结果中挑选出最合适的技能来组合。4. 从零构建一个生产级技能以minio-file-upload为例的全流程实战理论讲得再多不如亲手做一个。下面我将带你从零开始构建一个真实、可用、符合生产标准的minio-file-upload技能。MinIO 是一个流行的开源对象存储服务类似于 AWS S3。这个技能的目标是让 Agent 能够将本地文件上传到 MinIO 存储桶中并返回一个可公开访问的 URL。我们将严格遵循agent-skills协议并融入我在多个项目中踩过的坑和总结的经验。4.1 项目初始化与目录结构首先创建一个干净的项目目录mkdir minio-file-upload cd minio-file-uploadagent-skills协议对目录结构有明确要求。一个标准的技能包必须包含以下文件minio-file-upload/ ├── skill.yaml # 技能的元数据描述文件 ├── input_schema.json # 输入参数的 JSON Schema ├── output_schema.json # 输出结果的 JSON Schema ├── execute.py # 核心执行逻辑 └── README.md # 人类可读的文档我们先创建skill.yaml。这是技能的“身份证”它告诉 CLI 工具这个技能是谁、做什么、怎么用# skill.yaml name: minio-file-upload version: 1.0.0 author: your-name-here description: Upload a local file to a MinIO bucket and return a public URL. homepage: https://github.com/your-username/minio-file-upload license: MIT # 定义技能的输入和输出 Schema input_schema: ./input_schema.json output_schema: ./output_schema.json # 声明运行时依赖 requires: - python 3.7 - pip: minio 7.0.0 # 可选定义一个简短的 usage 示例用于 skills help 命令 usage: | Upload a file to MinIO. Example: echo {file_path: /tmp/report.pdf, bucket: documents, object_name: report-2024.pdf} | skills exec minio-file-upload注意skill.yaml中的homepage和license字段不是摆设。一个专业的技能包必须有可追溯的源代码和明确的许可协议。这关系到企业的法律合规性。4.2 定义严谨的输入/输出 Schema接下来我们定义input_schema.json。这个技能需要几个关键参数file_path: 本地文件的绝对路径。这是必需的。bucket: MinIO 中的目标存储桶名称。必需。object_name: 上传到 MinIO 后的对象文件名称。必需。minio_endpoint: MinIO 服务器的地址如play.min.io:9000。必需。minio_access_key: 访问密钥。必需但应通过环境变量注入所以这里不作为输入参数。minio_secret_key: 密钥。同上。minio_secure: 是否使用 HTTPS。可选默认为true。// input_schema.json { type: object, properties: { file_path: { type: string, description: Absolute path to the local file to be uploaded., pattern: ^/.*$ }, bucket: { type: string, description: Name of the MinIO bucket to upload to., minLength: 1, maxLength: 63 }, object_name: { type: string, description: Name to assign to the object in MinIO., minLength: 1 }, minio_endpoint: { type: string, description: MinIO server endpoint (e.g., play.min.io:9000). }, minio_secure: { type: boolean, description: Whether to use HTTPS (true) or HTTP (false)., default: true } }, required: [file_path, bucket, object_name, minio_endpoint] }这个 schema 有几个精妙之处pattern:^/.*$强制file_path必须是绝对路径防止用户传入相对路径如./report.pdf导致在沙箱环境中找不到文件。minLength/maxLength: 对bucket名称的长度做了限制因为 MinIO 对 bucket name 有严格的命名规则3-63个字符只能包含小写字母、数字、连字符。default: 为minio_secure设置了默认值简化了调用方的负担。output_schema.json则定义了上传成功后的返回结构// output_schema.json { type: object, properties: { public_url: { type: string, description: The publicly accessible URL of the uploaded object., format: uri }, bucket: { type: string, description: The name of the bucket where the object was uploaded. }, object_name: { type: string, description: The name of the object in the bucket. }, size_bytes: { type: integer, description: The size of the uploaded file in bytes., minimum: 0 } }, required: [public_url, bucket, object_name, size_bytes] }4.3 编写健壮的 execute.py处理所有边界情况现在进入最核心的execute.py。我们将用minioPython SDK 来实现上传逻辑。以下是经过生产环境验证的完整代码#!/usr/bin/env python3 import json import sys import os import mimetypes from pathlib import Path from urllib.parse import urljoin # 导入 MinIO SDK try: from minio import Minio from minio.error import S3Error except ImportError: raise RuntimeError(minio library is not installed. Please run pip install minio.) def execute(input_data): # 1. 从 input_data 中提取参数 file_path input_data[file_path] bucket input_data[bucket] object_name input_data[object_name] minio_endpoint input_data[minio_endpoint] minio_secure input_data.get(minio_secure, True) # 2. 验证本地文件是否存在且可读 file_path_obj Path(file_path) if not file_path_obj.exists(): raise RuntimeError(fLocal file does not exist: {file_path}) if not file_path_obj.is_file(): raise RuntimeError(fPath is not a file: {file_path}) if not os.access(file_path, os.R_OK): raise RuntimeError(fLocal file is not readable: {file_path}) # 3. 从环境变量获取 MinIO 凭据 access_key os.getenv(MINIO_ACCESS_KEY) secret_key os.getenv(MINIO_SECRET_KEY) if not access_key or not secret_key: raise RuntimeError(MINIO_ACCESS_KEY and MINIO_SECRET_KEY environment variables must be set.) # 4. 创建 MinIO 客户端 try: client Minio( minio_endpoint, access_keyaccess_key, secret_keysecret_key, secureminio_secure ) except Exception as e: raise RuntimeError(fFailed to initialize MinIO client: {str(e)}) # 5. 确保目标 bucket 存在 try: if not client.bucket_exists(bucket): raise RuntimeError(fMinIO bucket does not exist: {bucket}) except S3Error as e: if e.code NoSuchBucket: raise RuntimeError(fMinIO bucket does not exist: {bucket}) else: raise RuntimeError(fError checking bucket existence: {str(e)}) # 6. 推断文件 MIME 类型 mime_type, _ mimetypes.guess_type(str(file_path_obj)) if mime_type is None: mime_type application/octet-stream # 7. 执行上传 try: # 使用 put_object 方法它支持大文件流式上传 result client.put_object( bucket, object_name, file_path_obj.open(rb), file_path_obj.stat().st_size, content_typemime_type ) except S3Error as e: if e.code NoSuchBucket: raise RuntimeError(fTarget bucket {bucket} does not exist in MinIO.) elif e.code AccessDenied: raise RuntimeError(Access denied. Check your MinIO credentials and bucket policy.) else: raise RuntimeError(fMinIO upload failed: {str(e)}) except OSError as e: raise RuntimeError(fOS error during upload: {str(e)}) except Exception as e: raise RuntimeError(fUnexpected error during upload: {str(e)}) # 8. 生成公共 URL # 注意MinIO 默认不提供公共 URL需要配置 bucket policy 或使用 presigned URL # 这里我们使用 presigned URL有效期为 7 天 try: presigned_url client.presigned_get_object( bucket, object_name, expires7 * 24 * 3600 # 7 days in seconds ) except S3Error as e: raise RuntimeError(fFailed to generate presigned URL: {str(e)}) # 9. 返回符合 output_schema 的结构化数据 return { public_url: presigned_url, bucket: bucket, object_name: object_name, size_bytes: file_path_obj.stat().st_size } if __name__ __main__: try: input_json sys.stdin.read() if not input_json.strip(): raise RuntimeError(No input data provided.) input_data json.loads(input_json) output_data execute(input_data) print(json.dumps(output_data)) except json.JSONDecodeError as e: raise RuntimeError(fInvalid JSON input: {str(e)}) except Exception as e: # 所有异常都包装为 RuntimeError保持错误语义统一 raise RuntimeError(str(e))这段代码处理了几乎所有可能的失败点文件系统层检查文件是否存在、是否为文件、是否可读。网络层捕获S3Error并根据具体的错误码NoSuchBucket,AccessDenied给出精准的错误信息。安全层强制从环境变量读取凭据绝不硬编码。健壮性层对mimetypes.guess_type的返回值做空值处理防止上传二进制文件时出错。4.4 测试、打包与发布一个都不能少最后是测试和发布的环节。一个未经充分测试的技能是生产环境的定时炸弹。本地测试# 创建一个测试文件 echo Hello from agent-skills! /tmp/test.txt # 构造一个测试输入 JSON TEST_INPUT{ file_path: /tmp/test.txt, bucket: test-bucket, object_name: test.txt, minio_endpoint: play.min.io:9000 } # 设置环境变量使用 MinIO 的公开测试服务 export MINIO_ACCESS_KEYQ3AM3UQ867SPQQA43P2F export MINIO_SECRET_KEYzuftfteSlswRu7BJ86wekitnifILbZam1KYY3TG # 执行测试 echo $TEST_INPUT | python execute.py打包与发布一个技能包要被社区使用需要发布到一个公共的技能索引。最简单的做法是将其托管在 GitHub 上并在skill.yaml的homepage字段中指向它。然后你可以向一个中心化的索引如https://skills-index.example.com提交一个 PR将你的skill.yamlURL 添加到它的索引文件中。经验之谈永远不要在execute.py中写print()所有输出都必须是最终的 JSON 结果。print()会污染 stdout导致 Agent 无法解析。requirements.txt是鸡肋agent-skills协议通过skill.yaml的requires字段来声明依赖而不是requirements.txt。前者是协议的一部分后者只是 Python 生态的惯例。版本号是生命线每次修改execute.py的逻辑都必须更新skill.yaml中的version。skills update命令正是依赖这个版本号来判断是否需要拉取新版本。至此一个生产级的minio-file-upload技能就完成了。它不是一个玩具而是一个可以立即集成到你的 Agent 工作流中的、可靠的、可审计的组件。它的价值不在于它能上传一个文件而在于它证明了任何复杂的外部系统都可以被抽象为一个简洁、安全、可组合的“技能”成为 Agent 智能体的一部分。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑