IronClaw GitHub 扩展:用 `github.get_authenticated_user` 准确识别已认证的 GitHub 用户
IronClaw GitHub 扩展:用 github.get_authenticated_user 准确识别已认证的 GitHub 用户
本文围绕 IronClaw 开源仓库中 GitHub 扩展包(github)提供的 github.get_authenticated_user 能力展开,讲解它是什么、在何种场景下必须调用、为什么不能从 github.list_repos 的返回结果推断认证用户身份,以及该能力在 WASM 扩展中的底层实现、认证注入与测试验证。读完本文,你将掌握在 IronClaw 中正确回答"我是谁 / 当前连接的是哪个 GitHub 账号"类问题的完整方法,并理解其安全设计依据。
github.get_authenticated_user 是 IronClaw 内置 GitHub 工具集中专门用于识别当前配置 token 所认证的 GitHub 用户的只读能力,其 prompt 文档位于 crates/extensions/packages/github/prompts/github/get_authenticated_user.md,属于 GitHub 扩展包(crates/extensions/packages/github)49 个工具面(49 tools)之一。
能力定位:何时必须调用它
根据关联文档,github.get_authenticated_user 的唯一职责是:
使用
github.get_authenticated_user来识别由已配置 token 完成认证的 GitHub 用户。
它面向的问题非常明确,包括:
- "who am I on GitHub?"(我在 GitHub 上是谁?)
- "which GitHub account is connected?"(当前连接的是哪个 GitHub 账号?)
- 在 Agent 准备对外陈述"当前认证的 GitHub 登录名"这一事实之前,必须先调用本能力取得确凿依据。
也就是说,这是一条"事实获取"工具而非"操作"工具:它不修改任何资源,只负责把"这个 token 背后到底是哪个账号"这一信息从 GitHub 侧取回来。从扩展清单 manifest.toml 中可以看到该工具的定义:
[[tools]]
origin_gate_matrix = { loop_run = "gated_unless_granted", product = "forbidden", automation = "forbidden" }
id = "github.get_authenticated_user"
description = "Get the authenticated GitHub user for the configured token."
effects = ["network", "use_secret"]
default_permission = "allow"
visibility = "model"
input_schema_ref = "schemas/github/get_authenticated_user.input.v1.json"
prompt_doc_ref = "prompts/github/get_authenticated_user.md"
其中两个值得注意的配置点:
effects = ["network", "use_secret"]:调用该工具会产生一次网络请求,并使用机密凭据(GitHub token)。IronClaw 的能力系统据此进行效应声明与门控管理。default_permission = "allow":该工具默认放行,无需用户逐次确认(与create_issue、create_pull_request等写操作默认ask形成对比),因为它是一个只读的、低风险的身份查询能力。
关键陷阱:不要从 list_repos 的结果推断登录名
关联文档给出了本能力存在的最重要理由,也是 Agent 最容易犯的错误:
不要从
github.list_repos返回的仓库所有者推断已认证的登录名;/user/repos可能包含认证用户能够访问的组织所拥有的仓库。
这条警告的底层依据可以从源码得到印证。github.list_repos 的实现在 crates/extensions/packages/github/wasm-src/src/api/repos.rs 中:
pub(crate) fn list_repos(
repo_type: Option<RepoListType>,
page: Option<u32>,
limit: Option<u32>,
) -> Result<String, String> {
validate_page(page)?;
validate_limit(limit)?;
let limit = limit.unwrap_or(30).min(100); // Cap at 100
let mut path = format!("/user/repos?per_page={}", limit);
...
github_request("GET", &path, None)
}
它请求的端点是 /user/repos——这是"当前用户可访问的仓库"列表,而非"我拥有的仓库"列表。其返回结果中的 owner 字段可能是个人账号,也可能是该用户有权限访问的组织账号。因此,如果 Agent 看到列表里某个仓库的 owner 是 nearai,就断言"当前登录用户是 nearai",就会产生事实性错误:真实情况可能只是"该 token 拥有访问 nearai 组织仓库的权限"。
仓库内的单元测试也直接验证了 /user/repos 端点会携带 type 过滤参数(见 crates/extensions/packages/github/wasm-src/src/lib.rs 中 list_repos_appends_type_for_authenticated_user、list_repos_appends_supported_types_for_authenticated_user 等测试,断言路径形如 /user/repos?per_page=2&type=member、/user/repos?per_page=3&type=all 等),进一步说明该端点天然是"认证用户视角的可访问仓库集合"。
结论:唯一可靠的身份来源是 GitHub 的 /user 端点(即本工具),而不是任何仓库列表的 owner 字段。
底层实现:从能力 ID 到 HTTP 请求的完整调用链
github.get_authenticated_user 并非独立编写的业务逻辑,而是 GitHub 扩展 WASM 模块中的一个标准动作。整个调用链如下:
1. 能力 ID 映射为动作(dispatch)
调用时,宿主上下文会携带 {"capability_id":"github.get_authenticated_user"},分发层在 crates/extensions/packages/github/wasm-src/src/dispatch.rs 中将其映射到具体实现:
GitHubAction::GetAuthenticatedUser {} => get_authenticated_user(),
动作类型 GitHubAction::GetAuthenticatedUser 定义于 crates/extensions/packages/github/wasm-src/src/types.rs:
#[serde(rename = "get_authenticated_user")]
GetAuthenticatedUser {},
2. 动作实现:请求 /user 端点
核心实现位于 crates/extensions/packages/github/wasm-src/src/api/repos.rs:
pub(crate) fn get_authenticated_user() -> Result<String, String> {
github_request("GET", "/user", None)
}
可以看到它不发请求体、不做参数校验(因为该能力本就不需要任何输入参数),直接以 GET 方式请求 GitHub REST API 的 /user 端点。
3. 请求封装:经宿主 HTTP 出口出网
github_request 的实现在 crates/extensions/packages/github/wasm-src/src/request.rs 中,它定义了请求的完整形态:
const GITHUB_API_ROOT: &str = "https://api.github.com";
const GITHUB_API_VERSION: &str = "2026-03-10";
const HTTP_TIMEOUT_MS: u32 = 10_000;
pub(crate) fn github_request(
method: &str,
path: &str,
body: Option<String>,
) -> Result<String, String> {
let url = format!("{GITHUB_API_ROOT}{path}");
let headers = serde_json::json!({
"Accept": "application/vnd.github+json",
"Content-Type": "application/json",
"X-GitHub-Api-Version": GITHUB_API_VERSION,
"User-Agent": "IronClaw-GitHub-Reborn-WASM"
});
...
let response = crate::near::agent::host::http_request(
method,
&url,
&headers.to_string(),
body_bytes.as_deref(),
Some(HTTP_TIMEOUT_MS),
)
...
}
这里的关键点在于:网络请求并不是在 WASM guest 内部直接发起的,而是通过 near::agent::host::http_request 委托给宿主(host)的 HTTP 出口(HTTP egress)执行。这正对应关联文档中"该能力通过宿主 HTTP 出口读取 GitHub API"的描述。好处是:出网行为受宿主网络策略约束,凭据注入也由宿主管控,而不是把 token 交给不受控的 guest 代码。
响应处理逻辑还包括:2xx 直接透传响应体;422 且响应体符合 GitHub "Validation Failed" 结构时返回稳定错误码;401 时会捕获 provider 返回的 message 字段(截断至 512 字符)供宿主用于认证门控诊断。
4. 输入契约:空参数工具
github.get_authenticated_user 的输入 schema 位于 crates/extensions/packages/github/schemas/github/get_authenticated_user.input.v1.json,是一个不含任何属性的空对象:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GitHub get_authenticated_user input",
"type": "object",
"additionalProperties": false,
"properties": {},
"required": []
}
additionalProperties: false 意味着:如果调用方(模型)试图传入任何多余参数,校验会直接失败。该 schema 在 WASM 中通过 crates/extensions/packages/github/wasm-src/src/schema.rs 的 include_str! 嵌入,作为工具输入校验的依据。
5. 输出:GitHub 原始 JSON 透传
响应体为 GitHub /user 端点返回的原始 JSON(不做字段裁剪),模型可直接从中读取 login、type 等字段。仓库测试 crates/extensions/packages/github/wasm-src/src/lib.rs 的 get_authenticated_user_uses_user_endpoint 用例给出了典型返回形态:
test_support::set_response(Ok(json!({
"login": "serrrfirat",
"type": "User"
})
.to_string()));
let output = execute_inner(
r#"{}"#,
Some(r#"{"capability_id":"github.get_authenticated_user"}"#),
)
.expect("github.get_authenticated_user should return authenticated user");
let output: serde_json::Value =
serde_json::from_str(&output).expect("mock output should be JSON");
assert_eq!(output["login"], "serrrfirat");
assert_eq!(output["type"], "User");
let requests = test_support::requests();
assert_eq!(requests.len(), 1);
assert_eq!(requests[0].method, "GET");
assert_eq!(requests[0].body, None);
assert_eq!(requests[0].path, "/user");
该测试同时验证了三件事:调用会精确发出 GET /user(无请求体)、返回的 JSON 中 login 与 type 字段可被正确解析、且请求数恰好为 1(不存在额外请求)。
认证与凭据注入:token 从哪里来、如何被使用
github.get_authenticated_user 的 effects 包含 use_secret,意味着它必须依赖一个已配置的 GitHub 凭据才能工作。凭据的完整链路定义在 manifest.toml 中。
凭据句柄与注入方式
[[tools.credentials]]
handle = "github_runtime_token"
vendor = "github"
audience = { scheme = "https", host = "api.github.com" }
injection = { type = "header", name = "authorization", prefix = "token " }
placeholder_env = "GH_TOKEN"
也就是说,每个 GitHub 工具(包括本能力)都声明使用句柄 github_runtime_token,其受众(audience)是 https://api.github.com,注入方式为向 authorization 请求头写入 token <GH_TOKEN>。placeholder_env = "GH_TOKEN" 则提示该凭据对应的占位环境变量为 GH_TOKEN。
product-auth 账户配置
在扩展清单底部,[auth.github] 定义了该厂商的认证配置:
[auth.github]
method = "api_key"
display_name = "GitHub personal access token"
fields = [ { handle = "github_runtime_token", label = "Personal access token", secret = true } ]
validation = { method = "GET", url = "https://api.github.com/user", success_status = [200], inject = { handle = "github_runtime_token", type = "header", name = "authorization", prefix = "Bearer " } }
这印证了关联文档中的最后一句"该能力需要配置 GitHub product-auth 账户":用户需要在 IronClaw 中配置一个 GitHub Personal Access Token,作为该 product-auth 账户的凭据。校验方式本身也很有启发性——宿主会以 GET https://api.github.com/user(同样的 /user 端点)并注入 Authorization: Bearer <token> 来验证 token 是否有效,成功状态码为 200。这与 github.get_authenticated_user 的实现端点完全一致,二者共享"查询 /user 即验证身份"的同一事实基础。
在 IronClaw 中的实际使用场景与最佳实践
综合关联文档与源码,推荐的使用姿势如下:
- 在需要陈述账号身份时优先调用:当用户询问"我在 GitHub 上是谁""当前连接了哪个账号",或 Agent 需要在对话/报告/审计日志中声称"以账号 X 的身份执行了操作"时,先调用
github.get_authenticated_user取得login字段作为事实来源。 - 把身份查询与仓库操作解耦:不要因为
github.list_repos、github.get_repo等返回结果中的owner恰好等于某个登录名,就推断"当前认证用户就是该 owner"。/user/repos的视角是"token 可访问的仓库集合",包含组织仓库,owner 字段不能作为身份证据。唯一的身份证据是/user端点。 - 善用其零参数与低权限设计:由于输入为空对象、默认权限为
allow、仅产生只读网络请求,可以在流程开始时作为"身份探针"安全调用,无需额外授权确认;其失败(如401或 egress 被拒)也能快速暴露 token 配置问题——例如请求失败时的错误码体系(github_api_error_status_401、github_api_egress_denied等)都定义在 crates/extensions/packages/github/wasm-src/src/request.rs 中,便于排查。
延伸阅读
- 能力 prompt 文档:crates/extensions/packages/github/prompts/github/get_authenticated_user.md
- 扩展清单与全部 49 个工具、认证配置:crates/extensions/packages/github/manifest.toml
- 扩展包总览(data-only 包、WASM 运行时、测试命令):crates/extensions/packages/github/README.md
- 输入 schema:crates/extensions/packages/github/schemas/github/get_authenticated_user.input.v1.json
- 核心实现:crates/extensions/packages/github/wasm-src/src/api/repos.rs(
get_authenticated_user函数)、crates/extensions/packages/github/wasm-src/src/request.rs(请求封装与错误码)、crates/extensions/packages/github/wasm-src/src/dispatch.rs(动作分发) - 行为测试:crates/extensions/packages/github/wasm-src/src/lib.rs(
get_authenticated_user_uses_user_endpoint等用例)