资讯动态

ADK-python 技能会话状态注入实战:用 adk_inject_state 让 SKILL.md 动态读取 Session State

发布时间:2026/9/13 11:58:35 来源:尧图企业网站定制
ADK-python 技能会话状态注入实战用 adk_inject_state 让 SKILL.md 动态读取 Session State【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python导读本指南基于 ADKAgent Development Kit官方示例 skills_inject_state系统讲解如何通过SKILL.mdfrontmatter 中的一行声明metadata.adk_inject_state: true让 Skill 在加载时自动把会话状态Session State中的值注入到指令模板中实现「同一个 Skill、不同会话、不同个性化指令」。读完本文你将掌握{key}、{key?}、{user:key}等占位符语法、完整的示例工程拆解、底层注入实现原理以及状态新鲜度相关的正确使用姿势。为什么需要状态注入告别「Getter 工具 额外一次 LLM 往返」在 Agent 应用里Skill 经常需要读取 Agent 已经持有的信息——用户偏好、对话上下文、某个配置值等。在引入adk_inject_state之前一个需要读取状态的 Skill 通常要走下面这条笨重链路为 Skill 单独编写一个自定义的 getter 工具专门负责从状态里取值通过SkillToolset(additional_tools[...])把这个工具挂接到 Skill 上在 Skill 指令中指示模型先调用这个 getter 工具拿到值之后再执行真正的任务。这条链路带来了双重开销多写一份应用代码getter 工具本身以及运行时多一次 LLM 往返模型必须实际调用该工具才能读到状态。对一个本该专注于「按规则干活」的 Skill 来说这是不必要的样板代码。adk_inject_state正是为消除这份样板而设计的声明式方案当 Skill 的SKILL.mdfrontmatter 设置了metadata.adk_inject_state: trueLoadSkillTool会在加载 Skill 时通过inject_session_state渲染 Skill 正文把其中的{placeholder}替换为会话状态中对应的值。这套{var}/{var?}插值语法与LlmAgent.instruction所支持的完全一致见 instructions_utils.py如今被扩展到了 Skill 场景只需一行声明式改动即可启用。示例概览一个会「认人」的代码审查 Skill官方示例 agent.py 构建了一个名为skills_inject_state_agent的 Agent它展示的核心能力有四点选择注入Opt-in在SKILL.md的 frontmatter 中设置metadata.adk_inject_state: true声明式状态访问在 Skill 正文里直接用{dev_name}、{dev_language}、{dev_level}占位符引用会话状态无需任何 getter 工具状态填充一个remember_developer_profile工具把开发者档案写入会话状态Skill 稍后通过注入读取状态新鲜度理解状态值只在 Skill 加载时物化materialize一次加载之后的状态变更不会影响已加载的 Skill除非重新加载。工作流程graph TD User --|1. introduces themselves| Agent[Agent: skills_inject_state_agent] Agent --|writes dev_name, dev_language, dev_level| State[(Session State)] User --|2. asks for a code review| Agent Agent --|load_skill code-review-skill| Toolset[SkillToolset] State -. injected into instructions .- Toolset Toolset --|instructions with state filled in| Agent第一步用户在会话中自我介绍Agent 调用remember_developer_profile把档案写入状态第二步用户请求代码审查Agent 通过load_skill加载code-review-skill由于该 Skill 已声明状态注入占位符在指令返回前就已经被状态值填充完毕——全程没有额外的工具调用。示例工程拆解Agent 与 SKILL.md 的双向配合Agent 侧写状态与挂 Skill在 agent.py 中remember_developer_profile是一个带tool_context: ToolContext参数的普通函数工具通过tool_context.state[dev_name]等方式把档案写入会话状态def remember_developer_profile( name: str, primary_language: str, experience_level: str, tool_context: ToolContext, ) - dict: Saves the developers profile into session state for later personalization. tool_context.state[dev_name] name tool_context.state[dev_language] primary_language tool_context.state[dev_level] experience_level return { status: ok, stored: { dev_name: name, dev_language: primary_language, dev_level: experience_level, }, }随后用load_skill_from_dir加载目录型 Skill装入SkillToolset并挂到根 Agent 上code_review_skill load_skill_from_dir( pathlib.Path(__file__).parent / skills / code-review-skill ) my_skill_toolset SkillToolset(skills[code_review_skill]) root_agent Agent( nameskills_inject_state_agent, description( An agent that personalizes a code-review skill using session state. ), instruction( You help developers review their code.\n - When a user introduces themselves, call remember_developer_profile to save who they are.\n - When a user asks for a code review, load the code-review-skill and follow its (personalized) instructions exactly. ), tools[ remember_developer_profile, my_skill_toolset, ], )注意这里的指令设计Agent 被明确指示「用户自我介绍时调用remember_developer_profile存档」「用户请求代码审查时加载code-review-skill」。这保证了状态在 Skill 加载之前就已经就位与「先写状态、再加载 Skill」的正确时序完全吻合。Skill 侧一行声明开启注入SKILL.md 的 frontmatter 是注入开关所在--- name: code-review-skill description: Reviews code with feedback tailored to the developers profile in session state. metadata: adk_inject_state: true ---正文使用可选的占位符形式引用状态并用「档案为空则先询问」的逻辑保证优雅降级You are performing a personalized code review. The developers profile (from session state): - Name: {dev_name?} - Primary language: {dev_language?} - Experience level: {dev_level?} If the profile above is empty, first ask the developer to introduce themselves (their name, primary language, and experience level) so the review can be personalized, then stop. Otherwise, follow these steps: 1. Greet the developer by name. 2. Review the code the user provided, focusing on idioms and best practices for their primary language. 3. Calibrate the depth of your feedback to their experience level: keep it foundational for a junior developer, and concise and advanced for a senior developer. 4. End with one concrete, actionable suggestion.这份 Skill 的「个性化」完全来自状态注入同一份模板对 AlexPython / senior与对新人开发者初级 / 某语言会渲染出完全不同的审查指令而 Skill 文件本身无需任何改动。运行示例两种输入回合在示例的父目录下启动adk web然后在同一个会话中按顺序发送以下两轮消息第 1 轮Hi, Im Alex. I mainly write Python and Im a senior engineer.效果Agent 调用remember_developer_profile将档案写入会话状态。第 2 轮Can you review this for me? def add(a, b): return ab效果Agent 加载code-review-skill。因为 Skill 声明了adk_inject_state{dev_name}/{dev_language}/{dev_level}占位符在指令返回时已从状态填充完毕——读取档案不再需要额外的工具调用。占位符语法详解从{key}到{user:key}占位符与会话状态的键一一对应支持的语法在 instructions_utils.py 的替换逻辑中实现语法含义键缺失时的行为{key}必填占位符读取当前会话状态中的key注入失败抛出KeyError{key?}可选占位符读取key替换为空字符串不报错{user:key}读取 user 作用域前缀状态同{key}规则{app:key}读取 app 作用域前缀状态同{key}规则{temp:key}读取 temp 作用域前缀状态同{key}规则此外源码还支持{artifact.file_name}将 Skill/指令中引用的 artifact 内容注入进来artifact 不存在且为可选形式时替换为空串否则抛KeyError。值得注意的底层细节校验规则_is_valid_state_name见 instructions_utils.py只接受合法标识符或user:/app:/temp:前缀加合法标识符不合法的{var}会被原样保留直接返回匹配原文而不是报错或静默删除值类型状态值为None时替换为空字符串其余值经str()转成字符串后注入Frontmatter 类型校验adk_inject_state必须是布尔值否则Frontmatter模型会抛出ValueError(adk_inject_state must be a bool)见 models.py。本示例刻意使用可选形式{dev_name?}等这样在档案尚未写入时加载 Skill 会优雅降级——指令中对应字段留空Skill 转而执行「先请用户自我介绍」的逻辑而不是直接报错中断。源码级原理LoadSkillTool 与 inject_session_state 的调用链adk_inject_state的实现横跨两个模块1. Skill 加载时触发注入SkillToolset内部的LoadSkillTool.run_async见 skill_toolset.py在取到 Skill 的指令后检查 frontmatterinstructions skill.instructions if skill.frontmatter.metadata.get(adk_inject_state): instructions await instructions_utils.inject_session_state( instructions, tool_context, )即LoadSkillTool把 Skill 正文当作模板交给inject_session_state渲染渲染结果作为load_skill的返回值之一instructions字段返回给模型进入对话上下文。2. 统一的模板引擎inject_session_state见 instructions_utils.py与LlmAgent.instruction用的是同一套插值逻辑默认走基于正则的_render_with_regex引擎{[^{}]*}模式逐段异步替换可选use_jinja2True切换到 Jinja2 渲染支持条件与循环等更丰富的模板语法此时会话状态变量可直接按名访问{{ var_name }}artifact 通过{{ artifact(file_name) }}异步加载——注意 Jinja2 是可选依赖需pip install jinja2替换时从invocation_context.session.state读取状态因此注入内容天然与会话隔离不同会话的状态不同同一 Skill 渲染出的指令也不同。这条调用链印证了文档中的关键结论注入发生在加载时load time且只发生一次。渲染完成后的指令已经固化在对话上下文中后续状态变化不会自动刷新。状态新鲜度与最佳实践这是使用adk_inject_state最容易踩坑、也最需要牢记的部分加载时物化状态值在load_skill被调用的那一刻解析并注入一次。如果之后会话状态发生变化已经返回进对话上下文的指令不会自动更新——它不是「活引用」先写状态再加载 Skill务必保证 Skill 所需的会话状态值在模型加载 Skill 之前就已就位。这也是示例中 Agent 指令刻意设计为「先自我介绍存档、后请求审查」的原因动态或高频变化的状态对于在执行过程中持续变化的值优先使用常规的 getter 工具调用或显式重新加载 Skill而不是依赖加载时的一次性注入。adk_inject_state适合的是低频、会话级、个性化上下文用户偏好、身份档案、配置项而不是任务运行中不断变动的临时数据。进阶阅读完整示例代码与 Skill 文件skills_inject_state 示例目录Skill 数据模型与 frontmatter 校验models.py注入触发点LoadSkillToolskill_toolset.py模板引擎inject_session_state与状态名校验instructions_utils.pySkill 官方指南Skill 使用文档 与 Skill Registry 文档【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价