State:ADK 中基于作用域前缀的会话状态读写机制

发布时间:2026/9/13 15:17:47

State:ADK 中基于作用域前缀的会话状态读写机制 StateADK 中基于作用域前缀的会话状态读写机制【免费下载链接】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-pythonState是 ADKAgent Development KitPython 版中会话状态的增量感知视图delta-aware viewAgent、工具和回调并不直接写入Session.state这个普通字典而是统一通过State对象ctx.state即ToolContext.state写入。每一次写入都会同步记录两份内容——一份更新会话的当前值供下一行代码立即读取另一份进入随事件携带的delta增量由会话服务在追加事件时持久化。键的前缀app:、user:、temp:或无前缀决定了这个值能传播多远、是否会被存储这是 ADK 实现跨会话记忆用户偏好、应用级配置与同一次调用内临时数据传递的核心机制。读完本文你将掌握四类状态作用域的语义与取舍、delta 从写入到落库的完整链路、在工具/指令模板/Agent 配置中读写状态的具体姿势以及最容易踩的坑与后端差异。State 是什么先理解它和 Session、Context 的关系Session见 session.py本质上是一个 pydantic 模型其中携带一个普通的state: dict[str, Any]字段默认空字典以及按时间排序的events事件列表。它是存储快照——里面保存的是已经持久化的值。但运行在调用invocation内部的代码不直接写这个字典。它写的是一个State对象通过ctx.state拿到Context正是google.adk.tools以ToolContext名义导出的同一个类。State类定义在 state.py 中构造时接收三样东西value当前值字典即快照delta尚未提交的增量字典schema可选的 pydantic 模型用于校验状态键值。State的三个前缀是类常量State.APP_PREFIX app:、State.USER_PREFIX user:、State.TEMP_PREFIX temp:。为什么要有前缀如果没有前缀每个值都只属于一场对话Agent 永远无法记住昨天聊天里的偏好。app:和user:把作用域扩大到单场会话之外temp:则把作用域收窄到当前调用之内草稿值根本不进入存储。前缀的作用域语义总结如下键的形式存储位置是否持久化可见范围draft无前缀会话记录是仅本会话app:model_tierapp_name是该应用的所有会话、所有用户user:display_name(app_name, user_id)是该用户在此应用内的所有会话temp:token_count不存储否仅当前调用两个共享作用域都容易被误读务必注意app:是跨用户共享的适合放配置类信息绝不用于存放个人数据user:以应用名 用户 ID 共同作为键因此同一个人运行另一个应用时看到的是空的 user 作用域。快速上手一个不依赖模型和凭证的完整示例下面这个示例来自 sessions/state 指南它不需要任何模型、不需要任何凭证写入四种作用域各一个键重新加载会话再为同一用户开第二个会话观察什么活了下来。import asyncio from google.adk.events import Event from google.adk.events import EventActions from google.adk.sessions import InMemorySessionService async def main() - None: session_service InMemorySessionService() session await session_service.create_session( app_namenotes, user_idada, session_idmonday, state{app:model_tier: pro, user:display_name: Ada}, ) # State becomes durable only when it rides on an event. await session_service.append_event( session, Event( authornote_agent, actionsEventActions( state_delta{ draft: buy milk, # this session only user:display_name: Ada L., # every session of this user app:model_tier: flash, # every session of this app temp:token_count: 128, # never stored } ), ), ) monday await session_service.get_session( app_namenotes, user_idada, session_idmonday ) print(monday.state) tuesday await session_service.create_session( app_namenotes, user_idada, session_idtuesday ) print(tuesday.state) asyncio.run(main())输出揭示了哪些值存活、以及键读取回来时前缀保持原样{draft: buy milk, app:model_tier: flash, user:display_name: Ada L.} {app:model_tier: flash, user:display_name: Ada L.}temp:token_count两行里都没有。新会话tuesday继承了 app 和 user 作用域的值但没有继承draft。注意create_session时种的app:model_tier: pro也被事件 delta 里的flash覆盖了——因为append_event走的是同一条按桶拆分并写入对应存储的路径。一次写入如何变得持久delta 的五步生命周期从ctx.state[k] v到值真正落库共经历五个步骤ctx.state[k] v同时写入会话的值字典和event.actions.state_delta见 state.py 中__setitem__的实现self._value[key] value; self._delta[key] value。Agent 产出该事件Runner 把它交给会话服务的append_event。append_event先把temp:前缀的键复制到内存中的会话状态上这样同一次调用里后面的 Agent 也能读到随后把这些键从 delta 中剔除见 base_session_service.py 的_apply_temp_state与_trim_temp_delta_state。剩下的内容按 app / user / session 三个桶拆分去掉前缀后各自写入对应的存储区。拆分的核心实现是 _session_util.py 的extract_state_deltaapp:前缀键去掉前缀进deltas[app]user:前缀键去掉前缀进deltas[user]非temp:前缀的键进deltas[session]。get_session把三个存储合并回一个字典并重新加上前缀。以InMemorySessionService为例它的内部存储是app_state应用名 → 键值与user_state应用名 → 用户 ID → 键值合并逻辑在 _merge_state合并时补回State.APP_PREFIX/State.USER_PREFIX。create_session(state...)传入的初始字典也走同样的拆分路径_create_session_impl中同样调用extract_state_delta见 in_memory_session_service.pyRunner.run_async(state_delta...)则把 delta 挂到开启调用的用户消息事件上。因此三条路径殊途同归会话内写入、会话创建、调用启动最终都汇入同一条拆桶-落库-合并的管道。值得一提的细节对于需要落库的会话服务写库前通常还会用extract_json_safe_state_delta做一次 JSON 安全化——把 datetime、pydantic 模型等富类型忠实序列化只有序列化失败如遇到可调用对象才用字符串替换并打警告日志避免整个写入静默失败见 _session_util.py 的make_json_safe_state。从 Agent 内部写状态工具与 output_key在工具内部直接通过tool_context.state写入前缀同样生效from google.adk.agents import LlmAgent from google.adk.tools import ToolContext def remember_home_city(city: str, tool_context: ToolContext) - dict[str, str]: Records the users home city so later sessions can reuse it. tool_context.state[user:home_city] city tool_context.state[temp:lookup_count] ( tool_context.state.get(temp:lookup_count, 0) 1 ) return {status: ok, city: city} travel_agent LlmAgent( modelgemini-2.5-flash, nametravel_agent, instruction( Help the user plan trips. Their home city is {user:home_city?}. ), tools[remember_home_city], output_keylast_plan, )output_key也会把 Agent 的最终文本写进同一个 delta——因为LlmAgent._save_output_to_state见 llm_agent.py在事件最终响应时执行event.actions.state_delta[self.output_key] result。所以output_key同样接受前缀output_keytemp:draft可以把结果交给SequentialAgent中的下一个 Agent 而永不落库。在指令模板中读取状态{key}与{key?}instruction是一个模板。请求到达模型之前模板里的每个{key}都会被替换为对应键的当前值因此上面的travel_agent实际发给模型的是 Their home city is Paris. 而不是花括号本身。前缀是键的一部分所以模板必须写{user:home_city?}而不是{home_city?}。temp:键同样能在设置它的那次调用的剩余时间内解析。?决定未设置的键如何处理{user:home_city}键尚未写入时抛出KeyError{user:home_city?}渲染为空字符串。所以凡是 Agent 在没有该键时也能运行的场景一律加上?。不是合法状态名的花括号会被原样保留这保证了提示词中的 JSON 示例不会被破坏。唯一的例外是static_instruction它原样发送给模型提供方以便缓存不做任何替换。State 不是普通字典支持与不支持的操作State实现了__getitem__、__setitem__、__contains__、get、setdefault、update和to_dict但没有keys、items、pop、迭代或del。需要枚举时请用state.to_dict()内部是 value 与 delta 合并后的字典见 state.py。另外需要注意把某个键设为None只是存储了None键仍然存在k in state依然为真——State 不支持真正删除一个键。常见错误清单直接给Session.state赋值那个字典只是快照。赋值在当前进程内可见但因为没有事件携带 delta下一次get_session时就会消失。指望temp:活过本次调用它只在当前运行的剩余时间内可读之后的所有调用都读不到。在create_session(state...)里种temp:键这些键会被直接丢弃连返回的 session 上都看不到。读取时丢掉前缀存储的键是home_city但所有读取都要走state[user:home_city]。把State当 dict 用见上节支持/不支持的操作清单。试图删除键见上节None语义说明。限制与后端差异后端行为不一致InMemorySessionService、DatabaseSessionService和 SQLite 服务会把带前缀的键拆到独立的 app / user 存储中Firestore 与 Redis 的会话服务实现同样调用extract_state_delta见 firestore_session_service.py 与 _redis_session_service.py。而VertexAiSessionService把 delta 原样转发给 Agent Engine API 而不拆分其get_user_state直接抛NotImplementedError见 base_session_service.py 的默认实现及说明——不要在那里假设跨会话共享可用。声明的state_schema不覆盖带前缀的键任何包含:的键都会跳过校验见 state.py 的_validate_state_entryif : in key: return所以app:或user:键上的拼写错误永远不会被捕获。没有原子的读-改-写两个并发调用读同一键再写回彼此看不到对方最后追加的事件获胜last-write-wins。延伸阅读Event 与 NodeInfo携带 state delta 的事件本身Function Node如何从ctx.state解析节点参数并通过它写回会话服务实现in_memory_session_service.py、database_session_service.py、vertex_ai_session_service.py会话与事件模型session.py、events/event。【免费下载链接】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),仅供参考
延伸阅读

更多相关文章

2026/9/13 15:17:47

Maven从零到实战:下载安装、环境配置与IDEA集成全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 15:17:47

AI学术写作助手千笔:技术架构与核心功能解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 16:02:50

RAG系统安全基准测试:核心挑战与实战方案

1. RAG安全基准测试的必要性与核心挑战 检索增强生成(Retrieval-Augmented Generation,简称RAG)系统已成为当前AI应用的主流架构之一。但我在实际企业级部署中发现,许多团队在系统上线前往往忽视安全性和性能的量化评估&#xff0…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码