凭证管理
智能体配置决定使用哪些工具,Vault(保管库)决定访问第三方 MCP 服务时使用谁的身份。两者分别配置:同一智能体可以处理多个业务用户的任务,由应用在创建会话时选择对应的 vault_ids。
例如,应用为不同业务用户生成协作系统摘要时,应分别保存用户授权,并在每次创建会话前校验授权归属。不要把第三方令牌放进任务消息或系统提示,也不要让客户端直接决定使用哪个 Vault。
在 Portal 中,您可以从会话详情的凭证库入口查看关联的 Vault 名称、ID 和归档状态,并进入凭证库详情。任务详情显示当前配置的凭证库;运行历史则显示该次会话的关联,后续修改任务配置不会改变历史关联 ID。信息暂时不可用时,页面保留 Vault ID 并提供重试。
划分调用身份与业务授权
| 配置 | 负责的身份 | 应用需要控制的边界 |
|---|---|---|
| MaaS API Key | 调用 AgentAPI 的账户 | 保留在应用服务端,见接入准备 |
| 智能体的 MCP 配置 | 任务可使用的服务与工具 | 只声明任务需要的服务;声明服务器不代表已经获得第三方授权 |
| Vault 中的第三方凭证 | 访问 MCP 服务的业务用户或服务身份 | 维护用户与 Vault 的映射,创建会话前检查归属与权限 |
账户内的访问范围
Vault 和凭证属于当前账户,账户内有权访问这些资源的 API Key 可以引用它们。
metadata中的业务用户 ID 只是标记,不形成用户级访问隔离。应用服务端必须校验客户端发起的任务与允许使用的 Vault,不能将vault_ids或external_user_id直接作为授权依据。
确定会话的访问范围
创建会话前,核对三个条件:
- 服务地址一致。 MCP 凭证通过
mcp_server_url匹配智能体配置的服务地址;没有匹配凭证时,AgentAPI 会尝试匿名连接。 - 第三方权限满足任务。 摘要查询通常只需读取权限;发布消息等写操作需另行授权。Vault 保存令牌,不会缩小令牌在第三方系统的权限。
- 授权属于当前任务。 根据应用服务端的用户映射选出 Vault,再将 ID 传入会话;智能体配置可以复用,用户授权不能混用。
一个会话最多引用 50 个 Vault,执行时最多匹配并注入 20 个凭证。多个 Vault 匹配同一 MCP 地址时,vault_ids 中第一个匹配的 Vault 优先;应避免用数组顺序掩盖重复授权配置。
配置并使用授权
下面的示例按“保存业务用户标识 → 添加第三方令牌 → 创建会话引用”的顺序配置授权。示例中的 Alice 是业务用户标记,不是 AgentAPI 创建的独立安全主体。
创建保管库并关联业务用户
为业务用户或服务身份创建 Vault,保存返回的 ID,并在应用自己的授权记录中关联该 ID。display_name 用于识别,metadata 用于检索与标记。
cURL
vault_id=$(curl --request POST "$AGENTAPI_BASE_URL/v1/vaults" \
--header "x-api-key: $AGENTAPI_API_KEY" \
--header "content-type: application/json" \
--data @- <<'EOF' | jq -r '.id'
{
"display_name": "Alice",
"metadata": {"external_user_id": "usr_abc123"}
}
EOF
)
echo "$vault_id" # "vlt_01ABC..."
Python
vault = client.beta.vaults.create(
display_name="Alice",
metadata={"external_user_id": "usr_abc123"},
)
print(vault.id) # "vlt_01ABC..."
TypeScript
const vault = await client.beta.vaults.create({
display_name: "Alice",
metadata: { external_user_id: "usr_abc123" },
});
console.log(vault.id); // "vlt_01ABC..."
C#
var vault = await client.Beta.Vaults.Create(new()
{
DisplayName = "Alice",
Metadata = new Dictionary<string, string> { ["external_user_id"] = "usr_abc123" },
});
Console.WriteLine(vault.ID); // "vlt_01ABC..."
Go
vault, err := client.Beta.Vaults.New(ctx, anthropic.BetaVaultNewParams{
DisplayName: "Alice",
Metadata: map[string]string{"external_user_id": "usr_abc123"},
})
if err != nil {
panic(err)
}
fmt.Println(vault.ID) // "vlt_01ABC..."
Java
var vault = client.beta().vaults().create(VaultCreateParams.builder()
.displayName("Alice")
.metadata(VaultCreateParams.Metadata.builder()
.putAdditionalProperty("external_user_id", JsonValue.from("usr_abc123"))
.build())
.build());
IO.println(vault.id()); // "vlt_01ABC..."
PHP
$vault = $client->beta->vaults->create(
displayName: 'Alice',
metadata: ['external_user_id' => 'usr_abc123'],
);
echo $vault->id . "\n"; // "vlt_01ABC..."
Ruby
vault = client.beta.vaults.create(
display_name: "Alice",
metadata: {external_user_id: "usr_abc123"}
)
puts vault.id # "vlt_01ABC..."
响应返回完整的 Vault 记录:
{
"type": "vault",
"id": "vlt_01ABC...",
"display_name": "Alice",
"metadata": { "external_user_id": "usr_abc123" },
"created_at": "2026-03-18T10:00:00Z",
"updated_at": "2026-03-18T10:00:00Z",
"archived_at": null
}
选择第三方鉴权方式
鉴权方式由 MCP 服务决定,不由智能体模型决定:
| MCP 服务接受的授权 | 凭证类型 | 令牌维护责任 |
|---|---|---|
| 业务用户通过 OAuth 授予的访问令牌 | mcp_oauth |
应用完成授权与刷新,再更新 Vault 中的令牌 |
| 固定 API Key 或个人访问令牌,以 Bearer 方式发送 | static_bearer |
应用根据第三方令牌有效期安排轮换 |
两种类型都以 mcp_server_url 匹配目标服务。凭证值(token、access_token、refresh_token、client_secret)只写入、不在 API 响应中返回;应用应保存凭证 ID,用于后续更新或撤销。
保存 OAuth 授权
下面的示例保存业务用户的访问令牌及刷新信息。保存 refresh 配置不会启动自动刷新:AgentAPI 当前不执行 OAuth 刷新,应用必须在令牌过期后完成刷新并更新凭证。
refresh.token_endpoint_auth.type 字段指定令牌刷新请求的认证方式:
none:公共客户端client_secret_basic:使用客户端密钥的 HTTP Basic 身份验证client_secret_post:客户端密钥位于 POST 请求体中
cURL
credential_id=$(curl --fail-with-body -sS "$AGENTAPI_BASE_URL/v1/vaults/$vault_id/credentials" \
-H "x-api-key: $AGENTAPI_API_KEY" \
-H "content-type: application/json" \
--data @- <<'EOF' | jq -r '.id'
{
"display_name": "Alice's Slack",
"auth": {
"type": "mcp_oauth",
"mcp_server_url": "https://mcp.slack.com/mcp",
"access_token": "xoxp-...",
"expires_at": "2099-12-31T23:59:59Z",
"refresh": {
"token_endpoint": "https://slack.com/api/oauth.v2.access",
"client_id": "1234567890.0987654321",
"scope": "channels:read chat:write",
"refresh_token": "xoxe-1-...",
"token_endpoint_auth": {"type": "client_secret_post", "client_secret": "abc123..."}
}
}
}
EOF
)
Python
credential = client.beta.vaults.credentials.create(
vault_id=vault.id,
display_name="Alice's Slack",
auth={
"type": "mcp_oauth",
"mcp_server_url": "https://mcp.slack.com/mcp",
"access_token": "xoxp-...",
"expires_at": "2099-12-31T23:59:59Z",
"refresh": {
"token_endpoint": "https://slack.com/api/oauth.v2.access",
"client_id": "1234567890.0987654321",
"scope": "channels:read chat:write",
"refresh_token": "xoxe-1-...",
"token_endpoint_auth": {"type": "client_secret_post", "client_secret": "abc123..."},
},
},
)
TypeScript
const credential = await client.beta.vaults.credentials.create(vault.id, {
display_name: "Alice's Slack",
auth: {
type: "mcp_oauth",
mcp_server_url: "https://mcp.slack.com/mcp",
access_token: "xoxp-...",
expires_at: "2099-12-31T23:59:59Z",
refresh: {
token_endpoint: "https://slack.com/api/oauth.v2.access",
client_id: "1234567890.0987654321",
scope: "channels:read chat:write",
refresh_token: "xoxe-1-...",
token_endpoint_auth: {
type: "client_secret_post",
client_secret: "abc123...",
},
},
},
});
C#
var credential = await client.Beta.Vaults.Credentials.Create(vault.ID, new()
{
DisplayName = "Alice's Slack",
Auth = new BetaManagedAgentsMcpOAuthCreateParams
{
Type = BetaManagedAgentsMcpOAuthCreateParamsType.McpOAuth,
McpServerUrl = "https://mcp.slack.com/mcp",
AccessToken = "xoxp-...",
ExpiresAt = DateTimeOffset.Parse("2099-12-31T23:59:59Z"),
Refresh = new()
{
TokenEndpoint = "https://slack.com/api/oauth.v2.access",
ClientID = "1234567890.0987654321",
Scope = "channels:read chat:write",
RefreshToken = "xoxe-1-...",
TokenEndpointAuth = new BetaManagedAgentsTokenEndpointAuthPostParam
{
Type = BetaManagedAgentsTokenEndpointAuthPostParamType.ClientSecretPost,
ClientSecret = "abc123...",
},
},
},
});
Go
credential, err := client.Beta.Vaults.Credentials.New(ctx, vault.ID, anthropic.BetaVaultCredentialNewParams{
DisplayName: anthropic.String("Alice's Slack"),
Auth: anthropic.BetaVaultCredentialNewParamsAuthUnion{
OfMCPOAuth: &anthropic.BetaManagedAgentsMCPOAuthCreateParams{
Type: anthropic.BetaManagedAgentsMCPOAuthCreateParamsTypeMCPOAuth,
MCPServerURL: "https://mcp.slack.com/mcp",
AccessToken: "xoxp-...",
ExpiresAt: anthropic.Time(time.Date(2099, time.December, 31, 23, 59, 59, 0, time.UTC)),
Refresh: anthropic.BetaManagedAgentsMCPOAuthRefreshParams{
TokenEndpoint: "https://slack.com/api/oauth.v2.access",
ClientID: "1234567890.0987654321",
Scope: anthropic.String("channels:read chat:write"),
RefreshToken: "xoxe-1-...",
TokenEndpointAuth: anthropic.BetaManagedAgentsMCPOAuthRefreshParamsTokenEndpointAuthUnion{
OfClientSecretPost: &anthropic.BetaManagedAgentsTokenEndpointAuthPostParam{
Type: anthropic.BetaManagedAgentsTokenEndpointAuthPostParamTypeClientSecretPost,
ClientSecret: "abc123...",
},
},
},
},
},
})
if err != nil {
panic(err)
}
Java
var credential = client.beta().vaults().credentials().create(vault.id(),
CredentialCreateParams.builder()
.displayName("Alice's Slack")
.auth(BetaManagedAgentsMcpOAuthCreateParams.builder()
.type(BetaManagedAgentsMcpOAuthCreateParams.Type.MCP_OAUTH)
.mcpServerUrl("https://mcp.slack.com/mcp")
.accessToken("xoxp-...")
.expiresAt(OffsetDateTime.parse("2099-12-31T23:59:59Z"))
.refresh(BetaManagedAgentsMcpOAuthRefreshParams.builder()
.tokenEndpoint("https://slack.com/api/oauth.v2.access")
.clientId("1234567890.0987654321")
.scope("channels:read chat:write")
.refreshToken("xoxe-1-...")
.clientSecretPostTokenEndpointAuth("abc123...")
.build())
.build())
.build());
PHP
$credential = $client->beta->vaults->credentials->create(
vaultID: $vault->id,
displayName: "Alice's Slack",
auth: ManagedAgentsMCPOAuthCreateParams::with(
type: 'mcp_oauth',
mcpServerURL: 'https://mcp.slack.com/mcp',
accessToken: 'xoxp-...',
expiresAt: new DateTimeImmutable('2099-12-31T23:59:59Z'),
refresh: ManagedAgentsMCPOAuthRefreshParams::with(
tokenEndpoint: 'https://slack.com/api/oauth.v2.access',
clientID: '1234567890.0987654321',
scope: 'channels:read chat:write',
refreshToken: 'xoxe-1-...',
tokenEndpointAuth: ManagedAgentsTokenEndpointAuthPostParam::with(
type: 'client_secret_post',
clientSecret: 'abc123...',
),
),
),
);
Ruby
credential = client.beta.vaults.credentials.create(
vault.id,
display_name: "Alice's Slack",
auth: {
type: "mcp_oauth",
mcp_server_url: "https://mcp.slack.com/mcp",
access_token: "xoxp-...",
expires_at: "2099-12-31T23:59:59Z",
refresh: {
token_endpoint: "https://slack.com/api/oauth.v2.access",
client_id: "1234567890.0987654321",
scope: "channels:read chat:write",
refresh_token: "xoxe-1-...",
token_endpoint_auth: {
type: "client_secret_post",
client_secret: "abc123..."
}
}
}
)
保存固定 Bearer 令牌
固定令牌不需要 OAuth 刷新配置。下面的示例将令牌绑定到一个 MCP 地址;如服务地址发生变化,应创建新的凭证,而非只更新令牌值。
cURL
curl --fail-with-body -sS "$AGENTAPI_BASE_URL/v1/vaults/$vault_id/credentials" \
-H "x-api-key: $AGENTAPI_API_KEY" \
-H "content-type: application/json" \
--data @- <<'EOF'
{
"display_name": "Linear API key",
"auth": {
"type": "static_bearer",
"mcp_server_url": "https://mcp.linear.app/mcp",
"token": "lin_api_your_linear_key"
}
}
EOF
Python
bearer_credential = client.beta.vaults.credentials.create(
vault_id=vault.id,
display_name="Linear API key",
auth={
"type": "static_bearer",
"mcp_server_url": "https://mcp.linear.app/mcp",
"token": "lin_api_your_linear_key",
},
)
TypeScript
const bearerCredential = await client.beta.vaults.credentials.create(vault.id, {
display_name: "Linear API key",
auth: {
type: "static_bearer",
mcp_server_url: "https://mcp.linear.app/mcp",
token: "lin_api_your_linear_key",
},
});
C#
var bearerCredential = await client.Beta.Vaults.Credentials.Create(vault.ID, new()
{
DisplayName = "Linear API key",
Auth = new BetaManagedAgentsStaticBearerCreateParams
{
Type = BetaManagedAgentsStaticBearerCreateParamsType.StaticBearer,
McpServerUrl = "https://mcp.linear.app/mcp",
Token = "lin_api_your_linear_key",
},
});
Go
bearerCredential, err := client.Beta.Vaults.Credentials.New(ctx, vault.ID, anthropic.BetaVaultCredentialNewParams{
DisplayName: anthropic.String("Linear API key"),
Auth: anthropic.BetaVaultCredentialNewParamsAuthUnion{
OfStaticBearer: &anthropic.BetaManagedAgentsStaticBearerCreateParams{
Type: anthropic.BetaManagedAgentsStaticBearerCreateParamsTypeStaticBearer,
MCPServerURL: "https://mcp.linear.app/mcp",
Token: "lin_api_your_linear_key",
},
},
})
if err != nil {
panic(err)
}
_ = bearerCredential
Java
var bearerCredential = client.beta().vaults().credentials().create(vault.id(),
CredentialCreateParams.builder()
.displayName("Linear API key")
.auth(BetaManagedAgentsStaticBearerCreateParams.builder()
.type(BetaManagedAgentsStaticBearerCreateParams.Type.STATIC_BEARER)
.mcpServerUrl("https://mcp.linear.app/mcp")
.token("lin_api_your_linear_key")
.build())
.build());
PHP
$bearerCredential = $client->beta->vaults->credentials->create(
vaultID: $vault->id,
displayName: 'Linear API key',
auth: ManagedAgentsStaticBearerCreateParams::with(
type: 'static_bearer',
mcpServerURL: 'https://mcp.linear.app/mcp',
token: 'lin_api_your_linear_key',
),
);
Ruby
bearer_credential = client.beta.vaults.credentials.create(
vault.id,
display_name: "Linear API key",
auth: {
type: "static_bearer",
mcp_server_url: "https://mcp.linear.app/mcp",
token: "lin_api_your_linear_key"
}
)
在会话中引用授权
确认业务用户有权使用前面创建的 Vault 后,将其 ID 写入会话的 vault_ids。示例为同一业务用户启动协作系统摘要任务:
cURL
session_id=$(curl --fail-with-body -sS $AGENTAPI_BASE_URL/v1/sessions \
-H "x-api-key: $AGENTAPI_API_KEY" \
-H "content-type: application/json" \
--data @- <<EOF | jq -r '.id'
{
"agent": {"type": "agent", "id": "$agent_id", "version": 1},
"environment_id": "$environment_id",
"vault_ids": ["$vault_id"],
"title": "Alice's Slack digest"
}
EOF
)
Python
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
vault_ids=[vault.id],
title="Alice's Slack digest",
)
TypeScript
const session = await client.beta.sessions.create({
agent: agent.id,
environment_id: environment.id,
vault_ids: [vault.id],
title: "Alice's Slack digest",
});
C#
var session = await client.Beta.Sessions.Create(new()
{
Agent = agent.ID,
EnvironmentID = environment.ID,
VaultIds = [vault.ID],
Title = "Alice's Slack digest",
});
Go
session, err := client.Beta.Sessions.New(ctx, anthropic.BetaSessionNewParams{
Agent: anthropic.BetaSessionNewParamsAgentUnion{
OfString: anthropic.String(agent.ID),
},
EnvironmentID: environment.ID,
VaultIDs: []string{vault.ID},
Title: anthropic.String("Alice's Slack digest"),
})
if err != nil {
panic(err)
}
Java
var session = client.beta().sessions().create(SessionCreateParams.builder()
.agent(agent.id())
.environmentId(environment.id())
.vaultIds(List.of(vault.id()))
.title("Alice's Slack digest")
.build());
PHP
$session = $client->beta->sessions->create(
agent: $agent->id,
environmentID: $environment->id,
vaultIDs: [$vault->id],
title: "Alice's Slack digest",
);
Ruby
session = client.beta.sessions.create(
agent: agent.id,
environment_id: environment.id,
vault_ids: [vault.id],
title: "Alice's Slack digest"
)
会话创建成功只说明配置已保存,不能证明第三方鉴权已通过。开始任务后,结合会话事件核对 MCP 调用结果:
| 现象 | 优先检查 |
|---|---|
| MCP 连接或调用返回鉴权错误 | 服务地址是否匹配,令牌是否过期或已被第三方撤销 |
| 可以读取但无法执行写操作 | 第三方令牌是否具有所需权限,工具配置是否允许该操作 |
| 使用了不符合预期的业务身份 | 应用选择的 Vault 是否正确,是否存在多个匹配凭证 |
更新授权并验证生效
凭证更新分为两类:更换令牌值时更新原凭证;变更服务或 OAuth 客户端时创建新凭证。
| 变更 | 操作 |
|---|---|
密钥值、display_name、OAuth 刷新信息 |
更新原凭证 |
mcp_server_url、token_endpoint、client_id 等结构性字段 |
归档旧凭证,创建新凭证 |
应用完成 OAuth 刷新或取得新令牌后,使用已保存的凭证 ID 更新。运行中的会话需要异步同步;同步完成后,后续出站请求才使用新值。
cURL
curl --fail-with-body -sS \
"$AGENTAPI_BASE_URL/v1/vaults/$vault_id/credentials/$credential_id" \
-H "x-api-key: $AGENTAPI_API_KEY" \
-H "content-type: application/json" \
--data @- <<'EOF' > /dev/null
{
"auth": {
"type": "mcp_oauth",
"access_token": "xoxp-new-...",
"expires_at": "2099-12-31T23:59:59Z",
"refresh": {"refresh_token": "xoxe-1-new-..."}
}
}
EOF
Python
client.beta.vaults.credentials.update(
credential.id,
vault_id=vault.id,
auth={
"type": "mcp_oauth",
"access_token": "xoxp-new-...",
"expires_at": "2099-12-31T23:59:59Z",
"refresh": {"refresh_token": "xoxe-1-new-..."},
},
)
TypeScript
await client.beta.vaults.credentials.update(credential.id, {
vault_id: vault.id,
auth: {
type: "mcp_oauth",
access_token: "xoxp-new-...",
expires_at: "2099-12-31T23:59:59Z",
refresh: {
refresh_token: "xoxe-1-new-...",
},
},
});
C#
await client.Beta.Vaults.Credentials.Update(credential.ID, new()
{
VaultID = vault.ID,
Auth = new BetaManagedAgentsMcpOAuthUpdateParams
{
Type = BetaManagedAgentsMcpOAuthUpdateParamsType.McpOAuth,
AccessToken = "xoxp-new-...",
ExpiresAt = DateTimeOffset.Parse("2099-12-31T23:59:59Z"),
Refresh = new() { RefreshToken = "xoxe-1-new-..." },
},
});
Go
_, err = client.Beta.Vaults.Credentials.Update(ctx, credential.ID, anthropic.BetaVaultCredentialUpdateParams{
VaultID: vault.ID,
Auth: anthropic.BetaVaultCredentialUpdateParamsAuthUnion{
OfMCPOAuth: &anthropic.BetaManagedAgentsMCPOAuthUpdateParams{
Type: anthropic.BetaManagedAgentsMCPOAuthUpdateParamsTypeMCPOAuth,
AccessToken: anthropic.String("xoxp-new-..."),
ExpiresAt: anthropic.Time(time.Date(2099, time.December, 31, 23, 59, 59, 0, time.UTC)),
Refresh: anthropic.BetaManagedAgentsMCPOAuthRefreshUpdateParams{
RefreshToken: anthropic.String("xoxe-1-new-..."),
},
},
},
})
if err != nil {
panic(err)
}
Java
client.beta().vaults().credentials().update(credential.id(),
CredentialUpdateParams.builder()
.vaultId(vault.id())
.auth(BetaManagedAgentsMcpOAuthUpdateParams.builder()
.type(BetaManagedAgentsMcpOAuthUpdateParams.Type.MCP_OAUTH)
.accessToken("xoxp-new-...")
.expiresAt(OffsetDateTime.parse("2099-12-31T23:59:59Z"))
.refresh(BetaManagedAgentsMcpOAuthRefreshUpdateParams.builder()
.refreshToken("xoxe-1-new-...")
.build())
.build())
.build());
PHP
$client->beta->vaults->credentials->update(
$credential->id,
vaultID: $vault->id,
auth: ManagedAgentsMCPOAuthUpdateParams::with(
type: 'mcp_oauth',
accessToken: 'xoxp-new-...',
expiresAt: new DateTimeImmutable('2099-12-31T23:59:59Z'),
refresh: ManagedAgentsMCPOAuthRefreshUpdateParams::with(refreshToken: 'xoxe-1-new-...'),
),
);
Ruby
client.beta.vaults.credentials.update(
credential.id,
vault_id: vault.id,
auth: {
type: "mcp_oauth",
access_token: "xoxp-new-...",
expires_at: "2099-12-31T23:59:59Z",
refresh: {refresh_token: "xoxe-1-new-..."}
}
)
核对同步与撤销状态
凭证轮换会为正在运行的云端沙箱创建异步同步任务。归档或删除 Vault、凭证时,AgentAPI 同样会更新仍可复用的沙箱注入规则。
凭证同步
轮换成功仅表示新密文已保存,运行中的沙箱仍需异步同步。同步重试耗尽时没有可查询的用户事件;请在下一次会话或沙箱连接时验证新凭证,并保存轮换请求的
X-Trace-ID供排障。
下表为 Vault 生命周期的 Webhook 事件,不通过会话 SSE 返回。可在 Portal 的“服务设置 → Webhook”选择订阅,接收服务的验签与可靠处理见 Webhook 通知。未接入 Webhook 时,应用应通过资源查询核对归档或删除状态,再通过第三方服务调用验证凭证可用性。
| 事件 | 触发条件 |
|---|---|
vault.archived |
Vault 已归档。同时会为每个底层凭证发出一个 vault_credential.archived 事件。 |
vault.deleted |
Vault 已删除。同时会为每个底层凭证发出一个 vault_credential.deleted 事件。 |
vault_credential.archived |
凭证已归档,可能是直接归档,也可能是 vault 归档的结果。 |
vault_credential.deleted |
凭证已删除,可能是直接删除,也可能是 vault 删除的结果。 |
vault_credential.refresh_failed |
预留事件类型;AgentAPI 当前不执行 OAuth token 自动刷新,也不会用它报告沙箱同步失败。 |
这些事件用于确认资源状态变化,不等同于第三方在线鉴权校验。AgentAPI 当前不提供 OAuth 在线校验接口,令牌可用性仍需通过实际服务访问确认。
停止使用并保留审计记录
业务用户撤销授权后,应用应停止为新会话选择该 Vault 或凭证,并归档或删除相应资源。归档适用于保留非敏感审计记录;删除适用于不再保留资源记录。两种操作都会触发沙箱注入规则更新,但运行中的同步仍是异步的,不能承诺立即撤回已经发出的请求。
- 列出 Vault 或凭证: 分页返回,最新的在前。默认排除已归档记录;传入
include_archived=true可一并返回。 - 归档 Vault:
POST /v1/vaults/{id}/archive。同时归档其中的凭证并清除密钥,保留记录用于审计。新会话不能再引用该 Vault。 - 归档凭证:
POST /v1/vaults/{id}/credentials/{cred_id}/archive。清除密钥负载,但保留mcp_server_url等非敏感描述信息用于审计。 - 删除 Vault 或凭证: 永久删除记录。需要保留审计信息时,请使用归档。
在 Portal 的 Vault 列表中,您可以按名称或 ID 搜索,并选择活跃、已归档或全部状态。搜索会去掉关键词首尾的空白,按字面量包含关系匹配 display_name 或 id;%、_ 和 ! 不作为通配符。搜索和状态筛选均在统计总数和分页前完成。
对应的 Portal 接口为 GET /portal/v1/vaults?page_index=1&q=关键词。q 和 status 必须与 page_index 一起使用;status=active 仅返回活跃 Vault,status=archived 仅返回已归档 Vault。查看全部状态时,省略 status 并传入 include_archived=true,两者不能同时使用。公开接口 GET /v1/vaults 不接受 q 或 status,凭证列表也不支持这两个参数。