Langgraph 18. Skill 四种形态 —— Inline / File-based / External / Meta(含代码示例)

摘要 :本文介绍 Agent Skills 的四种形态 ------Inline(内联)、File-based(文件型)、External(外部型)、Meta(元技能),帮助架构师根据场景选择合适形态、实现可复用技能库。案例介绍 :配套 demo 实现一个「技能工厂」智能体,具备四类能力------(1) Inline 形态的快速格式化规则;(2) File-based 形态的博客写作与 SEO 技能;(3) External 形态的社区研究技能(模拟从 awesome-claude-skills 拉取);(4) Meta 形态的技能创造器,根据用户需求生成符合 agentskills.io 规范的 SKILL.md技术要点 :用 LangGraph 编排条件路由(任务执行 vs 技能创建),统一 skill_loader_ext 支持多种形态的发现与加载,Meta 技能通过 references/skill-spec.mdreferences/example-skill.md 引导 LLM 生成新技能。

关键词:Agent Skills;Inline;File-based;External;Meta;技能工厂;agentskills.io;LangGraph

源代码链接:LangGraph 18. Skill 四种形态 示例源代码


1. 为什么需要区分 Skill 的多种形态?

1.1 现实场景的多样性

想象你正在搭建一个企业级内容智能体。有些能力是稳定的、简短的 ------例如「输出时用 Markdown 标题分级」「避免使用第一人称」。这些规则不需要外部文件,改动的频率低。另一些能力则复杂且需要大量参考资料------例如 SEO 优化涉及 9 类检查项、每类有详细指南;博客写作需要风格手册、禁忌列表、段落模板。若把所有知识塞进一个 Python 字符串,既难维护,也无法版本控制。

进一步,你可能希望复用社区已有技能 ------awesome-claude-skills 等仓库中有上百个现成技能,直接拉取即可使用,无需自己撰写。更有甚者,你希望智能体具备「自我扩展」能力------当用户说「帮我创建一个 Python 安全审查技能」时,智能体能根据 agentskills.io 规范生成新的 SKILL.md,并将其纳入技能库。

💡 理解要点:不同形态的 Skill 适用于不同生命周期、来源和复杂度。统一用「一种写法」会导致要么过度简单(Inline 撑不住复杂技能),要么过度笨重(所有技能都拆成目录和 references,增加维护成本)。

1.2 四种形态的核心定义

参考 Lavi Nigam 的 ADK Skills 系列agentskills.io 规范,可将 Skill 归纳为四种形态:

形态 定义 来源 典型场景
Inline Python 内联定义,{name, description, instructions} 字典 代码 稳定、无需外部文件的简单规则
File-based SKILL.md + references/,符合 agentskills.io 目录结构 本地目录 需要 L3 资源的复杂技能,可版本控制
External 与 File-based 结构相同,来源为社区仓库或外部路径 克隆/下载目录 复用他人已写好的技能
Meta 技能的输出是新的 SKILL.md,使智能体能「写出新技能」 技能 + 规范资源 按需创建新能力,自我扩展

🔍 实际例子:Inline 适合「用项目符号输出清单」;File-based 适合 blog-writer(含 references/style-guide.md);External 适合从 awesome-claude-skills 克隆的 content-research-writer;Meta 则是一个 skill-creator,其 instructions 描述「如何撰写 SKILL.md」,resources 嵌入规范与示例,LLM 据此生成新技能文件。

1.3 与 17. Progressive Disclosure 的关系

17. Progressive Disclosure 介绍了 L1/L2/L3 分层加载与 load_skill_resource 按需调用。四种形态是技能来源与定义方式的分类,与 Progressive Disclosure 正交:无论 Inline 还是 File-based,都可以按 L1→L2→L3 的方式加载;External 与 File-based 在加载逻辑上完全一致,仅根路径不同;Meta 是特殊形态,其「执行」结果是生成新的 SKILL.md 文件。


2. 示例设定:「技能工厂」智能体

2.1 案例背景

我们构建一个技能工厂智能体,具备以下能力:

  • Inline 形态format-output------输出格式规则(用 Markdown、项目符号、避免冗长句子);
  • File-based 形态blog-writerseo-checklist,来自 skills_library/
  • External 形态content-research,模拟从社区拉取,存放在 external_skills/
  • Meta 形态skill-creator------根据用户需求生成新的 SKILL.md,写入 skills_library/ 并可供后续使用。

用户可能提出两类请求:

  1. 任务执行:「写一篇关于 LangGraph 的博客开头并做 SEO 优化」→ 使用 blog-writer + seo-checklist + format-output;
  2. 技能创建:「帮我创建一个 Python 代码安全审查技能」→ 调用 skill-creator,生成 SKILL.md 并加载。

2.2 方案设计

配套 demo 实现基于 LangGraph 的技能工厂

复制代码
                    START
                      ↓
              [意图路由] user_task
                      ↓
         ┌────────────┴────────────┐
         ↓                         ↓
   "创建技能" / "生成技能"        其他任务
         ↓                         ↓
   meta_skill_node           discover_node (Inline + File + External)
         ↓                         ↓
   生成 SKILL.md              select_node → load_l2_node → execute_node
         ↓                         ↓
   写入 skills_library             END
         ↓
        END
  • 意图路由:LLM 判断用户是否在请求「创建/生成新技能」,若是则进入 meta 分支,否则进入任务执行分支。
  • discover_node:从 Inline、File-based、External 三处汇总 L1 元数据,统一呈现给 select。
  • skill_loader_ext :扩展 skill_loader,支持 (1) Inline 字典直接返回 (2) 指定根路径加载 File-based / External。

2.3 典型流程示例

场景 A:用户输入「请写一段关于 LangGraph 的博客开头,并检查 SEO」。

  • 意图路由 → 任务执行;
  • Discover 汇总 format-output、blog-writer、seo-checklist、content-research 的 L1;
  • Select 选出 blog-writer、seo-checklist、format-output;
  • Load L2,Execute 时按需调用 load_skill_resource 加载 L3;
  • 输出格式遵循 format-output,内容遵循 blog-writer 与 seo-checklist。

场景 B:用户输入「帮我创建一个用于检查 Python 代码安全的技能」。

  • 意图路由 → 技能创建;
  • 加载 skill-creator 的 L2 + references(skill-spec.mdexample-skill.md);
  • LLM 根据规范与示例生成 python-security-review SKILL.md
  • 写入 skills_library/python-security-review/SKILL.md
  • 可立即通过 discover 发现并用于后续任务。

3. 状态与图结构:LangGraph 编排

3.1 状态定义

python 复制代码
class SkillFactoryState(TypedDict):
    user_task: str
    intent: str                    # "create_skill" | "execute_task"
    l1_skills: list
    selected_skill_names: list
    l2_content: dict
    l3_content: dict
    created_skill_name: str       # meta 分支:新技能名
    created_skill_path: str       # meta 分支:写入路径
    final_response: str
    verbose: NotRequired[bool]

3.2 图结构

text 复制代码
START
  ↓
route_node           # LLM 判断 intent: create_skill | execute_task
  ↓
条件边 ─┬─ create_skill → meta_skill_node → END
        └─ execute_task → discover_node → select_node → load_l2_node → execute_node → END

流程中,state["verbose"]=True 时,各节点通过 _log(state, msg, node) 输出日志到 terminal / notebook,便于调试与观察。

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

下文逐一说明每个节点的职责、调用链路、verbose 日志及关键代码。


3.3.1 route_node:意图路由

职责 :根据 user_task 判断用户意图------是「创建/生成新技能」还是「使用现有技能执行任务」。LLM 根据 ROUTE_PROMPT 返回 create_skillexecute_task,写入 state["intent"]。未配置 API 或任务为空时,默认 execute_task。这里,我们是通过LLM嵌入到Langgraph node来实现意图识别。

调用链路route_nodeChatPromptTemplate.from_template(ROUTE_PROMPT)_llm.invoke → 解析响应 → 更新 intent

verbose 日志:用户输入摘要、未配置 API 时的默认行为、最终意图。

route_node 实现skill_factory_graph.py):

python 复制代码
def route_node(state: SkillFactoryState) -> SkillFactoryState:
    """意图路由:判断 create_skill 或 execute_task。"""
    user_task = state.get("user_task") or ""
    _log(state, f"用户输入: {user_task[:80]}{'...' if len(user_task) > 80 else ''}", "route")

    if not _config.api_key or not user_task.strip():
        _log(state, "未配置 API 或任务为空,默认 execute_task", "route")
        return {**state, "intent": "execute_task"}

    prompt = ChatPromptTemplate.from_template(ROUTE_PROMPT)
    chain = prompt | _llm
    response = chain.invoke({"user_task": user_task})
    content = (response.content if hasattr(response, "content") else str(response)).strip().lower()

    intent = "create_skill" if "create_skill" in content else "execute_task"
    _log(state, f"意图: {intent}", "route")
    return {**state, "intent": intent}

ROUTE_PROMPTprompt.py):引导 LLM 仅返回 create_skillexecute_task,用于条件边分支。

py 复制代码
ROUTE_PROMPT = """你是一个技能工厂助手。用户可能提出两类请求:
1. **创建/生成新技能**:如「帮我创建一个 XXX 技能」「生成一个 YYY 技能」
2. **执行任务**:使用现有技能完成某任务,如写博客、检查 SEO、做研究等

用户输入:
{user_task}

请判断用户意图。仅返回以下之一(不要解释):
- create_skill:用户明确要求创建/生成/编写一个新的技能
- execute_task:用户在使用现有技能执行任务,或意图不明确时"""

3.3.2 meta_skill_node:Meta 技能执行

如果上面的 route_node 根据用户的输入判断 create_skill,即,创建新的skill支线,这个时候系统会调用 skill_meta.run_meta_skill,根据用户需求生成符合 agentskills.ioSKILL.md,写入 skills_library/{name}/SKILL.md。成功时更新 created_skill_namecreated_skill_pathfinal_response;失败时 final_response 为错误信息。

调用链路meta_skill_noderun_meta_skill(user_task, ...) → 内部加载 skill-creator 的 references、调用 LLM 生成、解析 frontmatter、写入文件。

verbose 日志:执行开始、run_meta_skill 内部的「加载 references」「调用 LLM」「已写入路径」、最终结果。

meta_skill_node 实现

python 复制代码
def meta_skill_node(state: SkillFactoryState) -> SkillFactoryState:
    """Meta 技能:生成新 SKILL.md 并写入 skills_library。"""
    user_task = state.get("user_task") or ""
    _log(state, "执行 Meta 技能:生成新 SKILL.md...", "meta_skill")

    name, path = run_meta_skill(
        user_task, DEFAULT_SKILLS_LIBRARY, _config, verbose=bool(state.get("verbose"))
    )

    if name:
        final = f"已创建技能「{name}」,路径:{path}。可通过 discover 发现并用于后续任务。"
        _log(state, final, "meta_skill")
        return {
            **state,
            "created_skill_name": name,
            "created_skill_path": path,
            "final_response": final,
        }
    else:
        final = path or "[Meta 技能执行失败]"
        return {
            **state,
            "created_skill_name": "",
            "created_skill_path": "",
            "final_response": final,
        }
py 复制代码
def run_meta_skill(
    user_demand: str,
    skills_library: Optional[Path] = None,
    config: Optional[SkillFactoryConfig] = None,
    verbose: bool = False,
) -> Tuple[str, str]:
    """
    执行 Meta 技能:根据用户需求生成 SKILL.md 并写入 skills_library。

    Returns:
        (created_skill_name, output_path)
        若失败则 created_skill_name 为空,output_path 为错误信息。
    """
    config = config or SkillFactoryConfig()
    skills_library = Path(skills_library) if skills_library else DEFAULT_SKILLS_LIBRARY

    if not config.api_key:
        return "", "[未配置 OPENAI_API_KEY 或 DASHSCOPE_API_KEY]"

    if verbose:
        print("  [meta_skill] 加载 skill-creator 的 references...")
    skill_spec, example_skill, creator_instructions = _load_meta_references()
    if verbose:
        print("  [meta_skill] 调用 LLM 生成 SKILL.md...")

    prompt = ChatPromptTemplate.from_template(META_SYSTEM_PROMPT)
    llm = ChatOpenAI(
        model=config.model,
        api_key=config.api_key,
        base_url=config.base_url if config.base_url else None,
        temperature=0.3,
    )
    chain = prompt | llm

    try:
        response = chain.invoke({
            "skill_spec": skill_spec,
            "example_skill": example_skill,
            "creator_instructions": creator_instructions,
            "user_demand": user_demand,
        })
        content = (response.content if hasattr(response, "content") else str(response)).strip()
    except Exception as e:
        return "", f"[LLM 调用失败: {type(e).__name__}] {e}"

    if not content:
        return "", "[生成内容为空]"

    # 确保以 --- 开头(可能 LLM 多输出了解释)
    if "---" in content:
        idx = content.index("---")
        content = content[idx:]
    else:
        content = "---\nname: generated-skill\ndescription: 自动生成的技能。\n---\n\n" + content

    name = _extract_skill_name_from_output(content)
    if not name:
        name = "generated-skill"
    safe_name = _sanitize_skill_name(name)

    output_dir = skills_library / safe_name
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / "SKILL.md"

    try:
        output_path.write_text(content, encoding="utf-8")
        if verbose:
            print(f"  [meta_skill] 已写入: {output_path}")
        return safe_name, str(output_path)
    except OSError as e:
        return "", f"[写入失败] {e}"

对应的 prompt(META_SYSTEM_PROMPT) 是:

py 复制代码
META_SYSTEM_PROMPT = """你是一个技能撰写专家,根据用户需求生成符合 agentskills.io 规范的 SKILL.md。

## 规范摘要

{skill_spec}

## 参考示例

{example_skill}

## 技能创建指令(skill-creator)

{creator_instructions}

## 用户需求

{user_demand}

请直接输出**完整的 SKILL.md 内容**,从 `---` 开始,到正文结束。不要输出任何解释或前后缀。"""

3.3.3 discover_node:多形态 L1 发现

如果上面的 route_node 根据用户的输入判断 execute_task,即,创建根据用户的输入匹配skills然后回复。

从 Inline(skill_inline.get_inline_skill_l1)、File-based(skills_library/)、External(external_skills/)三处汇总 L1 元数据,去重时 Inline > File > External 优先;计算 L1 token 写入 token_usage["l1"]

调用链路discover_nodeget_inline_skill_l1()discover_all_skills()count_tokens(l1_text)

verbose 日志:汇总开始、发现的技能列表(含形态来源)、L1 token。

discover_node 实现

python 复制代码
def discover_node(state: SkillFactoryState) -> SkillFactoryState:
    """发现 Inline + File-based + External 的 L1。"""
    _log(state, "汇总 Inline、File-based、External 技能...", "discover")

    inline_l1 = get_inline_skill_l1()
    all_skills = discover_all_skills(
        inline_l1,
        file_root=DEFAULT_SKILLS_LIBRARY,
        external_root=DEFAULT_EXTERNAL_SKILLS,
    )

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

    _log(state, f"发现 {len(all_skills)} 个技能: {[s.get('name') for s in all_skills]}", "discover")
    _log(state, f"L1 token: {usage['l1']}", "discover")
    return {**state, "l1_skills": all_skills, "token_usage": usage}


def discover_all_skills(
    inline_l1: List[Dict[str, str]],
    file_root: Optional[Path] = None,
    external_root: Optional[Path] = None,
) -> List[Dict[str, str]]:
    """
    汇总 Inline、File-based、External 的 L1 元数据。
    去重:若 name 重复,以 Inline > File > External 优先保留。
    """
    file_root = Path(file_root) if file_root else DEFAULT_SKILLS_LIBRARY
    external_root = Path(external_root) if external_root else DEFAULT_EXTERNAL_SKILLS

    seen: set[str] = set()
    result: List[Dict[str, str]] = []

    for meta in inline_l1:
        name = meta.get("name", "")
        if name and name not in seen:
            seen.add(name)
            m = dict(meta)
            m["_source"] = "inline"
            result.append(m)

    for meta in _discover_from_dir(file_root, "file"):
        name = meta.get("name", "")
        if name and name not in seen:
            seen.add(name)
            result.append(meta)

    for meta in _discover_from_dir(external_root, "external"):
        name = meta.get("name", "")
        if name and name not in seen:
            seen.add(name)
            result.append(meta)

    return result

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

职责 :根据 user_taskl1_skills 中选出 1~3 个相关技能名。使用 LLM 语义匹配,解析逗号分隔的响应并校验名称是否在 l1_skills 中。无技能或未配置 API 时返回空列表。

调用链路select_nodeChatPromptTemplate.from_template(SELECT_SKILL_PROMPT)_llm.invoke → 解析并过滤 → selected_skill_names

verbose 日志:用户任务摘要、无技能/未配置 API 的跳过、LLM 调用、选中技能列表。

select_node 实现

python 复制代码
def select_node(state: SkillFactoryState) -> SkillFactoryState:
    """根据 user_task 选出相关技能。"""
    skills = state.get("l1_skills") or []
    user_task = state.get("user_task") or ""
    _log(state, f"用户任务: {user_task[:60]}{'...' if len(user_task) > 60 else ''}", "select")

    if not skills:
        _log(state, "无可用技能,跳过选择", "select")
        return {**state, "selected_skill_names": []}
    if not _config.api_key or not user_task.strip():
        _log(state, "未配置 API 或任务为空,跳过 LLM 选择", "select")
        return {**state, "selected_skill_names": []}

    _log(state, "调用 LLM 进行技能语义匹配...", "select")
    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 if hasattr(response, "content") else str(response)).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)

    _log(state, f"选中技能: {selected}", "select")
    return {**state, "selected_skill_names": selected}

3.3.5 load_l2_node:统一加载 L2

职责 :对 selected_skill_names 中每个技能,调用 load_skill_unified 按 Inline → File → External 顺序加载 L2 正文;累计 L2 token 写入 token_usage["l2"]

调用链路load_l2_nodeload_skill_unified(name, get_inline_skill_l2, ...)skill_loader_ext 内部按形态查找。

verbose 日志:加载的技能列表、每个技能的 token 数、L2 总计。

load_l2_node 实现

python 复制代码
def load_l2_node(state: SkillFactoryState) -> SkillFactoryState:
    """加载选中技能的 L2(支持 Inline / File / External)。"""
    selected = state.get("selected_skill_names") or []
    _log(state, f"加载 L2: {selected}", "load_l2")

    l2_content = {}
    usage = dict(state.get("token_usage") or {})

    for name in selected:
        body, _ = load_skill_unified(
            name, get_inline_skill_l2,
            file_root=DEFAULT_SKILLS_LIBRARY,
            external_root=DEFAULT_EXTERNAL_SKILLS,
        )
        if body:
            l2_content[name] = body
            _log(state, f"  {name}: {count_tokens(body)} tokens", "load_l2")

    total_l2 = sum(count_tokens(b) for b in l2_content.values())
    usage["l2"] = total_l2
    _log(state, f"L2 总计: {total_l2} tokens", "load_l2")
    return {**state, "l2_content": l2_content, "token_usage": usage}

3.3.6 execute_node:Agent 工具循环与 final_response

职责 :将 L2 作为 system 上下文,将 load_skill_resource 暴露为 Agent 工具;运行工具循环(LLM 调用 → 若有 tool_calls 则执行 → 追加 ToolMessage → 再次调用),直至无 tool_calls;从工具调用结果统计 L3 token,填充 l3_contentfinal_response

调用链路execute_nodellm.bind_tools([load_skill_resource_tool])invoke(messages) 循环 → 工具调用 → count_tokens 统计 L3。

verbose 日志:执行任务与技能列表、每次 LLM 迭代、工具调用(名称与参数)、L3 加载与 token、工具失败、L3 总计与最终回复长度。

execute_node 实现(节选):

python 复制代码
def execute_node(state: SkillFactoryState) -> SkillFactoryState:
    """执行:L2 + load_skill_resource 工具循环。"""
    l2 = state.get("l2_content") or {}
    user_task = state.get("user_task") or ""
    _log(state, f"执行任务,技能: {list(l2.keys())}", "execute")
    # ... 构建 system_content, messages ...

    llm_with_tools = _llm.bind_tools(_TOOLS)
    l3_content, total_l3 = {}, 0
    while iterations < max_iterations:
        _log(state, f"LLM 调用 (迭代 {iterations})...", "execute")
        response = llm_with_tools.invoke(messages)
        if not getattr(response, "tool_calls", None):
            _log(state, "LLM 返回最终回复(无工具调用)", "execute")
            break
        _log(state, f"LLM 请求 {len(response.tool_calls)} 次工具调用", "execute")
        for tc in response.tool_calls:
            _log(state, f"  [Tool] {name}({args})", "execute")
            # ... 执行工具 ...
            _log(state, f"    -> L3 加载 {key}, {tokens} tokens", "execute")
        # ...
    _log(state, f"L3 总计: {total_l3} tokens, 最终回复: {len(final)} 字符", "execute")
    return {**state, "l3_content": l3_content, "token_usage": usage, "final_response": final}

3.3.7 辅助模块

skill_inline.pyINLINE_SKILLS 列表(format-output、concise-response),get_inline_skill_l1()get_inline_skill_l2(name)has_inline_skill(name)

skill_loader_ext.pydiscover_all_skillsload_skill_unifiedload_skill_resource,支持 Inline / File / External 三形态。

skill_meta.pyrun_meta_skill(user_demand, skills_library, config, verbose),加载 skill-creator 的 references、调用 LLM 生成、写入 SKILL.md

💡 理解要点 :六个图节点(route、meta_skill、discover、select、load_l2、execute)均通过 _log(state, msg, node)verbose=True 时输出日志;main.py -vmain.ipynbVERBOSE=True 可观测完整运行流程与工具调用。


4. 运行方式

4.1 环境与依赖

  • Python 3.9+
  • langgraphlangchain-openailangchain-corepython-dotenvtiktoken

4.2 配置

demo_codes/ 下创建 .env

复制代码
OPENAI_API_KEY=sk-...
BASE_URL=        # 可选
MODEL=gpt-4o-mini

4.3 运行

shell 复制代码
cd demo_codes
python main.py
python main.py "写一段关于 LangGraph 的博客开头"
python main.py "帮我创建一个 Python 代码安全审查技能"
python main.py -v "..."   # verbose=1 时输出各节点与工具调用日志

Notebook :打开 main.ipynb,设置 VERBOSE = True 可输出各节点与工具调用的详细日志;依次运行:图展示 → 任务执行示例 → 技能创建示例 → 形态对比。

verbose 日志示例python main.py -v "写一段关于 LangGraph 的博客开头"):

复制代码
--- 运行日志 (verbose=1) ---
  [route] 用户输入: 写一段关于 LangGraph 的博客开头...
  [route] 意图: execute_task
  [discover] 汇总 Inline、File-based、External 技能...
  [discover] 发现 5 个技能: ['format-output', 'concise-response', 'blog-writer', 'seo-checklist', 'content-research']
  [discover] L1 token: 328
  [select] 用户任务: 写一段关于 LangGraph 的博客开头...
  [select] 调用 LLM 进行技能语义匹配...
  [select] 选中技能: ['format-output', 'blog-writer', 'seo-checklist']
  [load_l2] 加载 L2: ['format-output', 'blog-writer', 'seo-checklist']
  [load_l2]   format-output: 89 tokens
  [load_l2]   blog-writer: 499 tokens
  [load_l2]   seo-checklist: 499 tokens
  [load_l2] L2 总计: 1087 tokens
  [execute] 执行任务,技能: ['format-output', 'blog-writer', 'seo-checklist']
  [execute] LLM 调用 (迭代 1)...
  [execute] LLM 请求 2 次工具调用
  [execute]   [Tool] load_skill_resource_tool({'skill_name': 'blog-writer', 'resource_path': 'references/style-guide.md'})
  [execute]     -> L3 加载 blog-writer:references/style-guide.md, 285 tokens
  [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 总计: 565 tokens, 最终回复: 2847 字符

4.4 目录结构

复制代码
18_skills_3/
├── 18_skills_3.md
└── demo_codes/
    ├── skill_inline.py        # Inline 形态定义
    ├── skill_loader_ext.py    # 多形态统一加载
    ├── skill_meta.py          # Meta 技能运行器
    ├── skill_factory_graph.py # LangGraph 图
    ├── skills_library/        # File-based 技能
    │   ├── blog-writer/
    │   ├── seo-checklist/
    │   └── ...
    ├── external_skills/       # External 技能(模拟社区)
    │   └── content-research/
    ├── skill_creator/         # Meta 技能
    │   ├── SKILL.md
    │   └── references/
    │       ├── skill-spec.md
    │       └── example-skill.md
    ├── main.py, main.ipynb
    ├── README.md
    └── requirements.txt

5. 小结与延伸

5.1 核心结论

  • 四种形态各有适用场景:Inline 快速稳定,File-based 可版本控制,External 复用社区,Meta 实现自我扩展;
  • skill_loader_ext 统一发现与加载逻辑,使 Agent 无需关心技能来自代码、本地还是外部;
  • LangGraph 条件路由清晰表达「任务执行」与「技能创建」两条主流程。

5.2 延伸方向

  1. External 实际拉取 :集成 git clonenpx skills add,从真实社区仓库拉取技能;
  2. Meta 校验增强 :使用 skills-ref validate 校验生成的 SKILL.md
  3. 与 "Langgraph 17. Skills 三级加载与 Token 优化" 整合:在 execute 分支中暴露 load_skill_resource 工具,L3 按需加载。

5.3 注意事项

  • 使用 External 技能前务必审阅 SKILL.md 与 references,技能指令会直接影响 Agent 行为;
  • Meta 生成的技能建议先人工复核再投入生产。

参考资料

相关推荐
好家伙VCC12 小时前
**发散创新:基于Python与OpenCV的视频流帧级分析实战**在当前人工智能与计算机视觉飞速发展的背景下
java·人工智能·python·计算机视觉
lpfasd12312 小时前
Harness架构将成为AI工程的终极范式
人工智能·架构
xiaotao13112 小时前
阶段零:IDE选择 与 Jupyter Notebook / Lab 使用
ide·人工智能·python·jupyter
TDengine (老段)12 小时前
中原油田引入时序数据库 TDengine:写入性能提升、存储成本下降 85%
大数据·数据库·人工智能·时序数据库·tdengine·涛思数据
IT_陈寒12 小时前
SpringBoot里的这个坑差点让我加班到天亮
前端·人工智能·后端
财经资讯数据_灵砚智能12 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年4月12日
大数据·人工智能·信息可视化·自然语言处理·ai编程
nix.gnehc12 小时前
实战部署|Ollama\+Qwen2\.5:3b\+Open WebUI 本地AI助手搭建全记录(附避坑指南)
人工智能·大模型·llm·ollama
FIT2CLOUD飞致云12 小时前
新增工作流类型工具,对话时可选择模型与知识库,MaxKB开源企业级智能体平台v2.8.0版本发布
人工智能·ai·开源·智能体·maxkb
code 小楊12 小时前
从开源折戟到闭源破局:Meta Muse Spark 全解析(含案例+调用指南)
人工智能·开源
deepdata_cn12 小时前
智能体的5个认知误区
人工智能·智能体