Ai分析结果
------ 大模型如何调用 Agent、Skills 与上下文管理
基于 v2.1.88 源码的技术分析
目录
- [Agent 调用机制](#Agent 调用机制 "#1-agent-%E8%B0%83%E7%94%A8%E6%9C%BA%E5%88%B6")
- [Skills 调用机制](#Skills 调用机制 "#2-Skills-%E8%B0%83%E7%94%A8%E6%9C%BA%E5%88%B6")
- 上下文管理机制
- 完整调用链路
- 关键设计模式
1. Agent 调用机制
1.1 AgentTool 输入参数
位置 : src/tools/AgentTool/AgentTool.tsx (228KB, 1398 行)
核心输入 Schema:
typescript
const baseInputSchema = z.object({
description: z.string().describe('3-5 字任务描述'),
prompt: z.string().describe('要执行的任务'),
subagent_type: z.string().optional().describe('使用的代理类型'),
model: z.enum(['sonnet', 'opus', 'haiku']).optional().describe('模型覆盖'),
run_in_background: z.boolean().optional().describe('是否后台运行')
})
1.2 三种执行模式详解
模式 A:同步执行(默认)------ 共享进程,独立对话
typescript
// src/tools/AgentTool/runAgent.ts:56-384
for await (const message of runAgent({
agentDefinition,
promptMessages,
toolUseContext: { ...context },
canUseTool,
isAsync: false,
querySource: 'agent:custom',
})) {
agentMessages.push(message)
}
特点:
- ✅ 共享同一进程,内存开销小
- ✅ 共享文件缓存,减少重复 IO
- ✅ 独立的消息历史 (messages[])
- ⚡ 适合快速任务(读取文件、简单修改等)
模式 B:Fork 子进程 ------ 完全隔离,资源独立
typescript
// src/tools/AgentTool/forkSubagent.ts:130-256
async function runForkedAgent(...) {
// 1. 创建独立进程
const child = forkAgentProcess({
agentId,
messages: buildForkedMessages(parent),
tools: availableTools,
cwd: worktreePath // 可选的 git worktree 隔离
})
// 2. 共享文件缓存,独立消息历史
return child.result
}
特点:
- ✅ 独立进程空间,完全隔离
- ✅ 共享文件缓存(性能优化)
- ✅ 完全独立的对话历史
- ✅ 可配置 git worktree 物理隔离
- ⚡ 适合长期任务(功能开发、测试等)
模式 C:远程代理 ------ 云端执行,资源弹性
typescript
// src/tasks/RemoteAgentTask/RemoteAgentTask.ts:88-267
async function launchRemoteAgent() {
// 通过 Bridge 协议启动远程会话
const session = await bridgeApi.createSession({
type: 'remote_agent',
resources: { cpu: 4, memory: '8GB' }
})
return { status: 'remote_launched', sessionUrl }
}
特点:
- ✅ 远程服务器执行,不占用本地资源
- ✅ 资源配置灵活(CPU/内存可调)
- ✅ 可监控的会话 URL
- ⚡ 适合重型任务(大型重构、数据分析等)
1.3 Agent 孵化的完整流程
1.4 多代理协作协议
团队管理 Schema:
typescript
// src/tools/AgentTool/AgentTool.tsx:89-97
const multiAgentInputSchema = z.object({
name: z.string().optional().describe('可寻址的代理名称'),
team_name: z.string().optional().describe('团队名称'),
mode: permissionModeSchema().optional().describe('权限模式')
})
代理间通信工具:
typescript
// 通过 SendMessageTool 进行代理间通信
SendMessageTool.call({
to: 'teammate-name',
message: '请审查这个 PR'
})
2. Skills 调用机制
2.1 SkillsTool 架构与输入
位置 : src/tools/SkillsTool/SkillsTool.ts (1109 行)
核心输入 Schema:
typescript
export const inputSchema = z.object({
Skills: z.string().describe('技能名称,如 "commit", "review-pr"'),
args: z.string().optional().describe('可选参数')
})
2.2 两种执行方式对比
方式 A:Inline 扩展 ------ 轻量级提示词注入
核心流程 (call() 函数,第 634-775 行):
typescript
// 1. 加载 Skills 提示词
const command = findCommand(Skills, commands)
// 2. 处理提示词(!command 替换、$ARGUMENTS 插值)
const processedCommand = await processPromptSlashCommand(
Skills, args, commands, context
)
// 3. 生成新消息注入对话
const newMessages = tagMessagesWithToolUseID(
processedCommand.messages,
toolUseID
)
// 4. 修改上下文(允许的工具、模型覆盖、努力程度)
return {
data: { success: true, commandName: Skills },
newMessages,
contextModifier: ctx => ({
...ctx,
options: {
...ctx.options,
mainLoopModel: resolveSkillsModelOverride(
command.model,
ctx.mainLoopModel
)
}
})
}
特点:
- ✅ 轻量级扩展,无额外进程开销
- ✅ 直接注入对话,立即生效
- ✅ 可动态修改上下文(工具权限、模型、努力程度)
- ⚡ 适合简单工作流(代码审查、提交信息等)
方式 B:Fork 子代理 ------ 隔离执行,实时进度
核心流程 (executeForkedSkills() 函数,第 122-289 行):
typescript
async function executeForkedSkills(command, args, context) {
// 1. 准备隔离的上下文
const { modifiedGetAppState, promptMessages, SkillsContent } =
await prepareForkedCommandContext(command, args, context)
// 2. 在独立代理中运行
for await (const message of runAgent({
agentDefinition: { ...baseAgent, effort: command.effort },
promptMessages,
toolUseContext: { ...context, getAppState: modifiedGetAppState },
querySource: 'agent:custom'
})) {
agentMessages.push(message)
// 报告进度
onProgress?.({ toolUseID, data: { message, type: 'Skills_progress' }})
}
// 3. 提取结果
return {
status: 'forked',
agentId,
result: extractResultText(agentMessages)
}
}
特点:
- ✅ 独立 token 预算,不占用父代理上下文
- ✅ 隔离的执行环境,避免干扰
- ✅ 实时进度报告(Skills_progress)
- ✅ 可配置努力程度(effort)
- ⚡ 适合复杂工作流(PR 审查、PDF 处理等)
2.3 Skills 发现与加载机制
三级 Skills 来源:
- 本地 Skillss :
~/.claude/Skillss/或项目.claude/Skillss/ - MCP Skillss: 通过 MCP 协议连接的外部服务
- 远程 Skillss: AKI/GCS云存储(实验性,仅内部)
MCP Skillss 集成:
typescript
// src/tools/SkillsTool/SkillsTool.ts:81-94
async function getAllCommands(context) {
// 从 AppState 获取 MCP Skillss
const mcpSkillss = context.getAppState()
.mcp.commands.filter(cmd => cmd.type === 'prompt' && cmd.loadedFrom === 'mcp')
// 合并本地 Skillss
const localCommands = await getCommands(getProjectRoot())
return uniqBy([...localCommands, ...mcpSkillss], 'name')
}
远程 Skillss (实验性,仅内部):
typescript
// src/tools/SkillsTool/SkillsTool.ts:969-1108
async function executeRemoteSkills(slug, commandName, parentMessage, context) {
// 从 AKI/GCS 加载远程 Skills
const loadResult = await loadRemoteSkills(slug, meta.url)
// 注入到对话
return {
data: { success: true, commandName, status: 'inline' },
newMessages: [createUserMessage({ content: finalContent, isMeta: true })]
}
}
2.4 Skills 权限检查流程
四步权限检查 (checkPermissions() 函数,第 432-578 行):
typescript
async function checkPermissions({ Skills, args }, context) {
const commandObj = findCommand(Skills, commands)
// 1. 检查拒绝规则(优先级最高)
const denyRules = getRuleByContentsForTool(
permissionContext, SkillsTool, 'deny'
)
if (denyRules.matches(Skills)) return { behavior: 'deny' }
// 2. 检查允许规则
const allowRules = getRuleByContentsForTool(
permissionContext, SkillsTool, 'allow'
)
if (allowRules.matches(Skills)) return { behavior: 'allow' }
// 3. 安全检查(仅允许安全属性)
if (SkillsHasOnlySafeProperties(commandObj)) {
return { behavior: 'allow' }
}
// 4. 默认:询问用户
return {
behavior: 'ask',
suggestions: [
{ type: 'addRules', rule: { toolName: 'Skills', ruleContent: Skills } }
]
}
}
安全属性白名单 (28 个):
typescript
const SAFE_Skills_PROPERTIES = new Set([
'type', 'model', 'effort', 'source', 'context',
'name', 'description', 'isEnabled', 'aliases',
'paths', 'version', 'disableModelInvocation',
// ... 共 28 个安全属性
])
匹配规则示例:
- 精确匹配:
commit→ 允许commitSkills - 前缀匹配:
review:*→ 允许所有review-开头的 Skillss
3. 上下文管理机制
3.1 三层压缩策略详解
阈值配置 (src/services/compact/autoCompact.ts):
typescript
export const AUTOCOMPACT_BUFFER_TOKENS = 13_000
export const WARNING_THRESHOLD_BUFFER_TOKENS = 20_000
export const ERROR_THRESHOLD_BUFFER_TOKENS = 20_000
export const MANUAL_COMPACT_BUFFER_TOKENS = 3_000
策略 A:autoCompact(自动总结)------ API 调用,智能压缩
触发条件:
typescript
function getAutoCompactThreshold(model: string): number {
const effectiveContextWindow = getEffectiveContextWindowSize(model)
return effectiveContextWindow - AUTOCOMPACT_BUFFER_TOKENS
}
压缩流程:
typescript
if (tokenCount >= autoCompactThreshold && !tracking.compacted) {
// 1. 调用 Claude API 总结旧消息
const { summary, boundaryMessage } = await compactConversation(messages)
// 2. 重建消息数组
messages = [summary, boundaryMessage, ...recentMessages]
// 3. 标记已压缩,防止重复压缩
tracking.compacted = true
}
特点:
- ✅ 智能总结,保留关键信息
- ✅ 需要 API 调用,有成本
- ✅ 保留 compact_boundary 标记,支持恢复
- ⚡ 适用于长对话场景
策略 B:snipCompact(剪切僵尸消息)------ 本地过滤,零成本
功能实现 (src/services/compact/snipCompact.js, feature-gated):
typescript
function snipCompact(messages) {
// 移除过时的标记和僵尸消息
const snipped = messages.filter(msg => {
return !isZombieMarker(msg) && !isStaleProgress(msg)
})
const tokensFreed = countTokens(messages) - countTokens(snipped)
return { snipped, tokensFreed }
}
特点:
- ✅ 本地过滤,零 API 成本
- ✅ 清理无效消息(zombie markers, stale progress)
- ✅ 快速释放上下文空间
- ⚡ 作为 autoCompact 的前置优化
策略 C:contextCollapse(重构上下文)------ 实验性结构优化
实验性功能 (src/services/contextCollapse/index.js, feature-gated):
typescript
async function contextCollapse(messages) {
// 重构上下文结构以提高效率
const restructured = await restructureContext(messages)
return restructured
}
特点:
- ✅ 重构消息结构,提升检索效率
- ✅ 实验性功能,需 feature flag 开启
- ⚡ 适用于超长对话场景
3.2 Session Memory(会话记忆)------ 跨会话学习
配置参数 (src/services/SessionMemory/sessionMemoryUtils.ts):
typescript
export const DEFAULT_SESSION_MEMORY_CONFIG = {
minimumMessageTokensToInit: 10000, // 初始化阈值
minimumTokensBetweenUpdate: 5000, // 更新阈值
toolCallsBetweenUpdates: 3 // 工具调用间隔
}
提取流程:
typescript
async function extractSessionMemory(messages, config) {
// 1. 检查是否达到初始化阈值(10K tokens)
if (!sessionMemoryInitialized &&
currentTokenCount >= config.minimumMessageTokensToInit) {
await initializeSessionMemory()
sessionMemoryInitialized = true
}
// 2. 检查是否达到更新阈值(5K tokens 增长)
if (tokensSinceLastExtraction >= config.minimumTokensBetweenUpdate) {
await updateSessionMemory(messages)
recordExtractionTokenCount(currentTokenCount)
}
// 3. 持久化到磁盘(~/.claude/projects/<hash>/sessions/)
await writeSessionMemory(memoryPath)
}
特点:
- ✅ 自动提取会话关键信息
- ✅ 双阈值控制(初始化 10K,更新 5K)
- ✅ 每 3 次工具调用检查一次
- ✅ 持久化到磁盘,支持崩溃恢复
- ⚡ 实现跨会话学习和记忆
3.3 Memory Directory(记忆目录)------ 结构化知识库
目录结构:
bash
~/.claude/projects/<hash>/memory/
├── MEMORY.md # 入口文件(行为指令)
├── user/ # 用户记忆
├── feedback/ # 反馈记忆
├── project/ # 项目记忆
└── reference/ # 参考记忆
提示词构建 (src/memdir/memdir.ts:199-250):
typescript
export function buildMemoryLines(displayName: string, memoryDir: string) {
return `
## ${displayName} (${memoryDir})
${DIR_EXISTS_GUIDANCE}
### 记忆类型(封闭分类)
1. **用户记忆**: 偏好、沟通风格、目标
2. **反馈记忆**: 对之前输出的明确反馈
3. **项目记忆**: 项目特定的知识(非代码可推导)
4. **参考记忆**: 外部资源、文档链接
### 何时访问
- 开始新任务时检索相关记忆
- 遇到模糊需求时查询用户偏好
- 收到反馈时更新反馈记忆
`
}
特点:
- ✅ 四类封闭分类(user/feedback/project/reference)
- ✅ 明确的访问指导
- ✅ 目录存在性自动保证(无需 mkdir)
- ⚡ 构建项目专属知识库
3.4 上下文字典管理 ------ 主循环中的压缩逻辑
主循环实现 (src/query.ts:365-420):
typescript
async function* queryLoop(params) {
let messages = params.messages
while (true) {
// 1. 获取压缩边界后的消息
let messagesForQuery = [...getMessagesAfterCompactBoundary(messages)]
// 2. 应用工具结果预算(限制 tool_result 大小)
messagesForQuery = await applyToolResultBudget(
messagesForQuery,
contentReplacementState
)
// 3. 应用 Snip 压缩(如果启用 HISTORY_SNIP)
if (feature('HISTORY_SNIP')) {
const { snipped, tokensFreed } = await snipCompact(messagesForQuery)
messagesForQuery = snipped
}
// 4. 检查是否需要自动压缩
const tokenCount = tokenCountWithEstimation(messagesForQuery)
if (tokenCount >= autoCompactThreshold) {
const { summary } = await compactConversation(messagesForQuery)
messagesForQuery = [summary, ...recentMessages]
}
// 5. 调用 Claude API
const response = await claudeAPI({
messages: messagesForQuery,
systemPrompt,
tools
})
// 6. 处理工具调用
if (response.stop_reason === 'tool_use') {
const toolResults = await runTools(response.content)
messages = [...messagesForQuery, ...toolResults]
continue
}
// 7. 返回最终响应
yield response
break
}
}
压缩顺序:
- getMessagesAfterCompactBoundary() → 获取有效消息
- applyToolResultBudget() → 限制工具结果大小
- snipCompact() → 移除僵尸消息(可选)
- autoCompact() → 总结旧消息(如超过阈值)
- claudeAPI() → 调用模型
4. 完整调用链路
5. 关键设计模式
5.1 上下文隔离与共享
子代理的上下文设计:
typescript
const forkedContext = {
...parentContext,
messages: [], // 空消息历史(隔离)
fileCache: shared, // 共享文件缓存(性能)
workingDirectory: worktreePath // 独立工作目录(可选)
}
设计优势:
- ✅ 保持对话清洁(独立 messages[])
- ✅ 避免上下文污染(独立 token 预算)
- ✅ 共享资源减少重复 IO(共享 fileCache)
- ✅ 独立工作目录避免冲突(worktree 隔离)
5.2 懒加载与预取
技能发现预取:
typescript
// 不阻塞的异步预取(利用工具执行时间)
const pendingSkillsPrefetch = SkillsPrefetch?.startSkillsDiscoveryPrefetch(
null, messages, toolUseContext
)
// 等待完成(在工具执行后)
await pendingSkillsPrefetch?.consume()
记忆预取:
typescript
using pendingMemoryPrefetch = startRelevantMemoryPrefetch(
messages, toolUseContext
)
await pendingMemoryPrefetch?.consume()
设计优势:
- ✅ 利用工具执行时间(隐藏加载延迟)
- ✅ 异步预取,不阻塞主流程
- ✅ 提升用户体验(减少等待感)
5.3 权限传递与覆盖
Skills 动态修改权限上下文:
typescript
contextModifier(ctx) {
if (allowedTools.length > 0) {
return {
...ctx,
getAppState() {
const appState = previousGetAppState()
return {
...appState,
toolPermissionContext: {
...appState.toolPermissionContext,
alwaysAllowRules: {
...alwaysAllowRules,
command: [...new Set([...alwaysAllowRules.command, ...allowedTools])]
}
}
}
}
}
}
}
设计优势:
- ✅ 细粒度权限控制(按 Skills 定制)
- ✅ 动态调整策略(contextModifier)
- ✅ 安全的权限继承(Set 去重)
- ✅ 作用域限定(仅当前 Skills 执行期间)
5.4 渐进式压缩与降级
多层压缩策略:
typescript
const compressionStrategies = {
autoCompact: '总结旧消息(API 调用,智能但昂贵)',
snipCompact: '移除僵尸消息(本地过滤,零成本)',
contextCollapse: '重构上下文结构(实验性)'
}
降级机制:
typescript
if (autoCompactFailed) {
trySnipCompact() // 尝试轻量级压缩
if (stillOverLimit) {
throw PromptTooLongError // 最终抛出错误
}
}
设计优势:
- ✅ 多层次策略应对不同场景
- ✅ 成本梯度(snip → auto → collapse)
- ✅ 降级机制保证可靠性
- ✅ 最大化利用上下文窗口
5.5 持久化与恢复
对话记录:
typescript
// src/utils/sessionStorage.js
async function recordTranscript(message) {
// 追加写入 JSONL 文件
await appendFile(sessionLogPath, JSON.stringify(message) + '\n')
}
恢复流程:
typescript
// src/commands/resume.js
async function resumeSession(sessionId) {
const messages = await readJSONL(sessionLogPath)
const lastMessage = messages[messages.length - 1]
// 重建对话状态
return rebuildStateFromMessages(messages)
}
设计优势:
- ✅ 追加写入(order-preserving queue)
- ✅ JSONL 格式(易解析,易恢复)
- ✅ 支持 --continue 和 --resume
- ✅ 崩溃后可完全恢复状态
核心设计总结
Claude Code 的 Agent/Skills/上下文管理系统展现了生产级 AI 代理的复杂性,其核心设计理念包括:
1. 渐进式增强
从基础的"调用 API→执行工具"循环开始,逐层添加压缩、记忆、多代理、权限等生产特性
2. 分层隔离
- 同步/Fork/远程三种代理模式
- 不同的隔离级别和资源管理
- 共享文件缓存 vs 独立消息历史
3. 弹性上下文管理
- 三层压缩策略应对不同场景
- Session Memory 提供跨会话学习
- Memory Directory 实现结构化知识
4. 安全优先的权限系统
- 细粒度的权限控制
- 动态修改和继承
- 白名单机制保护未知风险
5. 全面的持久化
- 所有对话记录到磁盘
- 支持崩溃恢复
- 会话恢复机制
文档生成时间 : 2026-04-01
分析版本 : Claude Code v2.1.88
核心文件:
src/tools/AgentTool/AgentTool.tsx(1,398 行)src/tools/SkillsTool/SkillsTool.ts(1,109 行)src/query.ts(1,730 行)src/services/compact/autoCompact.ts(352 行)src/services/SessionMemory/sessionMemoryUtils.ts(208 行)src/memdir/memdir.ts(508 行)