Agent X-Ray
RuntimeNotesAbout
Notes/源码拆解/Claude Code Harness/第10章

第10章:权限模型 —— 六种模式与被外包的沙箱

12 分钟 · 更新于 2026-09-01

第10章:权限模型 —— 六种模式与被外包的沙箱

src/utils/permissions/ 有 24 个文件、9409 行。本章讲清三件事:六种权限模式、三类规则的优先级、以及一批连 bypass 模式也拦不住的检查。最后对照 Codex:Claude Code 把沙箱整个外包给了一个独立 npm 包,这是一个和 Codex 完全相反的取舍。


一、六种模式

ts
export const EXTERNAL_PERMISSION_MODES = [
  'acceptEdits',
  'bypassPermissions',
  'default',
  'dontAsk',
  'plan',
] as const

export type InternalPermissionMode = ExternalPermissionMode | 'auto' | 'bubble'
export const INTERNAL_PERMISSION_MODES = [
  ...EXTERNAL_PERMISSION_MODES,
  ...(feature('TRANSCRIPT_CLASSIFIER') ? (['auto'] as const) : ([] as const)),
] as const

[源码 src/types/permissions.ts:16-36]

模式标题符号语义
defaultDefault按规则来,不确定就问
planPlan Mode只读,不许改文件
acceptEditsAccept edits⏵⏵文件编辑自动放行
dontAskDon't Ask⏵⏵不弹窗(但 deny 规则仍生效)
bypassPermissionsBypass Permissions⏵⏵绕过权限
auto [内部]Auto mode⏵⏵用一个模型当分类器决定放不放行
bubble [内部]——子 agent 的权限冒泡到父终端

bubble 不在 INTERNAL_PERMISSION_MODES 里(不可由用户选),它是 fork 子 agent 专用的 [源码 src/tools/AgentTool/forkSubagent.ts:52]:

permissionMode: 'bubble' surfaces permission prompts to the parent terminal.

isExternalPermissionMode() 的实现值得看一眼 [源码 src/utils/permissions/PermissionMode.ts:97]:

ts
export function isExternalPermissionMode(mode: PermissionMode): mode is ExternalPermissionMode {
  // External users can't have auto, so always true for them
  if (process.env.USER_TYPE !== 'ant') return true
  return mode !== 'auto' && mode !== 'bubble'
}

外部构建里这个函数恒返回 true,因为那两个模式的代码根本没进产物。第 2 章那条 DCE 主线在这里又出现一次。


二、三类规则与它们的来源

ts
export type PermissionBehavior = 'allow' | 'deny' | 'ask'

export type PermissionRule = {
  source: PermissionRuleSource     // 从哪来
  ruleBehavior: PermissionBehavior // allow / deny / ask
  ruleValue: {
    toolName: string
    ruleContent?: string           // 可选的内容匹配,如 Bash(git push:*)
  }
}

[源码 src/types/permissions.ts:44, 73]

来源有 8 种(第 2 章那 5 个设置层,加上 3 个运行时来源):

ts
export type PermissionRuleSource =
  | 'userSettings' | 'projectSettings' | 'localSettings'
  | 'flagSettings' | 'policySettings'
  | 'cliArg' | 'command' | 'session'

session 是"用户在这次会话里点了'总是允许'",不落盘。 第 2 章那个 OTel 映射就是靠它区分"临时批准"和"永久批准"的。

规则内容的语法是 工具名(内容)

ts
function permissionRuleValueFromString(ruleString: string): PermissionRuleValue {
  const matches = ruleString.match(/^([^(]+)\(([^)]+)\)$/)
  if (!matches) return { toolName: ruleString }
  return { toolName: matches[1], ruleContent: matches[2] }
}

[源码 src/utils/sandbox/sandbox-adapter.ts:62]

所以 Bash 是"整个工具",Bash(git push:*) 是"内容匹配",mcp__server 是"这个 MCP 服务器的全部工具"。

空内容的 deny 规则会在工具进入模型视野之前就把工具过滤掉 [源码 src/tools.ts:257]:

ts
/**
 * Filters out tools that are blanket-denied by the permission context.
 * A tool is filtered out if there's a deny rule matching its name with no
 * ruleContent (i.e., a blanket deny for that tool).
 *
 * Uses the same matcher as the runtime permission check (step 1a), so MCP
 * server-prefix rules like `mcp__server` strip all tools from that server
 * before the model sees them — not just at call time.
 */

两层防御:模型看不见 + 真调了也会被拦。注释特别强调"用的是同一个匹配器"——如果两处匹配逻辑不一致,就会出现"模型看不到但其实能调"或者反过来的漏洞。


三、决策流水线:hasPermissionsToUseToolInner

这是权限系统的主函数,逻辑是一串带编号的步骤(源码里的编号就是 1a/1b/1c…)[源码 src/utils/permissions/permissions.ts:1158]:

text
1a. 整个工具被 deny 规则拦     → deny
1b. 整个工具有 ask 规则         → ask(除非沙箱可自动放行,见 §4)
1c. tool.checkPermissions()     → 工具自己的判断
1d. 工具说 deny                 → deny
1e. 工具需要真人交互且说 ask    → ask ★ bypass 也拦不住
1f. 内容级 ask 规则             → ask ★ bypass 也拦不住
1g. 安全检查(.git/ .claude/…) → ask ★ bypass 也拦不住
2a. 模式说 bypass               → allow
2b. 整个工具被 allow 规则允许    → allow
3.  passthrough → ask

顺序即优先级。 三个关键判断:

3.1 deny 永远第一

1a 在最前面,2a(bypass 模式)在很后面。所以:

bypassPermissions 模式绕不过 deny 规则。

这是整个模型最重要的一条性质。用户设了 Bash(rm -rf:*) 的 deny,那么无论开什么模式,它都不会执行。

3.2 三条 bypass 免疫

1e / 1f / 1g 都在 2a 之前,注释各自解释了为什么:

1e 需要真人交互的工具

ts
// 1e. Tool requires user interaction even in bypass mode
if (tool.requiresUserInteraction?.() && toolPermissionResult?.behavior === 'ask') {
  return toolPermissionResult
}

AskUserQuestion 这种工具的本质就是问用户——bypass 掉它没有任何意义。

1f 内容级 ask 规则

ts
// Content-specific ask rules from tool.checkPermissions take precedence
// over bypassPermissions mode. When a user explicitly configures a
// content-specific ask rule (e.g. Bash(npm publish:*)), … This must be
// respected even in bypass mode, just as deny rules are respected at step 1d.

用户显式写了"npm publish 要问我",那就是要问。 逻辑是:用户配了 bypassPermissions 是在说"常规操作别烦我",不是在说"我刚才那条规则不算数了"。

1g 安全检查

ts
// 1g. Safety checks (e.g. .git/, .claude/, .vscode/, shell configs) are
// bypass-immune — they must prompt even in bypassPermissions mode.
// checkPathSafetyForAutoEdit returns {type:'safetyCheck'} for these paths.

一批路径是硬保护的.git/(改历史)、.claude/(改 agent 自己的配置)、.vscode/(改编辑器任务,能执行代码)、shell 配置文件(.bashrc 等,下次开终端就执行)。

注意这四类的共同点:它们都是"改一下就能获得持久的、超出本次会话的执行能力"。这是一个很清晰的威胁模型。

可迁移的判断 ㉑ "绕过所有检查"这个模式必须有一份显式的免疫清单,而且清单的判据要能一句话说清。

Claude Code 的判据是:"改一下就能获得持久执行能力的东西"(agent 自己的配置、编辑器配置、shell 配置、版本历史)+ "用户显式配过的规则" + "本质就是问用户的工具"。三类各有各的理由,没有一条是"感觉危险"。

3.3 plan 模式的一个后门

ts
const shouldBypassPermissions =
  appState.toolPermissionContext.mode === 'bypassPermissions' ||
  (appState.toolPermissionContext.mode === 'plan' &&
    appState.toolPermissionContext.isBypassPermissionsModeAvailable)

如果用户本来是以 bypass 模式启动的,那么他进 plan 模式时也享受 bypass。 因为 plan 模式本身已经是只读了,再弹权限窗没意义。

3.4 checkRuleBasedPermissions:给钩子用的精简版

第 9 章那个 resolveHookPermissionDecision 调用的是另一个函数 checkRuleBasedPermissions() [源码 src/utils/permissions/permissions.ts:1071]。

对比一下就能看出设计:

hasPermissionsToUseToolInnercheckRuleBasedPermissions
1a deny 规则
1b ask 规则
1c 工具自查
1d 工具 deny
1e 需要交互
1f 内容级 ask
1g 安全检查
2a 模式 bypass
2b allow 规则
3 passthrough→ask返回 null

它只保留"会反对"的那些步骤,不保留"会放行"的那些。 返回 null 表示"规则层没有异议"。

这正是第 9 章那张真值表的实现:钩子说 allow 时,只需要问"规则层有没有反对意见",而不需要重新走一遍完整的放行逻辑。函数的裁剪方式直接编码了它的语义。


四、沙箱:外包给一个独立包

这是本章和 Codex 教程差别最大的一节。

Codex 自己实现了四套沙箱(macOS Seatbelt、Linux Landlock+seccomp、Linux bwrap、Windows AppContainer),三套独立实现加一层统一抽象,是它"工程完备"哲学的最强证据。

Claude Code 的做法是 [源码 src/utils/sandbox/sandbox-adapter.ts:1]:

ts
/**
 * Adapter layer that wraps @anthropic-ai/sandbox-runtime with Claude CLI-specific
 * integrations. This file provides the bridge between the external sandbox-runtime
 * package and Claude CLI's settings system, tool integration, and additional features.
 */
import {
  SandboxManager as BaseSandboxManager,
  SandboxRuntimeConfigSchema,
  SandboxViolationStore,
} from '@anthropic-ai/sandbox-runtime'

整个沙箱是一个独立的 npm 包,这个文件只是适配层。

Claude Code 里剩下的只有配置 schema [源码 src/entrypoints/sandboxTypes.ts]:

ts
export const SandboxNetworkConfigSchema = lazySchema(() => z.object({
  allowedDomains: z.array(z.string()).optional(),
  allowManagedDomainsOnly: z.boolean().optional().describe(
    'When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. ' +
    'User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources.'),
  allowUnixSockets: z.array(z.string()).optional().describe(
    'macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path).'),
  allowAllUnixSockets: z.boolean().optional(),
  allowLocalBinding: z.boolean().optional(),
  httpProxyPort: z.number().optional(),
  socksProxyPort: z.number().optional(),
}).optional())

从这些字段能反推出沙箱的能力面:网络域名白名单、Unix socket 控制、本地端口绑定、HTTP/SOCKS 代理端口,加上文件系统的 allowWrite / denyWrite

两处细节暴露了实现差异:

  • allowUnixSockets 标着 "macOS only … Ignored on Linux (seccomp cannot filter by path)" —— macOS 的 Seatbelt 能按路径过滤 socket,Linux 的 seccomp 不能。平台差异没有被抽象掉,而是直接写进了配置项的文档里。
  • allowManagedDomainsOnly管理端专用的收紧开关:打开后只认管理端配的域名,用户/项目/本地/命令行配的一律忽略——但 deny 仍然从所有来源生效。 又是那条"收紧无条件、放宽受限"的不对称原则。

4.1 沙箱和权限的耦合点

沙箱不是独立于权限的另一套东西,它们在两处交汇。

交汇点一:沙箱内的命令可以自动放行

ts
const canSandboxAutoAllow =
  tool.name === BASH_TOOL_NAME &&
  SandboxManager.isSandboxingEnabled() &&
  SandboxManager.isAutoAllowBashIfSandboxedEnabled() &&
  shouldUseSandbox(input)

if (!canSandboxAutoAllow) {
  return { behavior: 'ask', … }
}
// Fall through to let Bash's checkPermissions handle command-specific rules

[源码 src/utils/permissions/permissions.ts:1183]

"这条命令会在沙箱里跑"本身就是一个放行理由。 因为沙箱已经限制了它能碰的文件和网络。

交汇点二:allow 规则会喂给沙箱

配置项 allowWrite 的说明:Merged with paths from Edit(...) allow permission rules. —— 用户批准过编辑的路径,自动成为沙箱的可写路径。

4.2 excludedCommands 明确不是安全边界

ts
// NOTE: excludedCommands is a user-facing convenience feature, not a security boundary.
// It is not a security bug to be able to bypass excludedCommands — the sandbox permission
// system (which prompts users) is the actual security control.
function containsExcludedCommand(command: string): boolean

[源码 src/tools/BashTool/shouldUseSandbox.ts:18]

在代码里明确声明"这个不是安全边界,绕过它不算安全漏洞"。

这句话的价值在于降低安全响应的噪音:没有它,每个发现"我能绕过 excludedCommands"的人都会提一个安全 issue。

可迁移的判断 ㉒ 在代码里显式声明哪些机制不是安全边界。

一个系统里总有一些"看起来像安全检查但其实是便利功能"的东西(前端校验、UI 隐藏、便利性黑名单)。不声明清楚,它们会同时造成两种损失:安全团队浪费时间在假漏洞上,以及有人真的把它们当成安全边界来依赖。


五、auto 模式:用模型当分类器 [内部]

auto 模式是 feature('TRANSCRIPT_CLASSIFIER') 门控的内部功能。它的实现文件 yoloClassifier.ts 有 1495 行,在快照里存在(不像第 7 章那些被 DCE 掉的),但它加载的提示词模板是 .txt 文件,那些不在。

ts
const BASE_PROMPT: string = feature('TRANSCRIPT_CLASSIFIER')
  ? txtRequire(require('./yolo-classifier-prompts/auto_mode_system_prompt.txt'))
  : ''

[源码 src/utils/permissions/yoloClassifier.ts:55]

从周边代码能还原它的工作方式:

  • sideQuery(一个旁路模型调用),用一个专门的 ant 模型
  • 输入包括:命令、当前 CLAUDE.md 内容、工具集、消息历史("transcript classifier" 这个名字说明它看整个对话)
  • 输出是结构化的放行/拒绝判断
  • getBashPromptAllowDescriptions / getBashPromptDenyDescriptions 把用户的规则翻译成自然语言喂给分类器

这就是 Codex Guardian 的对位物——两家都走到了"静态规则拦不住,上一个模型当判官"这一步。差别在成熟度和公开程度:Codex 的 Guardian 策略是仓库里一份 8281 字节的公开风险分类学,Claude Code 的分类器提示词是内部构建才有的 .txt

5.1 危险模式清单:allow 规则也可能是漏洞

auto 模式入口处会剥掉一批危险的 allow 规则 [源码 src/utils/permissions/dangerousPatterns.ts:1]:

ts
/**
 * An allow rule like `Bash(python:*)` or `PowerShell(node:*)` lets the model
 * run arbitrary code via that interpreter, bypassing the auto-mode classifier.
 * These lists feed the isDangerous{Bash,PowerShell}Permission predicates in
 * permissionSetup.ts, which strip such rules at auto-mode entry.
 */
export const CROSS_PLATFORM_CODE_EXEC = [
  'python', 'python3', 'python2', 'node', 'deno', 'tsx', 'ruby', 'perl', 'php', 'lua',
  'npx', 'bunx', 'npm run', 'yarn run', 'pnpm run', 'bun run',
  'bash', 'sh',
  'ssh',
] as const

export const DANGEROUS_BASH_PATTERNS = [
  ...CROSS_PLATFORM_CODE_EXEC,
  'zsh', 'fish', 'eval', 'exec', 'env', 'xargs', 'sudo',
  ...(process.env.USER_TYPE === 'ant' ? ['fa run', 'coo', 'gh', 'gh api', 'curl', 'wget', 'git', 'kubectl', 'aws', 'gcloud', 'gsutil'] : []),
]

一个 Bash(python:*) 的 allow 规则等于"允许执行任意代码"。 用户配它的时候想的是"让 python 脚本跑起来别老问我",但它实际授予的是完整的代码执行权。

内部版那批更狠,注释解释了取舍:

These stay ant-only — external users don't have coo, and the rest are an empirical-risk call grounded in ant sandbox data, not a universal "this tool is unsafe" judgment.

"这是基于内部沙箱数据的经验性风险判断,不是普世的'这个工具不安全'的论断" —— 很克制的表述。git 上榜的理由写得很具体:git config core.sshCommand 和装 hook 都等于任意代码执行。

还有一条关于匹配器形状的注释:

gh api needs its own entry — the matcher is exact-shape, not prefix, so pattern 'gh' alone does not catch rule 'gh api:*' (same reason 'npm run' is separate from 'npm').

匹配器是按规则形状精确匹配的,不是前缀匹配,所以 ghgh api 要各写一条。

5.2 分类器的止损:连续拒绝就回退到问人

ts
export const DENIAL_LIMITS = {
  maxConsecutive: 3,
  maxTotal: 20,
} as const

export function shouldFallbackToPrompting(state: DenialTrackingState): boolean

[源码 src/utils/permissions/denialTracking.ts:12]

连续拒绝 3 次,或累计拒绝 20 次 → 不再信任分类器,回退到弹窗问人。

这个设计的逻辑是:分类器连续拒绝,说明模型正在反复尝试一类它认为该做而分类器认为不该做的事。这时候争议应该上交给人,而不是让两个模型互相消耗。

和第 7 章那个 autocompact 断路器(连续失败 3 次就停)是同一个模式:任何"自动判断"的组件都要有一个"我判断不了了,交给上一层"的出口。

5.3 bypass 模式可以被远程关掉

ts
export async function checkAndDisableBypassPermissionsIfNeeded(…) {
  if (bypassPermissionsCheckRan) return
  bypassPermissionsCheckRan = true
  if (!toolPermissionContext.isBypassPermissionsModeAvailable) return

  const shouldDisable = await shouldDisableBypassPermissions()   // Statsig gate
  if (!shouldDisable) return

  setAppState(prev => ({ ...prev, toolPermissionContext: createDisabledBypassPermissionsContext(prev.toolPermissionContext) }))
}

[源码 src/utils/permissions/bypassPermissionsKillswitch.ts:19]

一个远程开关可以在第一次请求之前关掉所有用户的 bypass 模式。 文件名直接叫 bypassPermissionsKillswitch.ts

这是产品化 agent 才会有的东西:如果发现某个模型版本在 bypass 模式下会做危险的事,需要一个不用发版就能止血的手段。


六、决策原因的十一种类型

第 9 章列过,这里补全语义 [源码 src/services/tools/toolExecution.ts:214-244]:

decisionReason.type含义OTel 归类
rule规则命中按规则来源映射(临时/永久/拒绝/配置)
hook钩子决定hook
mode权限模式决定(bypass)config
classifierauto 模式分类器config
subcommandResultsbash 子命令逐条判断的合并结果config
asyncAgent后台 agent(不能弹窗,自动拒)config
sandboxOverride沙箱相关覆盖config
workingDir工作目录判断config
safetyCheck安全路径检查config
permissionPromptToolSDK 宿主提供的权限工具宿主自报,兜底 user_temporary / user_reject
other其它config

subcommandResults 值得单独说:git status && rm -rf / 是一条 bash 命令但有两个子命令,权限系统要把它拆开逐个判断,然后合并结果。合并规则显然是"任何一个 deny 就整体 deny"。

asyncAgent 也很有意思——后台 agent 没有 UI,弹不了窗,所以它的"ask"等于"deny"

ts
/** When true, permission prompts are auto-denied (e.g., background agents that can't show UI) */
shouldAvoidPermissionPrompts?: boolean

[源码 src/Tool.tsToolPermissionContext]


七、和 Codex 的正面对照

维度CodexClaude Code
沙箱实现自研 4 套(Seatbelt / Landlock+seccomp / bwrap / AppContainer)外包@anthropic-ai/sandbox-runtime,仓库里只有适配层和配置 schema
沙箱是不是默认防线是——审批策略和沙箱策略是一对部分——沙箱是可选的,权限规则才是主防线
模型判官Guardian,策略是仓库里 8281 字节的公开风险分类学auto 模式分类器,内部构建专有
判官的输入命令 + 上下文整个 transcript(名字就叫 transcript classifier)
判官失效时回退到人工审批连续 3 次 / 累计 20 次拒绝 → 回退到弹窗
危险 allow 规则——有一份显式清单,进 auto 模式时剥掉
远程止血——bypass 模式有 killswitch
权限规则来源配置 + CLI8 种来源,每条规则记得自己的出身

两条路线的分歧点很清楚

  • Codex 把"隔离"当第一防线——先假设 agent 会干坏事,用内核机制限制它能干什么。所以必须自己实现,因为每个操作系统的机制不一样,抽象层做不干净。
  • Claude Code 把"规则 + 审批"当第一防线——先定义什么可以做,沙箱是加固层。所以沙箱可以外包,因为它不承担主要的安全语义。

哪个更好取决于威胁模型:如果假设"模型可能被提示词注入劫持",隔离优先是对的;如果假设"模型基本可信但会犯错",规则优先更实用(也不会因为沙箱兼容性问题让工具全挂)。

Claude Code 显然选了后者——但它同时保留了 auto 模式分类器这条针对注入的防线。第 6 章末尾说这条防线"不算强",现在可以补完:它不强,但它不是唯一的一层。


八、动手复核

bash
cd claude-code-deep-dive/extracted-source

# 1. 六种模式
cat src/utils/permissions/PermissionMode.ts
sed -n '1,60p' src/types/permissions.ts

# 2. 决策流水线(带 1a/1b/1c… 编号)
sed -n '1158,1310p' src/utils/permissions/permissions.ts

# 3. 给钩子用的精简版,对比看裁剪了什么
sed -n '1071,1155p' src/utils/permissions/permissions.ts

# 4. 三条 bypass 免疫
grep -n -B3 -A8 'bypass-immune\|even in bypass mode\|requiresUserInteraction' src/utils/permissions/permissions.ts

# 5. 沙箱:只有适配层
head -50 src/utils/sandbox/sandbox-adapter.ts
cat src/entrypoints/sandboxTypes.ts | head -80

# 6. 「这不是安全边界」的声明
grep -n -B2 -A4 'not a security boundary' src/tools/BashTool/shouldUseSandbox.ts

# 7. 危险 allow 规则清单
cat src/utils/permissions/dangerousPatterns.ts

# 8. 分类器止损与 bypass killswitch
cat src/utils/permissions/denialTracking.ts
cat src/utils/permissions/bypassPermissionsKillswitch.ts

本机侧:

bash
# 看当前生效的规则及其来源
# (在 Claude Code 里敲)
/permissions

# 看沙箱状态
/sandbox-toggle

九、总结

  1. 六种模式(外部 5 + 内部 auto),加一个不可选的 bubble(fork 子 agent 把权限弹窗冒泡给父终端)
  2. 三类规则 × 8 种来源,每条规则记得自己的出身,一路带到遥测的四桶词表里
  3. 空内容的 deny 规则在工具进入模型视野之前就过滤掉工具,而且用的是和运行时检查同一个匹配器——两处不一致就是漏洞
  4. 决策流水线的顺序即优先级:deny 在最前,bypass 在很后面,所以 bypass 绕不过 deny
  5. 三条 bypass 免疫:需要真人交互的工具、用户显式配的内容级 ask 规则、安全路径(.git/ .claude/ .vscode/ shell 配置)——判据是"改一下就能获得持久执行能力"
  6. 给钩子用的 checkRuleBasedPermissions 只保留"会反对"的步骤,函数的裁剪方式直接编码了它的语义
  7. 沙箱整个外包给独立 npm 包,仓库里只有适配层;平台差异不抽象,直接写进配置项文档("macOS only, Linux seccomp 不能按路径过滤")
  8. 代码里显式声明 excludedCommands 不是安全边界——降低假漏洞噪音
  9. auto 模式是 Guardian 的对位物,输入是整个 transcript;有危险 allow 规则剥离清单(Bash(python:*) = 任意代码执行)和连续拒绝止损(3 次/20 次 → 回退问人)
  10. bypass 模式有远程 killswitch —— 不发版就能止血
  11. 和 Codex 的分歧是威胁模型的分歧:隔离优先(假设会被劫持)vs 规则优先(假设会犯错)

下一章讲那个在执行链上权力最大、也是本仓踩过坑的子系统:27 个事件的钩子。


  • 第9章-工具执行链-一次调用要过多少道关
  • 第11章-钩子系统-27个事件的治理层
  • 第2章-工程骨架-一个npm包里的AgentOS —— 五层设置来源
  • 第12章-Agent调度-fork与fresh两条路 —— bubble 模式的用处
  • Codex 教程第 10 章 —— 自研沙箱的对照
  • Codex 教程第 11 章 —— Guardian 的对照
  • dsh 教程第 10 章 —— seam + 多后端的对照

本章目录
一、六种模式二、三类规则与它们的来源三、决策流水线:hasPermissionsToUseToolInner四、沙箱:外包给一个独立包五、auto 模式:用模型当分类器 [内部]六、决策原因的十一种类型七、和 Codex 的正面对照八、动手复核九、总结Related Documents
苏ICP备2025204887号-2