- 人工智能
- AI 应用
- 交互助手
- AI Agent
【免费下载链接】ironclaw
IronClaw is an Agent OS focused on privacy, security and extensibility
导读
google-drive.get_file是 IronClaw Agent OS 中 Google Drive 扩展包(crates/extensions/packages/google-drive)提供的一个只读工具,用于按文件 ID 获取单个 Drive 文件/文件夹的元数据(名称、类型、大小、所有者、共享状态、所在目录等),而不下载其内容。本文以该工具的操作提示文档为核心骨架,结合其输入 Schema、WASM 实现、扩展 Manifest 与契约测试,完整剖析"Agent 如何安全、规范地读取 Google Drive 文件元数据"这条能力链路,读完后你将掌握该工具的调用契约、底层 API 实现、凭据注入与错误处理机制,以及它在整个扩展打包体系中的运作方式。
一、get_file 的定位:Google Drive 扩展包中的"轻量元数据读取"能力
google-drive是一个data-only 扩展包(无 Rust crate,可移植工具半部分以 WASM guest 形式交付),扩展 ID 为google-drive,共暴露 12 个工具(google-drive.list_files…google-drive.list_shared_drives)外加[auth.google]认证面,详见其 README.md。
在这 12 个工具中,get_file承担的是最基础的"单文件元数据查询"职责,与周边工具形成明确分工:
| 工具 | 职责 |
|---|---|
google-drive.list_files | 按 Drive 查询语法搜索/列出文件,定位目标file_id |
google-drive.get_file | 按file_id读取单个文件的元数据(本文主角) |
google-drive.download_file | 下载文件内容为文本(内部会先调用 get_file 获取元数据) |
google-drive.update_file | 重命名、移动、加星、改描述(移动时也会先调用 get_file) |
从源码结构可以推断,get_file是许多下游操作的前置依赖:download_file在下载前需要先拿到mime_type判断是普通文件还是 Google Workspace 文件(决定走alt=media下载还是/export导出),见 api.rs;update_file在移动文件时需要先读取当前parents才能构造removeParents参数。因此理解get_file是理解整个 Drive 扩展包读取链路的基础。
二、操作提示文档:面向模型的操作契约
本文的关联文档位于 get_file.md,全文如下:
Get file metadata.
The host selects this operation from the capability id. Provide only the parameters described by the input schema; do not include an action field.
这段看似简短的两句话,实际上是 IronClaw 扩展体系中的模型可见操作契约,包含三条关键约束:
- 能力语义:该工具只做一件事——获取文件元数据(
Get file metadata.),不包含内容下载或写入行为。 - 操作选择由宿主完成:
The host selects this operation from the capability id——Agent 无需也不能自行声明要执行哪个操作,宿主运行时根据能力 ID(google-drive.get_file)确定具体动作。 - 禁止携带 action 字段:
do not include an action field——模型只允许按 input schema 提供参数。
2.1 "宿主选择操作"的源码印证
这条契约在 WASM guest 的入口 lib.rs 中有严格实现:
action_from_context从调用上下文的capability_id解析动作名,将google-drive.get_file映射为get_file,其余 11 个能力 ID 同理映射,未知 ID 返回unsupported_google_drive_capability错误;params_with_action在把参数交给 serde 反序列化前,先检查是否包含action字段——如果 Agent 违反 prompt 约束擅自传入action,会被直接判定为invalid_parameters输入错误(lib.rs中if obj.contains_key("action") { return Err(input_failure("invalid_parameters")); })。
也就是说,这条 prompt 不是建议性文案,而是与 guest 代码硬性校验一一对应的契约:动作由宿主注入,模型越权声明动作即失败。
2.2 prompt 文档在扩展包中的流转方式
该 prompt 文档并非孤立的说明文件,而是扩展资产的正式组成部分:
- 在 manifest.toml 中,
google-drive.get_file工具通过prompt_doc_ref = "prompts/google-drive/get_file.md"引用它,且visibility = "model",表明其内容会暴露给模型; - 打包时由 gsuite.rs 中的
google_wasm_assets!宏通过include_bytes!将prompts/google-drive/get_file.md与同名 input schema、WASM 二进制一起嵌入包资产(asset 路径为prompts/google-drive/get_file.md); - 与同目录其他工具的 prompt 相比,
get_file的提示保持极简,因为它没有可选参数、没有查询语法说明、没有下载/导出细节——只有一个必填的file_id,全部语义由 schema 承载。对比 list_files.md(附有 Drive 查询语法示例)和 download_file.md(说明二进制文档自动转文本),可以看到 prompt 详略程度与工具参数复杂度是严格匹配的。
三、输入契约:JSON Schema 与 serde 的双重校验
get_file的输入 Schema 位于 get_file.input.v1.json,全文如下:
{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Google Drive get_file", "description": "Get file metadata.", "type": "object", "required": ["file_id"], "properties": { "file_id": { "type": "string", "description": "The file ID." } }, "additionalProperties": false }要点:
- 唯一参数
file_id(字符串,必填),即 Drive 文件/文件夹的资源 ID(形如1aB2cD3eF4gH5iJ6...的长字符串); additionalProperties: false意味着不接受任何额外字段;- 该工具没有任何可选参数——元数据读取不需要分页、查询或导出类型。
3.1 与 serde 层的契约一致性
输入参数在 guest 端由 types.rs 中的带标签枚举GoogleDriveAction约束:
#[serde(tag = "action", rename_all = "snake_case")] pub enum GoogleDriveAction { /// Get file metadata. GetFile { /// The file ID. file_id: String, }, // ...其余 11 个变体 }该类型同时派生JsonSchema,由lib.rs的schema()方法在运行时生成对外公布的 schema(每个枚举变体成为oneOf分支,且各自的required数组独立),确保"广告给模型的 schema"与"serde 强制执行的解析契约"永不漂移。
types.rs的测试直接印证了这一设计动机:
get_file_requires_file_id_at_serde_layer:{"action":"get_file"}(缺file_id)必须在 serde 层被拒绝,而{"action":"get_file","file_id":"abc123"}必须通过;schema_marks_file_id_required_for_get_file:生成的 schema 中get_file分支的required必须同时包含action与file_id;schema_does_not_require_file_id_for_list_files:list_files分支的required只能是["action"],防止file_id在错误上下文中被误判为必填。
测试注释中还记录了历史教训:此前手写 schema 把所有变体字段都声明为顶层可选,导致模型经常构造出缺file_id的畸形调用,运行时才报missing field 'file_id';改用 schemars 派生后,模型在构造调用前就能看到字段是否必填。
四、实现剖析:WASM 中的 get_file 调用链
get_file的完整执行链路为:
execute → execute_inner → action_from_context(capability_id) // google-drive.get_file → "get_file" → params_with_action(params, action) // 注入 action 字段、拒绝模型自带 action → serde 反序列化为 GoogleDriveAction::GetFile { file_id } → api::get_file(&file_id) → 序列化 FileResult 返回核心实现在 api.rs:
pub fn get_file(file_id: &str) -> Result<FileResult, GuestFailure> { let path = format!( "files/{}?fields={}&supportsAllDrives=true", url_encode(file_id), FILE_FIELDS ); let response = api_call("GET", &path, None)?; let parsed: serde_json::Value = serde_json::from_str(&response).map_err(|e| serialization_failure(&e))?; Ok(FileResult { file: parse_file(&parsed) }) }4.1 请求构造细节
- 请求目标:
GET https://www.googleapis.com/drive/v3/files/{file_id}; supportsAllDrives=true恒定携带:即使文件位于共享云端硬盘(Shared Drive)也能正常访问;fields参数精确裁剪响应,只请求下面这组元数据字段(常量FILE_FIELDS):
id, name, mimeType, description, size, createdTime, modifiedTime, webViewLink, parents, shared, starred, trashed, ownedByMe, driveId, owners(emailAddress, displayName)使用fields显式声明字段列表,既减小响应体积,也让返回值结构完全可控可预测。
4.2 统一的 HTTP 封装
所有 Drive API 调用都经过api_call封装(api.rs),它做三件事:
- 通过
host::http_request发起请求——这是 IronClaw WASM 宿主提供的 HTTP 能力,凭据注入与限流都由宿主完成,WASM 工具本身永远看不到 OAuth token(api.rs文件头注释明确说明这一点); - 非 2xx 状态码统一走
api_status_error错误映射; - 响应体按 UTF-8 解码,解码失败映射为
invalid_utf8_response执行错误。
对模型而言,get_file是一个"无副作用、只读、单次请求"的轻量操作:不需要 Content-Type、没有请求体、没有 multipart 组装,是所有 Drive 操作中最简单直接的一条路径。
五、返回结构:DriveFile 元数据模型逐字段解读
get_file的返回值由FileResult { file: DriveFile }包装(types.rs),parse_file负责把 Drive API 响应 JSON 映射为结构化DriveFile。各字段及其含义如下:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 文件 ID |
name | string | 文件名/文件夹名 |
mime_type | string | MIME 类型;application/vnd.google-apps.folder表示文件夹 |
is_folder | bool | 由mime_type == "application/vnd.google-apps.folder"推导,方便模型快速判断 |
description | string? | 文件描述(可为空) |
size | string? | 文件大小(字符串形式,Drive API 以字符串返回字节数) |
created_time/modified_time | string? | 创建/修改时间(RFC 3339) |
web_view_link | string? | 浏览器打开链接 |
parents | string[] | 父目录 ID 列表(Drive 中一个文件可有多个父目录) |
shared/starred/trashed | bool | 是否共享、是否加星、是否在回收站 |
owned_by_me | bool | 是否本人所有 |
drive_id | string? | 所属共享云端硬盘 ID(个人盘为空) |
owners | Owner[] | 所有者列表,每项含emailAddress与displayName |
parse_file对每个字段都做了容错:缺失时对可选字段返回None,对布尔字段回退为false,对数组字段回退为空数组,绝不因单字段缺失导致整个调用失败。输出侧还有配套的宽松 schema raw_output.v1.json(additionalProperties: true),表示输出由 WASM 工具序列化、结构以实际返回为准。
对 Agent 而言,一次get_file调用即可回答诸如"这个文件多大、谁拥有、在哪个目录、是否已共享/已加星/在回收站"等问题,作为是否值得download_file的决策依据。
六、错误处理与失败语义
get_file的失败路径经过精心设计,见 api.rs:
6.1 HTTP 状态码映射
- 401:映射为
ErrorKind::AuthRequired,错误码固定为google_api_error_status_401——这是给宿主的可执行信号,用于触发重新授权流程; - 其他非 2xx 状态码:映射为
ErrorKind::Client,错误码为api_status_{status}(如api_status_404、api_status_429),消息中附带服务名与响应正文; - 无错误码兜底为
google_api_transport_error。
6.2 宿主传输层错误映射
transport_failure将宿主 HTTP 能力的各类错误(AuthRequired、Input、OutputTooLarge、Executor、NetworkDenied、Client、OperationFailed)逐一映射为 guest 侧对应的ErrorKind,保证错误分类在宿主与 guest 之间语义一致。
6.3 消息长度边界
所有自由文本错误消息都经过bounded_message截断到 512 字符以内——guest 永远不应向宿主交出无界字符串(宿主侧后续还会再做二次截断与清洗),避免恶意响应撑爆错误通道。
对应的单元测试覆盖了这些语义:api_status_error_401_maps_to_auth_required(401 → AuthRequired + 固定错误码)、api_status_error_non_401_maps_to_client(429 → Client +api_status_429,且消息包含rate limited)。
七、安全与权限模型:只读、按需授权、凭据不可见
get_file的安全设计可以从 manifest.toml 中完整读出:
[[tools]] origin_gate_matrix = { loop_run = "gated_unless_granted", product = "forbidden", automation = "forbidden" } id = "google-drive.get_file" description = "Get file metadata." effects = ["network", "use_secret"] default_permission = "ask" visibility = "model" input_schema_ref = "schemas/google-drive/get_file.input.v1.json" prompt_doc_ref = "prompts/google-drive/get_file.md" [[tools.credentials]] handle = "google_runtime_token" vendor = "google" scopes = ["https://www.googleapis.com/auth/drive.readonly"] audience = { scheme = "https", host = "www.googleapis.com" } injection = { type = "header", name = "authorization", prefix = "Bearer " }四个关键安全维度:
- 最小权限 OAuth 范围:
get_file只申请drive.readonly只读 scope(写操作如upload_file、delete_file才用drive全量 scope),与"只读元数据"的语义严格对应; - 效果声明:
effects = ["network", "use_secret"],不含external_write——它在能力层面就被声明为无外部写入副作用; - 默认询问:
default_permission = "ask",模型每次调用该工具都需要用户按需授权;origin_gate_matrix进一步限定:只能在loop_run场景以"未授权则门禁"(gated_unless_granted)方式使用,product与automation场景直接forbidden; - 凭据不可见:凭据句柄
google_runtime_token由宿主以Authorization: Bearer <token>头注入(injection = { type = "header", name = "authorization", prefix = "Bearer " }),WASM guest 全程接触不到 OAuth token;宿主 HTTP 能力同时负责限流。
此外,google是一个跨扩展共享的凭据权威(vendor):Gmail、Docs、Sheets、Slides 与 Drive 共用同一个 OAuth 客户端,注册表契约测试extensions_sharing_one_provider_project_the_same_auth_provider(manifest_v2_contract.rs)明确验证:Gmail 与 Google Drive 是不同的扩展 ID,但投影出的认证提供者都是google命名空间。[auth.google]段配置了 OAuth2 授权码流程(authorization endpoint、token endpoint、PKCEs256、access_type=offline换取刷新令牌),并针对 Google"testing 发布状态的应用刷新令牌闲置 7 天过期"的机制,配置了keepalive_idle_seconds = 604800的宿主保活刷新。
部署侧,管理员需要在[admin_configuration]中配置google_oauth_client_id与google_oauth_client_secret(后者标记为secret = true),供所有 Google 系扩展共享使用。
八、在扩展体系中的打包与投影
google-drive包由ironclaw_extension_support::packages::gsuite模块负责嵌入与投影,google_drive_bundle()(gsuite.rs)通过google_wasm_assets!宏一次性打包:
manifest.toml(声明 12 个工具、认证面、管理员配置);- 每个操作的
schemas/google-drive/{operation}.input.v1.json; - 每个操作的
prompts/google-drive/{operation}.md(含本文主角get_file.md); schemas/google-drive/raw_output.v1.json(宽松输出 schema);wasm/google_drive_tool.wasm(编译产物,guest 源码在wasm-src/,WIT 世界为lanes/ironclaw_wasm/wit/tool.wasm中的sandboxed-tool)。
WASM 产物有专门的保鲜检查脚本scripts/ci/check-wasm-artifact-freshness.py,保证提交的.wasm与wasm-src/源码一致;manifest 投影则由cargo test -p ironclaw_extension_registry验证。模型最终通过注册表看到的能力形态是:工具google-drive.get_file+ 认证面[auth.google],其中 prompt 文档与 input schema 成为模型可读的调用指南。
九、典型使用链路
在实际的 Agent 工作流中,get_file通常出现在这样的链路中:
- 定位:
google-drive.list_files用查询(如name contains '报告' and mimeType = 'application/pdf' and trashed = false)找到候选文件,得到file_id; - 甄别:
google-drive.get_file读取元数据,判断大小、所有者、共享状态,决定是否值得进一步处理; - 读取:
google-drive.download_file下载内容为文本(二进制文档自动转提取文本); - 操作:必要时再走
update_file/share_file/trash_file等写操作(这些操作需要用户按需授权)。
get_file因为是纯只读、单参数、无副作用的操作,是模型在"不确定某个文件是什么"时最安全的探询手段——一次调用即可获得完整的元数据画像,而不会触发任何外部写入。
结语
从 3 行 prompt 文档出发,google-drive.get_file展示了 IronClaw 扩展体系的一贯设计哲学:契约即代码、最小权限、凭据与决策分离。操作提示文档向模型声明"只提供 schema 参数、不要带 action",guest 代码用capability_id解析 + serde 严格反序列化把这条契约变成硬约束;schema 由 schemars 从 Rust 类型自动派生,杜绝手写漂移;OAuth 凭据由宿主注入、scope 按工具粒度最小化、效果声明与门禁矩阵层层设防。理解这一个工具,就理解了整个 Google Drive 扩展包(乃至全部 WASM 工具包)的运作范式。
如果你想继续深入,推荐按此顺序阅读仓库源码:get_file.md 原文档 → input schema → types.rs → api.rs → lib.rs → manifest.toml → gsuite.rs 打包模块。
- 人工智能
- AI 应用
- 交互助手
- AI Agent
【免费下载链接】ironclaw
IronClaw is an Agent OS focused on privacy, security and extensibility
相关推荐
IronClaw Google Sheets 扩展解析:get_spreadsheet 元数据操作的设计与实现
IronClaw Google Sheets 扩展解析:get_spreadsheet 元数据操作的设计与实现 本篇文章聚焦 IronClaw 开源仓库中 Go
人工智能AI 应用交互助手AI AgentIronClaw 扩展实战:Google Slides `get_presentation` 工具解析与演示文稿元数据读取
IronClaw 扩展实战:Google Slides get_presentation 工具解析与演示文稿元数据读取 本篇技术指南聚焦 IronClaw 开源
人工智能AI 应用交互助手AI AgentIronClaw Google Drive 扩展:download_file 文件内容读取能力全解析
IronClaw Google Drive 扩展:download_file 文件内容读取能力全解析 导读 google drive.download_file
人工智能AI 应用交互助手AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考