{
  "source_file": "0930",
  "source_platform": "Hashnode",
  "author": "Juan Carlos Olamendy",
  "title_listed": "State and Memory Management in Google ADK: A Practical Tutorial",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://juancolamendy.hashnode.dev/state-and-memory-management-in-google-adk-a-practical-tutorial",
  "publish_date": "2025-10-08",
  "corpus_stage": "",
  "notes": "",
  "id": "db1543f397bd",
  "collected_at": "2026-10-02T14:10:49",
  "title": "State and Memory Management in Google ADK: A Practical Tutorial",
  "body_markdown": "State and Memory Management in Google ADK: A Practical Tutorial\nPublished\nOctober 8, 2025\n•\n7\nmin read\n•\nView as Markdown\nJ\nJuan Carlos Olamendy\nSenior AI Engineer | Building & Telling Stories about AI/ML Systems | Software Engineer\nIntroduction\nBuilding truly intelligent agents requires more than just processing individual requests—agents need to remember context, learn from interactions, and maintain continuity across conversations.\nThis is where Google ADK's state and memory management system becomes essential.\nIn this comprehensive tutorial, we'll explore how to leverage ADK's state management to create context-aware, personalized agents that can maintain information across interactions and provide meaningful, continuous experiences.\nUnderstanding State vs. Conversation History\nBefore diving into implementation, it's crucial to understand the distinction between two types of memory in ADK:\nConversation History\n: The chronological sequence of messages exchanged between user and agent\nState\n: A structured key-value store for persistent data that agents can read from and write to\nThink of conversation history as a transcript, while state is like a notebook where agents jot down important facts, preferences, and contextual information.\nThe Four Scopes of State\nADK's state management system uses prefixes to determine data persistence scope:\n1. Session State (No Prefix)\nData persists only for the current conversation session.\nsession.state[\n\"current_step\"\n] =\n3\nsession.state[\n\"last_query\"\n] =\n\"What's the weather in London?\"\nUse Cases:\nTracking progress in multi-step workflows\nStoring temporary calculations\nMaintaining conversation-specific context\n2. User State (\nuser:\nprefix)\nData persists across all sessions for a specific user.\nsession.state[\n\"user:preferred_language\"\n] =\n\"Spanish\"\nsession.state[\n\"user:timezone\"\n] =\n\"America/New_York\"\nsession.state[\n\"user:name\"\n] =\n\"Sarah\"\nUse Cases:\nPersonal preferences and settings\nUser profile information\nLong-term learning about user behavior\n3. Application State (\napp:\nprefix)\nData shared across all users and sessions.\nsession.state[\n\"app:version\"\n] =\n\"2.1.0\"\nsession.state[\n\"app:feature_flags\"\n] = {\n\"new_ui\"\n:\nTrue\n}\nsession.state[\n\"app:maintenance_mode\"\n] =\nFalse\nUse Cases:\nGlobal configuration settings\nFeature flags\nSystem-wide announcements\n4. Temporary State (\ntemp:\nprefix)\nData that exists only during current execution, not persisted.\nsession.state[\n\"temp:api_response\"\n] = response_data\nsession.state[\n\"temp:intermediate_result\"\n] = calculation\nUse Cases:\nIntermediate processing results\nTemporary caching\nCross-tool data sharing within single execution\nSetting Up Basic State Management\nLet's start with a simple example of creating and managing sessions:\nimport\nasyncio\nfrom\ngoogle.adk.sessions\nimport\nInMemorySessionService\n# Initialize session service\nsession_service = InMemorySessionService()\n# Application configuration\nAPP_NAME =\n\"personal_assistant\"\nUSER_ID =\n\"user_12345\"\nSESSION_ID =\n\"session_67890\"\n# Basic state operations\nasync\ndef\ndemonstrate_basic_state\n():\n# Create or retrieve session\nsession =\nawait\nsession_service.create_session(\n        app_name=APP_NAME,\n        user_id=USER_ID,\n        session_id=SESSION_ID\n    )\n# Reading with default value\nuser_name = session.state.get(\n\"user:name\"\n,\n\"Guest\"\n)\n# Writing to different scopes\nsession.state[\n\"user:name\"\n] =\n\"Alice\"\nsession.state[\n\"last_interaction\"\n] =\n\"greeting\"\nsession.state[\n\"app:total_users\"\n] = session.state.get(\n\"app:total_users\"\n,\n0\n) +\n1\nuser_name = session.state.get(\n\"user:name\"\n,\n\"Guest\"\n)\n    last_interaction = session.state.get(\n\"last_interaction\"\n,\n\"none\"\n)\n    total_users = session.state.get(\n\"app:total_users\"\n,\n0\n)\n    print(\nf\"Hello,\n{user_name}\n!\"\n)\n    print(\nf\"Total app users:\n{total_users}\n\"\n)\n    print(\nf\"Last interaction:\n{last_interaction}\n\"\n)\n# Run the async function\nasyncio.run(demonstrate_basic_state())\nBuilding State-Aware Tools\nTools are where agents interact with state most directly. Here's how to create tools that leverage state management:\nfrom\ngoogle.adk.tools.tool_context\nimport\nToolContext\nfrom\ndatetime\nimport\ndatetime\nfrom\ntyping\nimport\nDict, Any\ndef\nsave_user_preference\n(\npreference_type: str, \n    value: str, \n    tool_context: ToolContext\n) -> Dict[str, Any]:\n\"\"\"Save a user preference with timestamp.\n\n    Args:\n        preference_type: Type of preference (e.g., 'cuisine', 'music_genre')\n        value: The preference value\n        tool_context: Automatically injected by ADK\n\n    Returns:\n        dict: Operation status and details\n    \"\"\"\n# Store preference with user scope\npreference_key =\nf\"user:preference_\n{preference_type}\n\"\ntimestamp_key =\nf\"user:preference_\n{preference_type}\n_updated\"\n# Save the preference and when it was set\ntool_context.state[preference_key] = value\n    tool_context.state[timestamp_key] = datetime.now().isoformat()\nreturn\n{\n\"status\"\n:\n\"success\"\n,\n\"message\"\n:\nf\"Saved\n{preference_type}\npreference:\n{value}\n\"\n,\n\"updated_at\"\n: tool_context.state[timestamp_key]\n    }\nCreating State-Aware Agents\nNow let's build agents that intelligently use state information:\nfrom\ngoogle.adk.agents\nimport\nAgent\nfrom\ngoogle.adk.tools.tool_context\nimport\nToolContext\nfrom\ndatetime\nimport\ndatetime\nfrom\ntyping\nimport\nDict, Any, List\ndef\nsave_user_preference\n(\npreference_type: str, \n    value: str, \n    tool_context: ToolContext\n) -> Dict[str, Any]:\n\"\"\"Save a user preference with timestamp.\n\n    Args:\n        preference_type: Type of preference (e.g., 'cuisine', 'music_genre')\n        value: The preference value\n        tool_context: Automatically injected by ADK\n\n    Returns:\n        dict: Operation status and details\n    \"\"\"\n# Store preference with user scope\npreference_key =\nf\"user:preference_\n{preference_type}\n\"\ntimestamp_key =\nf\"user:preference_\n{preference_type}\n_updated\"\n# Save the preference and when it was set\ntool_context.state[preference_key] = value\n    tool_context.state[timestamp_key] = datetime.now().isoformat()\nreturn\n{\n\"status\"\n:\n\"success\"\n,\n\"message\"\n:\nf\"Saved\n{preference_type}\npreference:\n{value}\n\"\n,\n\"updated_at\"\n: tool_context.state[timestamp_key]\n    }\ndef\nget_user_profile\n(\ntool_context: ToolContext\n) -> Dict[str, Any]:\n\"\"\"Retrieve comprehensive user profile information.\n\n    Args:\n        tool_context: Automatically injected by ADK\n\n    Returns:\n        dict: User profile data including preferences and history\n    \"\"\"\n# Get user name\nuser_name = tool_context.state.get(\n\"user:name\"\n,\n\"Guest\"\n)\n# Collect all user preferences\npreferences = {}\n# Check for common preference types\ncommon_preferences = [\n\"cuisine\"\n,\n\"music_genre\"\n,\n\"favorite_color\"\n,\n\"language\"\n,\n\"outdoor_activity\"\n,\n\"timezone\"\n,\n\"notification_preference\"\n,\n\"theme\"\n,\n\"accessibility\"\n,\n\"reading_genre\"\n]\nfor\npref_type\nin\ncommon_preferences:\n        pref_key =\nf\"user:preference_\n{pref_type}\n\"\nif\npref_key\nin\ntool_context.state:\n            preferences[pref_type] = tool_context.state[pref_key]\n# Get timestamp if available\ntimestamp_key =\nf\"\n{pref_key}\n_updated\"\nif\ntimestamp_key\nin\ntool_context.state:\n                preferences[\nf\"\n{pref_type}\n_updated\"\n] = tool_context.state[timestamp_key]\n# Get conversation history\nlast_interaction = tool_context.state.get(\n\"last_interaction\"\n,\n\"none\"\n)\n    total_interactions = tool_context.state.get(\n\"user:total_interactions\"\n,\n0\n)\nreturn\n{\n\"user_name\"\n: user_name,\n\"preferences\"\n: preferences,\n\"last_interaction\"\n: last_interaction,\n\"total_interactions\"\n: total_interactions,\n\"profile_retrieved_at\"\n: datetime.now().isoformat()\n    }\ndef\ntrack_conversation_flow\n(\nflow_type: str,\n    step: str,\n    data: str,\n    tool_context: ToolContext\n) -> Dict[str, Any]:\n\"\"\"Track multi-step conversation flows for better context.\n\n    Args:\n        flow_type: Type of flow (e.g., 'booking', 'planning', 'troubleshooting')\n        step: Current step in the flow\n        data: Relevant data for this step\n        tool_context: Automatically injected by ADK\n\n    Returns:\n        dict: Flow tracking status and current state\n    \"\"\"\n# Store flow information\nflow_key =\nf\"user:flow_\n{flow_type}\n\"\nstep_key =\nf\"user:flow_\n{flow_type}\n_step\"\ndata_key =\nf\"user:flow_\n{flow_type}\n_data\"\ntimestamp_key =\nf\"user:flow_\n{flow_type}\n_updated\"\ntool_context.state[flow_key] = flow_type\n    tool_context.state[step_key] = step\n    tool_context.state[data_key] = data\n    tool_context.state[timestamp_key] = datetime.now().isoformat()\nreturn\n{\n\"status\"\n:\n\"success\"\n,\n\"message\"\n:\nf\"Tracked\n{flow_type}\nflow:\n{step}\n\"\n,\n\"current_step\"\n: step,\n\"flow_data\"\n: data,\n\"updated_at\"\n: tool_context.state[timestamp_key]\n    }\ndef\nupdate_user_interaction\n(\ninteraction_type: str,\n    details: str,\n    tool_context: ToolContext\n) -> Dict[str, Any]:\n\"\"\"Update user interaction history and preferences.\n\n    Args:\n        interaction_type: Type of interaction (e.g., 'question', 'request', 'feedback')\n        details: Details about the interaction\n        tool_context: Automatically injected by ADK\n\n    Returns:\n        dict: Interaction update status\n    \"\"\"\n# Update interaction count\ncurrent_count = tool_context.state.get(\n\"user:total_interactions\"\n,\n0\n)\n    tool_context.state[\n\"user:total_interactions\"\n] = current_count +\n1\n# Store interaction details\ninteraction_key =\nf\"user:interaction_\n{current_count +\n1\n}\n\"\ntool_context.state[interaction_key] = {\n\"type\"\n: interaction_type,\n\"details\"\n: details,\n\"timestamp\"\n: datetime.now().isoformat()\n    }\n# Update last interaction\ntool_context.state[\n\"last_interaction\"\n] =\nf\"\n{interaction_type}\n:\n{details}\n\"\nreturn\n{\n\"status\"\n:\n\"success\"\n,\n\"message\"\n:\nf\"Updated interaction:\n{interaction_type}\n\"\n,\n\"interaction_count\"\n: current_count +\n1\n,\n\"timestamp\"\n: datetime.now().isoformat()\n    }\n# Tools list\nstate_tools = [\n    save_user_preference, \n    get_user_profile, \n    track_conversation_flow,\n    update_user_interaction\n]\n# Personal assistant with state awareness\nroot_agent = Agent(\n    name=\n\"personal_assistant\"\n,\n    model=\n\"gemini-2.0-flash-exp\"\n,\n    instruction=\n\"\"\"\n    You are a highly personalized assistant that remembers user preferences and context.\n\n    STARTUP BEHAVIOR:\n    - Always check user state at the beginning of each interaction\n    - If user:name exists, greet them by name\n    - If this is a returning user, reference relevant previous preferences\n    - Check for any ongoing conversation flows and offer to continue them\n\n    STATE USAGE GUIDELINES:\n    - Use save_user_preference tool when users express preferences\n    - Use get_user_profile tool to understand user background before making recommendations\n    - Use track_conversation_flow for multi-step processes (booking, planning, troubleshooting)\n    - Use update_user_interaction to track user engagement and build context\n\n    PERSONALIZATION:\n    - Tailor responses based on user:preferences\n    - Reference previous interactions when relevant\n    - Maintain consistency with established user relationships\n    - Learn from user feedback and adjust recommendations accordingly\n\n    MEMORY MANAGEMENT:\n    - Store important decisions and outcomes\n    - Remember user goals and aspirations\n    - Track what works well for each user\n    - Maintain conversation context across sessions\n\n    CONVERSATION FLOW:\n    - For new users, focus on learning their preferences\n    - For returning users, reference their history and preferences\n    - Proactively suggest improvements based on past interactions\n    - Handle multi-step processes with clear progress tracking\n    \"\"\"\n,\n    tools=state_tools,\n    output_key=\n\"last_assistant_response\"\n)\nSee the whole iteration with the agent.\nSee the events in the session.\nAnd the current state of the agent.\nConclusion\nState and memory management in Google ADK enables the creation of truly intelligent, context-aware agents.\nBy leveraging the four scopes of state (session, user, application, and temporary), implementing robust session services, and following best practices, you can build agents that:\nMaintain continuity across conversations\nPersonalize experiences based on user preferences\nTrack complex workflows and processes\nLearn and adapt from user interactions\nScale efficiently in production environments\nThe key to successful state management is thoughtful design of your data model, appropriate use of scoping, and robust error handling.\nStart simple with session-scoped state, then expand to user and application scopes as your agent's sophistication grows.\nRemember that state is not just about storage—it's about creating meaningful, continuous relationships between users and your AI agents.\nPS:\nIf you like this article, share it with others ♻️\nWould help a lot ❤️\nAnd feel free to follow me for more content like this.\n#\nartificial-intelligence\n#\nagentic-ai\n#\nllm\n#\ngoogle-adk\n#\nagents",
  "metadata": {
    "title": "State and Memory Management in Google ADK: A Practical Tutorial",
    "description": "Introduction\nBuilding truly intelligent agents requires more than just processing individual requests—agents need to remember context, learn from interactions, and maintain continuity across conversations.\nThis is where Google ADK's state and memory ...",
    "keywords": null,
    "author": null,
    "og:title": "State and Memory Management in Google ADK: A Practical Tutorial",
    "og:description": "Introduction\nBuilding truly intelligent agents requires more than just processing individual requests—agents need to remember context, learn from interactions, and maintain continuity across conversations.\nThis is where Google ADK's state and memory ...",
    "og:url": "https://juancolamendy.hashnode.dev/state-and-memory-management-in-google-adk-a-practical-tutorial",
    "og:site_name": "Juan C Olamendy",
    "og:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759942527344/e506320d-84d6-4452-b39f-0b42ab5c3ff7.png",
    "og:image:width": "1200",
    "og:image:height": "630",
    "og:type": "article",
    "twitter:card": "summary_large_image",
    "twitter:creator": "https://twitter.com/juancolamendy",
    "twitter:title": "State and Memory Management in Google ADK: A Practical Tutorial",
    "twitter:description": "Introduction\nBuilding truly intelligent agents requires more than just processing individual requests—agents need to remember context, learn from interactions, and maintain continuity across conversations.\nThis is where Google ADK's state and memory ...",
    "twitter:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759942527344/e506320d-84d6-4452-b39f-0b42ab5c3ff7.png",
    "article:published_time": "2025-10-08T16:56:54.082Z",
    "article:author": "https://juancolamendy.hashnode.dev/@juancolamendy"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/db1543f397bd/code/body-000.txt",
      "chars": 96,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-001.txt",
      "chars": 142,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-002.txt",
      "chars": 139,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-003.txt",
      "chars": 107,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-004.txt",
      "chars": 1171,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-005.txt",
      "chars": 1017,
      "language": "text"
    },
    {
      "file": "attachments/db1543f397bd/code/body-006.txt",
      "chars": 6718,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759942527344/e506320d-84d6-4452-b39f-0b42ab5c3ff7.png",
      "bytes": 1189450,
      "reused": true,
      "local_path": "attachments/db1543f397bd/images/000.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759942527344/e506320d-84d6-4452-b39f-0b42ab5c3ff7.png",
      "alt": "State and Memory Management in Google ADK: A Practical Tutorial",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941832322/0d43a0bb-222b-4bf4-8703-8cf4fc1e1166.png",
      "bytes": 317448,
      "reused": true,
      "local_path": "attachments/db1543f397bd/images/002.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941832322/0d43a0bb-222b-4bf4-8703-8cf4fc1e1166.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941940783/c09128e1-f24e-4cc3-be57-bfa2fc7c83d3.png",
      "bytes": 68799,
      "reused": true,
      "local_path": "attachments/db1543f397bd/images/003.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941940783/c09128e1-f24e-4cc3-be57-bfa2fc7c83d3.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941990505/a646cdfe-afcc-41dd-a03b-e2508867784b.png",
      "bytes": 98826,
      "reused": true,
      "local_path": "attachments/db1543f397bd/images/004.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1759941990505/a646cdfe-afcc-41dd-a03b-e2508867784b.png",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://juancolamendy.hashnode.dev/state-and-memory-management-in-google-adk-a-practical-tutorial.md",
      "label": "View as Markdown",
      "type": "a"
    },
    {
      "href": "https://hashnode.com/@juancolamendy",
      "label": "J",
      "type": "a"
    },
    {
      "href": "https://twitter.com/juancolamendy",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://www.linkedin.com/in/juancolamendy/",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/artificial-intelligence",
      "label": "# artificial-intelligence",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/agentic-ai",
      "label": "# agentic-ai",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/llm",
      "label": "# llm",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/google-adk",
      "label": "# google-adk",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/agents",
      "label": "# agents",
      "type": "a"
    }
  ],
  "retry_at": "2026-10-03T08:05:53",
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:50:35Z",
  "source_url": "https://juancolamendy.hashnode.dev/state-and-memory-management-in-google-adk-a-practical-tutorial",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 12733,
  "expected_body_images": 4,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/db1543f397bd/pages/source.html",
  "local_html": "attachments/db1543f397bd/pages/article.html",
  "body_base_path": "attachments/db1543f397bd/pages/",
  "body_markdown_path": "attachments/db1543f397bd/pages/article.md"
}