Langgraph 17. Skills 三级加载与 Token 优化(含代码示例)

摘要 :本文介绍 Agent Skills 中的 Progressive Disclosure(渐进式披露) 设计模式------将技能知识按需分层加载(L1 元数据 → L2 指令 → L3 资源),显著减少每次 LLM 调用的 token 消耗。本文严格遵循 agentskills.io / ADK SkillToolset 规范:L3 由 Agent 在 execute 阶段通过 load_skill_resource 工具按需调用 ,而非图节点提前批量加载。案例介绍 :配套 demo 实现一个基于 LangGraph 的多技能内容工作流智能体 ,具备 SEO 检查、博客写作、代码审查、研究摘要四类技能;智能体先通过 L1 元数据发现可用技能,再根据用户任务按需加载 L2 指令;在 execute 阶段将 load_skill_resource 暴露为 Agent 工具,由 LLM 根据 L2 指令按需加载 L3 参考文档。技术要点 :用 LangGraph 编排 discoverselectload_l2execute 流程;L1 仅解析 frontmatter;L2 按需读取 SKILL.md 正文;L3 在 execute 的 Agent 工具循环中按需调用加载;支持 tiktoken 统计各层 token 并与全量加载对比。

关键词:Progressive Disclosure;Agent Skills;L1/L2/L3;Token 优化;LangGraph;SKILL.md;按需加载

源代码链接:LangGraph 17. Progressive Disclosure 示例源代码


1. 为什么智能体需要「Progressive Disclosure」?

1.1 传统方式的痛点

想象一下,你经营一家拥有十位专家的咨询公司。客户每次来电,你都把所有专家的详细履历、工作手册、参考资料一口气塞进对话------即便客户只是问一个简单问题。这不仅浪费纸张和时间,还会让对话变得臃肿、难以聚焦。

智能体使用 Skills 时,若采用传统全量加载方式,也会遇到类似问题:

  • 能力写死在 system prompt 中:研究、写作、SEO、代码审查等技能的全部指令一次性拼接到 system prompt;
  • 每次调用都付费:无论用户问题是「请优化这段博客的 SEO」还是「帮我写一篇技术博客」,所有技能的完整说明都会进入 LLM 上下文,消耗大量 token;
  • 扩展成本线性增长:每增加一个技能,system prompt 就增加几百到几千 token;10 个技能、每个平均 1000 token,则每次调用 baseline 就接近 10,000 token。

💡 理解要点 :把能力塞进 system prompt 的方式,在技能数量较少时尚可接受;一旦技能库扩展,每次请求都承担全部技能的 token 成本,既不经济,也容易触及 context 上限。

1.2 Progressive Disclosure 的核心思路

Progressive Disclosure(渐进式披露)Agent Skills 规范 中定义的设计模式:将技能知识分为三个层次,按需加载,而不是一次性全部塞入上下文。

层级 内容 何时加载 典型规模
L1 元数据 name、description(frontmatter) 每次调用 ~100 tokens/技能
L2 指令 完整 SKILL.md 正文 选定技能后 <5000 tokens/技能
L3 资源 references/、assets/ 中的文件 技能明确引用时 按需

类比 :就像餐厅的菜单------顾客先看菜名和简短描述 (L1)决定要点什么,再向服务员询问做法和配料 (L2),若对某道菜的酱汁配方感兴趣,再要详细配方卡(L3)。不必一进门就拿到所有菜品的完整菜谱。

🔍 实际例子 :用户问「Review my blog post for SEO」。全量加载时,博客写作、SEO、研究、代码审查四个技能的完整指令(约 8000 token)全部在上下文中。采用 Progressive Disclosure 时:先加载 L1(4 个技能的 name + description,约 400 token)→ Agent 识别需要 SEO 技能 → 仅加载 seo-checklist 的 L2(约 300 token)→ 若技能内引用 references/seo-guidelines.md,再加载 L3。总消耗从 8000 降至约 700 token,节省约 90%

1.3 小结:要解决什么?

Progressive Disclosure 要解决的核心问题:

  • 降低 baseline token 消耗:每次调用只加载 L1「菜单」,让 Agent 知道有哪些技能可用;
  • 按需加载 L2/L3:仅对与当前任务相关的技能加载完整指令和参考文档;
  • 可扩展性:技能库增长时,baseline 仅随 L1 元数据线性增长,而非随全部技能内容爆炸式增长。

💡 理解要点 :Progressive Disclosure 不是「少用技能」,而是聪明地决定何时加载哪些知识。Agent 通过 L1 发现、选择,再通过 L2/L3 获得执行所需的具体指导。


2. 示例设定:一个「按需加载」的多技能内容工作流智能体

2.1 案例背景

我们构建一个多技能内容工作流智能体,具备四类能力:

  • seo-checklist :SEO 优化检查清单,含 L3 参考文档 references/seo-guidelines.md
  • blog-writer :博客写作技能,含 L3 风格指南 references/style-guide.md
  • code-review:代码审查技能;
  • research-summarizer:研究摘要技能。

用户可能提出单一任务(如「检查这段文字的 SEO」)或复合任务(如「写一篇博客并做 SEO 优化」)。我们希望智能体:

  1. 启动时仅加载 L1 元数据,了解可用技能;
  2. 根据用户任务,用 LLM 做语义匹配选出相关技能;
  3. 仅对选中的技能加载 L2 指令;
  4. 若技能指令中引用 references/ 中的文件,按需加载 L3;
  5. 将加载的知识与用户输入一起交给 LLM 执行。

2.2 方案设计

配套 demo 实现基于 LangGraph 的 Progressive Disclosure 流程 ,严格遵循 agentskills.io / ADK SkillToolset 规范:

复制代码
START
  ↓
discover (L1)     → 扫描 skills_library,解析每个 SKILL.md 的 frontmatter
  ↓
select           → 根据 user_task 从 L1 列表选出 1~N 个技能(LLM 语义匹配)
  ↓
load_l2          → 仅对选中技能读取完整 SKILL.md 正文
  ↓
execute          → 将 L2 作为 system 上下文,将 load_skill_resource 暴露为 Agent 工具;
                    Agent 根据 L2 指令按需调用工具加载 references/ 中的文件(L3)
  ↓
END

同时,demo 内置 token 计量模块 :用 tiktoken 统计 L1、L2、L3 各层以及「全量加载」模式下的 token 数,并在 main.ipynb 中输出对比表,直观展示 Progressive Disclosure 的 token 节省效果。

2.3 典型流程示例

用户输入:「请检查下面这段博客的 SEO,并给出改进建议。」

  • L1 :Agent 看到 seo-checklist: SEO优化检查清单...blog-writer: 博客写作... 等,识别需要 seo-checklist
  • L2 :加载 seo-checklist 的完整 SKILL.md,得到 9 条检查项,其中指令写明「请先使用 load_skill_resource 工具读取 references/seo-guidelines.md」;
  • Execute :LLM 收到 L2 指令后,主动调用 load_skill_resource 工具获取 L3 文件内容,再按检查项逐项评估并输出建议。

💡 理解要点 :L3 由 Agent 按需调用 load_skill_resource 工具加载,而非图节点提前批量加载;blog-writercode-reviewresearch-summarizer 的 L2/L3 在此过程中从未被加载,从而避免了不必要的 token 消耗。


3. 状态与图结构:用 LangGraph 表达 Progressive Disclosure

3.1 状态定义

progressive_disclosure_graph.py 中,我们用 SkillsWorkflowState 描述图中流转的状态:

python 复制代码
class SkillsWorkflowState(TypedDict):
    user_task: str              # 用户任务描述
    l1_skills: list[dict]       # discover 得到的 L1 元数据列表
    selected_skill_names: list[str]  # select 选中的技能名
    l2_content: dict[str, str]  # skill_name -> 完整 SKILL.md 正文
    l3_content: dict[str, str]  # execute 阶段由 load_skill_resource 工具调用结果填充
    token_usage: dict           # 各层 token 统计
    final_response: str         # execute 后的输出

3.2 图结构

text 复制代码
START
  ↓
discover_node       # 扫描 skills_library,解析 frontmatter → l1_skills
  ↓
select_node         # 根据 user_task 从 l1_skills 选出技能 → selected_skill_names
  ↓
load_l2_node        # 对 selected_skill_names 读取 SKILL.md 正文 → l2_content
  ↓
execute_node        # 将 L2 作为 system,load_skill_resource 作为工具;
                    # Agent 按需调用工具加载 L3 → l3_content、final_response
  ↓
END

流程为线性;execute_node 内部为 Agent 工具循环(LLM → 若有 tool_calls 则执行工具 → 再次调用 LLM → 直至生成最终回复)。L3 的 l3_content 与 token 计量在 execute 阶段由工具调用结果动态填充。

3.3 核心节点逻辑与代码详解

下文逐一说明每个节点的职责、调用链路及关键代码实现。底层能力由 skill_loader.py 提供,图中节点负责编排与状态更新。


3.3.1 discover_node:将所有 skills L1 数据提取出来

职责 :扫描 skills_library/,仅解析每个 SKILL.mdYAML frontmatternamedescription),得到 L1 技能列表;同时用 count_tokens 统计 L1 文本的 token 数,写入 token_usage["l1"]

调用链路discover_nodeskill_loader.discover_skills() → 内部 _parse_frontmatter()

skill_loader 的源代码如下:

py 复制代码
def discover_node(state: SkillsWorkflowState) -> SkillsWorkflowState:
    """L1:扫描技能库,解析 frontmatter。"""
    skills = discover_skills(DEFAULT_SKILLS_LIBRARY)
    usage = state.get("token_usage") or {}

    l1_text = "\n".join(
        f"{s.get('name', '')}: {s.get('description', '')}"
        for s in skills
    )
    usage["l1"] = count_tokens(l1_text)

    return {
        **state,
        "l1_skills": skills,
        "token_usage": usage,
    }

skill_loader 中的 discover_skillsskill_loader.py):

python 复制代码
def discover_skills(skills_root: Optional[Path] = None) -> List[Dict[str, str]]:
    root = Path(skills_root) if skills_root else DEFAULT_SKILLS_LIBRARY
    result = []
    for path in sorted(root.iterdir()):
        if not path.is_dir():
            continue
        skill_md = path / "SKILL.md"
        if not skill_md.is_file():
            continue
        raw = skill_md.read_text(encoding="utf-8", errors="replace")
        meta = _parse_frontmatter(raw)  # 仅解析 --- ... --- 之间的 YAML
        if meta.get("name"):
            result.append(meta)
    return result

_parse_frontmatter 用正则 ^---\s*\n(.*?)\n---\s*\n 匹配 frontmatter 块,解析其中 namedescription 等字段。不读取正文,符合 L1 仅加载元数据的定义。


3.3.2 select_node:技能选择(LLM 语义匹配)

职责 :根据 user_taskl1_skills 中选出 1~2 个相关技能名。使用 LLM 做语义匹配:将 L1 列表与用户任务交给 LLM,由其根据 name 与 description 返回最相关的技能名。未配置 API 或任务为空时返回空列表。

流程 :将 L1 列表格式化为 - {name}: {description},与 user_task 填入 SELECT_SKILL_PROMPT,要求 LLM 仅返回技能名、多个用逗号分隔。解析响应后校验名称是否在 l1_skills 中,过滤无效项。

select_node 实现progressive_disclosure_graph.py):

python 复制代码
def select_node(state: SkillsWorkflowState) -> SkillsWorkflowState:
    skills = state.get("l1_skills") or []
    user_task = state.get("user_task") or ""

    if not skills:
        return {**state, "selected_skill_names": []}

    # 未配置 API 或任务为空时,无法进行 LLM 选择
    if not _config.api_key or not user_task.strip():
        return {**state, "selected_skill_names": []}

    prompt = ChatPromptTemplate.from_template(SELECT_SKILL_PROMPT)
    chain = prompt | _llm
    response = chain.invoke({
        "skills_list": _format_skills_list(skills),
        "user_task": user_task,
    })
    content = (response.content or "").strip()

    selected = []
    for part in content.replace(",", ",").split(","):
        name = part.strip().lower().replace(" ", "-")
        if any(s.get("name") == name for s in skills):
            selected.append(name)

    return {**state, "selected_skill_names": selected}

相关 prompt:

py 复制代码
SELECT_SKILL_PROMPT = """你是一个多技能内容工作流助手。你有以下技能可用(仅名称和简短描述):

{skills_list}

用户任务:
{user_task}

请从上述技能中选择与此任务最相关的 1~2 个技能。仅返回技能名称,多个用英文逗号分隔,不要解释。
例如:seo-checklist
或:blog-writer, seo-checklist
"""

3.3.3 load_l2_node:读取上阶段筛选后skills的l2信息

职责 :对 selected_skill_names 中每个技能,调用 skill_loader.load_skill() 读取完整 SKILL.md 正文 (去掉 frontmatter 后的部分),存入 l2_content[skill_name];并用 count_tokens 累计 L2 token,更新 token_usage["l2"]

load_l2_node 实现

python 复制代码
def load_l2_node(state: SkillsWorkflowState) -> SkillsWorkflowState:
    """L2:对选中技能加载完整 SKILL.md 正文。"""
    selected = state.get("selected_skill_names") or []
    l2_content: dict[str, str] = {}
    usage = dict(state.get("token_usage") or {})

    total_l2 = 0
    for name in selected:
        full, body = load_skill(name, DEFAULT_SKILLS_LIBRARY)
        if body:
            l2_content[name] = body
            total_l2 += count_tokens(body)

    usage["l2"] = total_l2
    return {
        **state,
        "l2_content": l2_content,
        "token_usage": usage,
    }

skill_loader 中的 load_skillskill_loader.py):

python 复制代码
def load_skill(skill_name: str, skills_root: Optional[Path] = None) -> Tuple[str, str]:
    """
    L2:加载技能。读取指定技能的完整 SKILL.md 内容。

    Args:
        skill_name: 技能名称(子目录名)。
        skills_root: 技能库根目录。

    Returns:
        (full_content, body_only)。body_only 为去掉 frontmatter 的正文。
    """
    root = Path(skills_root) if skills_root else DEFAULT_SKILLS_LIBRARY
    skill_dir = root / skill_name
    skill_md = skill_dir / SKILL_FILENAME
    if not skill_md.is_file():
        return "", ""

    try:
        full = skill_md.read_text(encoding="utf-8", errors="replace")
    except OSError:
        return "", ""

    body = full
    m = FRONTMATTER_PATTERN.match(full)
    if m:
        body = full[m.end() :].strip()
    return full, body

3.3.4 L3 按需加载:load_skill_resource 工具

职责 :遵循 agentskills.io / ADK SkillToolset 推荐做法,L3 由图节点提前加载,而是由 Agent 在 execute 阶段通过 load_skill_resource 工具按需调用

实现方式

  1. skill_tools.py :将 load_skill_resource 封装为 LangChain Tool(@tool),参数为 skill_nameresource_path,内部调用 skill_loader.load_skill_resource() 读取文件。

    py 复制代码
     @tool
     def load_skill_resource_tool(skill_name: str, resource_path: str) -> str:
         """加载技能参考资源(L3)。当技能指令(L2)要求阅读 references/ 中的某文件时调用此工具。
    
         Args:
             skill_name: 技能名称,如 blog-writer、seo-checklist。
             resource_path: 相对于技能目录的路径,如 references/style-guide.md 或 references/seo-guidelines.md。
    
         Returns:
             文件内容;若文件不存在则返回空字符串。
         """
         return load_skill_resource(skill_name, resource_path, DEFAULT_SKILLS_LIBRARY)
  2. SKILL.md 正文 :在 L2 指令中显式写明 「请使用 load_skill_resource 工具读取 references/xxx.md」,引导 LLM 在需要时调用该工具。

    py 复制代码
     ---
     name: blog-writer
     description: 博客写作技能,含结构模板与风格指南。适用于技术博客、产品介绍、教程类内容。当用户需要撰写博客、文章或教程时使用。
     ---
    
     # 博客写作指南
    
     当用户请求撰写博客时,请先使用 load_skill_resource 工具读取 `references/style-guide.md` 获取写作风格与禁忌,然后按以下结构组织内容:
    
     ## 步骤 1:确定主题与受众
     - 明确目标读者
     - 确定核心信息(读者读完应带走什么)
     - 选择合适的语气(正式/轻松/技术向)
  3. execute_node :将 L2 作为 system 上下文,将 load_skill_resource_tool 绑定到 LLM(bind_tools),运行 Agent 工具循环------LLM 根据 L2 指令决定是否调用工具,工具返回的 L3 内容进入对话上下文,LLM 据此完成任务。

何时加载 L3? 由 LLM 自主决定。当 L2 指令明确要求「使用 load_skill_resource 读取 references/xxx」时,LLM 会发起工具调用;若技能无 references 引用或 LLM 判断不需要,则不会加载,实现真正的按需加载。


3.3.5 execute_node:Agent 工具循环与 final_response

职责 :将 L2 作为 system 上下文,将 load_skill_resource 暴露为 Agent 工具;运行 Agent 工具循环,直至 LLM 生成最终回复;从工具调用结果中统计 L3 token 并填充 l3_content

流程 :SystemMessage(L2 + 用户任务 + 工具使用说明) + HumanMessage(用户任务) → llm.bind_tools([load_skill_resource_tool]).invoke(messages) → 若返回 tool_calls,依次执行工具,将 ToolMessage 追加到 messages,再次调用 LLM → 重复直至无 tool_calls,此时 response.content 即为 final_response

prompt 模板prompt.py):

python 复制代码
EXECUTE_SYSTEM_INSTRUCTION = """你正在使用以下 Agent Skills 的指令执行用户任务。请严格按照技能说明完成用户请求。

--- 技能指令(L2)---
{skill_instructions}
---

重要:当技能指令中提到需要参考 `references/xxx.md` 或类似路径时,你必须先调用 load_skill_resource 工具读取该文件内容,再据此执行任务。不要假设或猜测参考文件内容。

用户任务:
{user_input}
"""

execute_node 实现

python 复制代码
def execute_node(state: SkillsWorkflowState) -> SkillsWorkflowState:
    """
    执行节点:将 L2 作为 system 上下文,将 load_skill_resource 暴露为 Agent 工具。

    遵循 agentskills.io / ADK SkillToolset:Agent 根据 L2 指令按需调用 load_skill_resource,
    加载 references/ 中的文件(L3)。L3 不提前加载,由 LLM 在对话中主动调用工具获取。
    """
    l2 = state.get("l2_content") or {}
    user_task = state.get("user_task") or ""
    usage = dict(state.get("token_usage") or {})

    parts = [f"## 技能: {name}\n\n{body}" for name, body in l2.items()]
    skill_instructions = "\n\n---\n\n".join(parts) if parts else "(无技能指令)"

    if not _config.api_key:
        return {
            **state,
            "l3_content": {},
            "token_usage": {**usage, "l3": 0, "total": usage.get("l1", 0) + usage.get("l2", 0)},
            "final_response": "[请配置 OPENAI_API_KEY 或 DASHSCOPE_API_KEY]",
        }

    system_content = EXECUTE_SYSTEM_INSTRUCTION.format(
        skill_instructions=skill_instructions,
        user_input=user_task,
    )
    messages = [
        SystemMessage(content=system_content),
        HumanMessage(content=user_task),
    ]

    llm_with_tools = _llm.bind_tools(_TOOLS)
    l3_content: dict[str, str] = {}
    total_l3 = 0
    max_iterations = 10
    iterations = 0

    try:
        while iterations < max_iterations:
            iterations += 1
            response = llm_with_tools.invoke(messages)

            if not getattr(response, "tool_calls", None):
                break

            messages.append(response)

            for tc in response.tool_calls:
                tc_dict = tc if isinstance(tc, dict) else {"name": getattr(tc, "name", ""), "args": getattr(tc, "args", {}), "id": getattr(tc, "id", "")}
                name = tc_dict.get("name", "")
                args = tc_dict.get("args", {})
                tool_call_id = tc_dict.get("id", "")

                tool = _TOOLS_BY_NAME.get(name)
                result = ""
                if tool:
                    try:
                        result = tool.invoke(args)
                        if name == "load_skill_resource":
                            skill_name = args.get("skill_name", "")
                            resource_path = args.get("resource_path", "")
                            key = f"{skill_name}:{resource_path}"
                            l3_content[key] = result
                            total_l3 += count_tokens(result)
                    except Exception:
                        result = f"[工具 {name} 执行失败]"

                messages.append(
                    ToolMessage(content=str(result), tool_call_id=tool_call_id)
                )

        final = (response.content if hasattr(response, "content") else str(response) or "").strip()
    except Exception as e:
        final = f"[LLM 调用失败: {type(e).__name__}] 请检查 API 配置。技能已按 Progressive Disclosure 加载完成。"
        usage = dict(state.get("token_usage") or {})

    usage["l3"] = total_l3
    usage["total"] = usage.get("l1", 0) + usage.get("l2", 0) + total_l3

    return {
        **state,
        "l3_content": l3_content,
        "token_usage": usage,
        "final_response": final,
    }

💡 理解要点 :四个图节点(discover → select → load_l2 → execute);L3 在 execute_node 内部的工具循环中按需加载 ,由 LLM 根据 L2 指令主动调用 load_skill_resource,符合 agentskills.io 与 ADK SkillToolset 规范。


4. Token 计量与对比:tiktoken 驱动

4.1 计量模块

token_counter.py 提供 count_tokens(text, model),基于 tiktoken 对给定文本统计 token 数。支持 cl100k_base(GPT-4/3.5 等)编码。

4.2 对比模式

Demo 支持两种运行模式:

  1. Progressive 模式:按 L1 → select → L2 → L3 → execute 流程,仅加载选中技能的内容;
  2. Monolithic 模式:一次性加载所有技能的完整 SKILL.md + references,模拟「全量 system prompt」方式。

main.ipynb 中,对同一 user_task 分别跑两种模式,输出类似:

模式 L1 L2 L3 总计
Progressive 420 380 0 800
Monolithic --- --- --- 7200

从而直观看到:当用户只需 1 个技能时,Progressive 可节省约 90% 的 skill 相关 token。


5. 运行方式

5.1 环境与依赖

  • Python 3.9+
  • 依赖见 demo_codes/requirements.txtlanggraphlangchain-openaitiktokenpython-dotenv

5.2 配置

demo_codes/ 下创建 .env

复制代码
OPENAI_API_KEY=sk-...   # 或 DASHSCOPE_API_KEY
BASE_URL=               # 可选,如使用代理
MODEL=gpt-4o-mini       # 可选

5.3 运行

命令行

shell 复制代码
cd demo_codes
python main.py
python main.py "请检查下面博客的 SEO:..."

Notebook :打开 main.ipynb,可逐步运行 discover → select → load_l2 → load_l3 → execute,以及 token 对比实验。

如下是 main.ipynb 中运行的测试代码的详细日志返回:

复制代码
user_task = "请检查下面这段话的 SEO 并给出改进建议:LangGraph 是一个用于构建多步推理与智能体工作流的 Python 库,支持状态图与条件边。"

返回:

复制代码
--- 运行日志 (verbose=1) ---
  [discover] 开始扫描 skills_library...
  [discover] 发现 4 个技能: ['blog-writer', 'code-review', 'research-summarizer', 'seo-checklist']
  [discover] L1 token: 268
  [select] 用户任务: 请检查下面这段话的 SEO 并给出改进建议:LangGraph 是一个用于构建多步推理与智能体工作流的 Python 库...
  [select] 调用 LLM 进行技能语义匹配...
  [select] 选中技能: ['seo-checklist']
  [load_l2] 加载 L2: ['seo-checklist']
  [load_l2]   seo-checklist: 499 tokens
  [load_l2] L2 总计: 499 tokens
  [execute] 执行任务,技能: ['seo-checklist']
  [execute] LLM 调用 (迭代 1)...
  [execute] LLM 请求 1 次工具调用
  [execute]   [Tool] load_skill_resource_tool({'skill_name': 'seo-checklist', 'resource_path': 'references/seo-guidelines.md'})
  [execute]     -> L3 加载 seo-checklist:references/seo-guidelines.md, 280 tokens
  [execute] LLM 调用 (迭代 2)...
  [execute] LLM 返回最终回复(无工具调用)
  [execute] L3 总计: 280 tokens, 最终回复: 3315 字符
=== Progressive 模式 Token 消耗 ===
L1: 268 | L2: 499 | L3: 280 | 总计: 1047
选中技能: ['seo-checklist']

=== Monolithic 模式 Token 消耗 ===
L2+L3 总计: 2174

Progressive 节省约 1127 tokens (52%)

5.4 技能库

Demo 自带 skills_library/,内含 seo-checklistblog-writercode-reviewresearch-summarizer 四个技能。其中 seo-checklistblog-writerreferences/ 子目录,用于演示 L3 加载。若需扩展,可参考 skills_library/README.md 按 Agent Skills 规范添加新技能。


6. 小结与延伸

6.1 核心结论

  • Progressive Disclosure 将技能知识分为 L1(元数据)、L2(指令)、L3(资源)三层,按需加载,显著降低 baseline token 消耗;
  • LangGraph 可清晰编排 discover → select → load_l2 → (load_l3,这里通过Tools调用) → execute 流程,每步对应一个节点,状态在图中流转;
  • Token 计量:用 tiktoken 统计各层消耗,并与全量加载对比,可量化 Progressive Disclosure 的收益。

6.2 延伸方向

  1. 技能选择 :可调整 SELECT_SKILL_PROMPT 或引入 few-shot 示例,以提升复杂任务下的匹配准确度;
  2. 多技能组合:支持同一任务加载多个技能(如 blog-writer + seo-checklist),L2 合并后一并交给 LLM,L3 由 Agent 按需调用;
  3. LangGraph 7. 技能 Skills 集成 :本 demo 的 skill_loaderLangGraph 7. 技能 Skills 的发现/加载逻辑兼容,可复用或替换为 LangGraph 7. 技能 Skillsskill_loader.py
  4. 生产化:将 token 计量接入监控,设置阈值告警;对高频技能可做 L2 缓存,进一步减少重复读取。

参考资料

相关推荐
吴佳浩 Alben2 小时前
GPU 编号错乱踩坑指南:PyTorch cuda 编号与 nvidia-smi 不一致
人工智能·pytorch·python·深度学习·神经网络·语言模型·自然语言处理
AI茶水间管理员2 小时前
爆火的OpenClaw到底强在哪?一文了解核心架构(附一条消息的全链路流程)
人工智能·后端
Agent产品评测局2 小时前
中小企业数字化转型,优先选 RPA 还是 AI Agent?:2026企业自动化架构选型深研
人工智能·ai·chatgpt·自动化·rpa
Master_oid2 小时前
机器学习35:元学习的应用
人工智能·学习·机器学习
Echo_NGC22372 小时前
【卷积神经网络 CNN】一文讲透卷积神经网络CNN的核心概念与演进历程
人工智能·深度学习·神经网络·目标检测·机器学习·自然语言处理·cnn
achi0102 小时前
Ubuntu 24 Desktop LTS 部署 AI 智能体 OpenClaw
人工智能·ai agent·openclaw·openclaw 安装·openclaw 部署·ubuntu openclaw·agent 部署
吴佳浩 Alben2 小时前
CUDA_VISIBLE_DEVICES、多进程与容器化陷阱
人工智能·pytorch·语言模型·transformer
用户2704272838122 小时前
排查 OpenClaw token 暴涨:MEMORY.md 藏了83行废话,3个Cron任务静默失败
人工智能
郑同学zxc2 小时前
机器学习19-tensorflow4.2
人工智能·机器学习