{
  "source_file": "0930",
  "source_platform": "Hashnode",
  "author": "Juan Carlos Olamendy",
  "title_listed": "Debug and Inject Data/Session to the Context in ADK",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://juancolamendy.hashnode.dev/debug-and-inject-datasession-to-the-context-in-adk",
  "publish_date": "2026-01-22",
  "corpus_stage": "",
  "notes": "",
  "id": "e88b56545582",
  "collected_at": "2026-10-02T14:10:47",
  "title": "Debug and Inject Data/Session to the Context in ADK",
  "body_markdown": "Debug and Inject Data/Session to the Context in ADK\nPublished\nJanuary 22, 2026\n•\n13\nmin read\n•\nView as Markdown\nJ\nJuan Carlos Olamendy\nSenior AI Engineer | Building & Telling Stories about AI/ML Systems | Software Engineer\nEver stared at your AI agent wondering\nwhy on earth\nit gave that response? You're not alone. Debugging LLM-powered agents feels like shouting into a void—you send a prompt, something mysterious happens, and out comes... chaos.\nHere's the problem: most developers have zero visibility into what actually reaches the model. Session state? Invisible. System instructions? A black box. You're left guessing, tweaking, and burning hours on trial-and-error debugging.\nThe fix is simpler than you think. Google's ADK provides a powerful\nbefore_model_callback\nhook that lets you intercept, inspect, and inject data into every LLM request.\nIn this guide, you'll learn how to:\nPeek inside\nthe full context being sent to your model\nInject dynamic data\nlike timestamps and session state\nBuild a reusable debug utility\nin under 50 lines of Python\nLet's crack open that black box.\nThe Hidden Challenge of AI Agent Development\nDebugging traditional software follows predictable patterns. You set breakpoints, inspect variables, trace execution flows, and identify where things went wrong. The logic is deterministic—given the same inputs, you get the same outputs. AI agents break all these assumptions.\nWhen you build an agent with ADK, multiple layers sit between your code and the LLM. Your instruction gets combined with conversation history, session state, tool definitions, and system-level configurations. The final context that reaches the model might look nothing like what you originally wrote. A missing piece of context or an unexpected value can completely derail your agent's behavior.\nThe real pain manifests in several ways. You might spend hours wondering why your agent doesn't \"remember\" information you thought was in its context. Or you discover that session state you expected to persist simply isn't there. Perhaps the agent ignores temporal context because it has no concept of the current time. These issues compound when you're working with complex multi-turn conversations or stateful workflows.\nTraditional debugging approaches fall short here. Print statements in your application code only show you what you send—not what the LLM actually receives. Logging the response tells you something went wrong but not why. You need a way to intercept and inspect the complete request before it hits the model.\nUnderstanding ADK's Callback Architecture\nGoogle's ADK provides an elegant solution through its callback system. The framework exposes several hook points where you can inject custom logic into the agent execution pipeline. The most powerful of these is the\nbefore_model_callback\n—a function that runs immediately before every LLM request.\nThis callback receives two critical objects. The\nCallbackContext\ncontains metadata about the current execution: agent name, user ID, session information, and the current state dictionary. The\nLlmRequest\nholds the actual request being sent to the model, including the system instruction, conversation history, and configuration parameters.\nThe beauty of this design lies in its flexibility. You can inspect these objects without modifying them, giving you pure visibility into the agent's behavior. Or you can modify them on the fly, injecting additional context, transforming instructions, or augmenting the conversation history. The framework doesn't care—it simply uses whatever you return.\nThis callback pattern enables several powerful use cases. You can build comprehensive debugging utilities that log every request. You can inject dynamic runtime data that the agent needs but can't access otherwise. You can implement sophisticated context management strategies that go beyond ADK's defaults. The possibilities extend as far as your requirements demand.\nBuilding the Core Debug Callback\nThe heart of our solution is a single callback function that handles both debugging and injection. This function intercepts every LLM request, augments it with additional context, and prints detailed information about what's being sent. Let's build it step by step.\nFirst, import the required modules:\nimport\nasyncio\nfrom\ndatetime\nimport\ndatetime\nfrom\ngoogle.genai\nimport\ntypes\nfrom\ngoogle.adk.agents\nimport\nAgent\nfrom\ngoogle.adk.agents.callback_context\nimport\nCallbackContext\nfrom\ngoogle.adk.models\nimport\nLlmRequest\nfrom\ngoogle.adk.runners\nimport\nRunner\nfrom\ngoogle.adk.sessions\nimport\nInMemorySessionService\nThese imports give you access to ADK's core components. The\nAgent\nclass creates your AI agent, while\nRunner\nhandles execution.\nInMemorySessionService\nprovides simple session management for development. The\nCallbackContext\nand\nLlmRequest\ntypes define what your callback receives.\nNow define the callback function signature:\ndef\ndebug_and_inject_context\n(\ncallback_context: CallbackContext,\n    llm_request: LlmRequest\n):\nThis function takes exactly two parameters—no more, no less. ADK calls it automatically before every model invocation. Whatever modifications you make to\nllm_request\npersist into the actual API call. The function can return\nNone\nto continue normal execution or return a response to short-circuit the model call entirely.\nInjecting Dynamic Datetime Information\nOne of the most common issues with LLM agents is temporal awareness. The model has no inherent knowledge of the current date and time. If your agent needs to answer questions about \"today\" or \"this week,\" it's flying blind without explicit context.\nInjecting\ndatetime\ninformation solves this problem elegantly:\n# ===== INJECT DATETIME =====\nnow = datetime.now()\ndatetime_text =\nf\"\"\"\nCurrent Date and Time:\n{now.strftime(\n\"%A, %B %d, %Y at %I:%M:%S %p\"\n)}\n\"\"\"\nThis code captures the current timestamp and formats it in a human-readable way. The format includes the day of the week, full date, and precise time. You place this at the beginning of the system instruction so the model sees it first.\nThe benefits extend beyond simple date questions. Your agent can now make time-sensitive decisions. It can understand relative references like \"yesterday\" or \"next Monday.\" It can appropriately handle requests that depend on business hours or seasonal context. A single injection transforms a temporally ignorant agent into one that understands when it is.\nInjecting Session State Into Context\nSession state represents persistent information about the user or conversation. ADK stores this state and makes it available through the callback context. However, the LLM doesn't automatically see this state—you must explicitly inject it.\nThe injection code walks through the state dictionary and formats it for the model:\n# ===== INJECT SESSION STATE =====\nstate_text =\n\"\\nSession State:\\n\"\nstate_dict = callback_context.state.to_dict()\nif\ncallback_context.state\nelse\n{}\nif\nstate_dict:\nfor\nkey, value\nin\nstate_dict.items():\nif\nnot\nkey.startswith(\n\"_\"\n):\n# Skip internal keys\nstate_text +=\nf\"  -\n{key}\n:\n{value}\n\\n\"\nelse\n:\n    state_text +=\n\"  (empty)\\n\"\nstate_text +=\n\"\\n\"\n+\n\"=\"\n*\n70\n+\n\"\\n\"\nThis code performs several important tasks. First, it safely converts the state object to a dictionary, handling cases where state might be None. Then it iterates through the dictionary, formatting each key-value pair. The underscore prefix check skips internal ADK state that shouldn't influence the model. Finally, it adds a visual separator to clearly delineate injected context from the original instruction.\nWith session state injected, your agent gains powerful personalization capabilities. It can remember user preferences across conversation turns. It can reference information like location, membership level, or previous choices. The model receives this context naturally, as if it were always part of the instruction.\nModifying the System Instruction\nNow you combine the\ndatetime\nand state injections with the original system instruction. This modification happens in place on the\nllm_request\nobject:\n# ===== MODIFY SYSTEM INSTRUCTION =====\noriginal_instruction = llm_request.config.system_instruction\nor\n\"\"\nllm_request.config.system_instruction = (\n    datetime_text + state_text + original_instruction\n)\nThe code preserves any existing system instruction. It prepends the injected context, ensuring the model sees dynamic information first. The order matters—information at the beginning of a prompt typically receives more attention from the model.\nThis approach maintains clean separation between your injection logic and your agent definition. Your agent's instruction remains focused on its core behavior. The callback handles cross-cutting concerns like\ndatetime\nand state. You can enable or disable the callback without touching agent code.\nCreating Comprehensive Debug Output\nThe debugging portion of the callback prints detailed information about every request. This visibility proves invaluable during development and troubleshooting. Let's examine each debug section:\n# ===== DEBUG OUTPUT =====\nprint(\n\"\\n\"\n+\n\"=\"\n*\n70\n)\nprint(\n\"🔍 DEBUG: LLM REQUEST\"\n)\nprint(\n\"=\"\n*\n70\n)\nClear visual separators make debug output easy to spot in your terminal. The emoji adds quick visual identification when scrolling through logs. You'll thank yourself for this formatting when debugging complex interactions.\nNext, print the execution metadata:\nprint(\nf\"\\n📌 Agent:\n{callback_context.agent_name}\n\"\n)\nprint(\nf\"📌 User:\n{callback_context.user_id}\n\"\n)\nprint(\nf\"📌 Session:\n{callback_context.session.id\nif\ncallback_context.session\nelse\n'N/A'\n}\n\"\n)\nThis information helps you track which agent is executing and for whom. In multi-agent systems, knowing the agent name prevents confusion. The session ID lets you correlate debug output with specific conversation instances.\nDisplay the modified system instruction:\nprint(\nf\"\\n📋 System Instruction:\"\n)\nprint(\n\"-\"\n*\n70\n)\n# Show first 500 chars to avoid clutter\ninstruction_preview = llm_request.config.system_instruction[:\n500\n]\nif\nlen(llm_request.config.system_instruction) >\n500\n:\n    instruction_preview +=\n\"...\"\nprint(instruction_preview)\nprint(\n\"-\"\n*\n70\n)\nTruncation keeps output manageable while still showing the most important content. The 500-character limit captures your injected context and the beginning of the original instruction. For full inspection, you can increase this limit or remove truncation entirely.\nShow the current session state:\nprint(\nf\"\\n💾 Session State:\n{callback_context.state.to_dict()}\n\"\n)\nThis quick dump confirms what state exists at execution time. Comparing this with your expected state often reveals the source of bugs. Missing or incorrect state values become immediately obvious.\nFinally, display the conversation history:\nprint(\nf\"\\n💬 Messages (\n{len(llm_request.contents)}\n):\"\n)\nfor\ni, content\nin\nenumerate(llm_request.contents):\n    role_emoji =\n\"👤\"\nif\ncontent.role ==\n\"user\"\nelse\n\"🤖\"\nprint(\nf\"  [\n{i}\n]\n{role_emoji}\n{content.role}\n:\"\n, end=\n\" \"\n)\nif\ncontent.parts:\nfor\npart\nin\ncontent.parts:\nif\npart.text:\n                text = part.text[:\n80\n] +\n\"...\"\nif\nlen(part.text) >\n80\nelse\npart.text\n                print(\nf\"\n{text}\n\"\n)\nelif\npart.function_call:\n                print(\nf\"[Tool:\n{part.function_call.name}\n]\"\n)\nelif\npart.function_response:\n                print(\nf\"[Tool Result:\n{part.function_response.name}\n]\"\n)\nThis section reveals the full conversation context. You see every message in the history, including their roles and content. Tool calls and responses appear clearly labeled. Truncated text previews keep output readable while showing message structure.\nBuilding the Conversation Turn Handler\nWith the callback complete, you need a helper function to execute conversation turns. This function sends a user message and processes the response:\nasync\ndef\nrun_turn\n(\nrunner: Runner, user_id: str, session_id: str, query: str\n):\n\"\"\"\n    Execute a single conversation turn with the agent.\n\n    Args:\n        runner: The Runner instance to execute the query\n        user_id: The user identifier\n        session_id: The session identifier\n        query: The user's query text\n    \"\"\"\nprint(\nf\"\\n\n{\n'─'\n*\n70\n}\n\"\n)\n    print(\nf\"👤 USER:\n{query}\n\"\n)\n    print(\n'─'\n*\n70\n)\n\n    msg = types.Content(role=\n'user'\n, parts=[types.Part(text=query)])\nasync\nfor\nevent\nin\nrunner.run_async(\n        user_id=user_id,\n        session_id=session_id,\n        new_message=msg\n    ):\nif\nevent.is_final_response():\n            response_text = event.content.parts[\n0\n].text\nif\nevent.content\nand\nevent.content.parts\nelse\n\"No response\"\nprint(\nf\"\\n🤖 AGENT:\n{response_text}\n\\n\"\n)\nThe function creates a Content object with the user's message. It uses\nrun_async\nto execute the conversation turn asynchronously. The async iterator yields events as the agent processes the request. Checking\nis_final_response()\nfilters for the actual model output.\nThis pattern handles streaming responses gracefully. ADK emits multiple events during execution—tool calls, intermediate steps, and the final response. By filtering for final responses, you capture just the output you want to display.\nWiring Everything Together\nThe main function assembles all components into a working application. It creates the agent, configures the runner, sets up initial session state, and runs an interactive loop:\nasync\ndef\nmain\n():\n\"\"\"\n    Simple example demonstrating context debugging.\n    \"\"\"\nprint(\n\"\\n\"\n+\n\"=\"\n*\n70\n)\n    print(\n\"🚀 SIMPLE ADK CONTEXT DEBUGGER\"\n)\n    print(\n\"=\"\n*\n70\n)\n    print(\n\"This example shows how to debug the LLM context.\"\n)\n    print(\n\"=\"\n*\n70\n+\n\"\\n\"\n)\n# Create agent with debug callback\nagent = Agent(\n        name=\n\"debug_agent\"\n,\n        model=\n\"gemini-2.0-flash-exp\"\n,\n        instruction=\n\"You are a helpful assistant. Use the information provided above to answer questions.\"\n,\n        before_model_callback=debug_and_inject_context\n    )\n# Create runner with in-memory sessions\nrunner = Runner(\n        app_name=\n\"simple_debug_app\"\n,\n        agent=agent,\n        session_service=InMemorySessionService()\n    )\n    user_id =\n\"user123\"\nsession_id =\n\"session456\"\n# Create session with some initial state\nawait\nrunner.session_service.create_session(\n        app_name=\n\"simple_debug_app\"\n,\n        user_id=user_id,\n        session_id=session_id,\n        state={\n\"location\"\n:\n\"San Francisco\"\n,\n\"membership_level\"\n:\n\"premium\"\n}\n    )\n# Interactive loop\nprint(\n\"Type 'exit' to quit\\n\"\n)\nwhile\nTrue\n:\n        query = input(\n\"👤 YOU: \"\n).strip()\nif\nquery.lower() ==\n'exit'\n:\nbreak\nif\nquery:\n# Only process non-empty input\nawait\nrun_turn(runner, user_id, session_id, query)\nif\n__name__ ==\n\"__main__\"\n:\n    asyncio.run(main())\nThe\nbefore_model_callback\nparameter accepts your function directly. ADK automatically invokes it at the right point in the execution pipeline. The instruction references \"information provided above\" because your callback prepends context.\nInMemorySessionService\nprovides lightweight session storage perfect for development. For production, you'd swap this for a persistent implementation. The app name creates a namespace for your sessions.\nInitialize a session with starting state. Pre-populating state demonstrates how injected values appear to the model. The location and membership level represent typical personalization data. Your callback will inject these into every request automatically.\nThe loop accepts user input continuously until they type \"exit.\" Empty inputs get skipped to prevent unnecessary API calls. The\nasyncio.run\n()\ncall bootstraps the async event loop.\nBest Practices for Context Management\nEffective context management requires thoughtful design. These practices help you build maintainable and reliable agents.\nKeep Injected Context Concise\n: Every character you inject consumes model context window. Focus on information the model actually needs to perform its task. Remove redundant or rarely-used state values from injection.\nUse Clear Separators\n: Visual separators help the model understand context structure. The example uses equals signs and dashes to delineate sections. Consistent formatting reduces confusion and improves response quality.\nOrder Context Strategically\n: Place the most important information early in the context. Models often attend more strongly to content near the beginning. Put dynamic, request-specific data before static instructions.\nDocument Your Injections\n: Future maintainers need to understand what gets injected. Comment your callback code explaining each injection's purpose. Keep a README describing the full context structure.\nTest With and Without Injections\n: Verify that your agent works correctly both ways. Disable injections temporarily to test baseline behavior. Compare responses to ensure injections improve rather than confuse.\nConclusion\nDebugging AI agents doesn't have to feel like shouting into a void. Google's ADK provides powerful hooks that let you see exactly what reaches your model and inject the dynamic context your agent needs. The\nbefore_model_callback\npattern offers both visibility and control in a clean, maintainable way.\nYou've learned how to build a comprehensive debug utility from scratch. The callback injects datetime information so your agent understands temporal context. It injects session state so the model can personalize its responses. It prints detailed debug information so you always know what's happening.\nTake this code and adapt it to your needs. Add new injection types for your specific use cases. Implement the advanced patterns for production deployments. Build the observability tooling that lets you understand and improve your agents over time.\nThe black box is open. Now go build something amazing.\nComplete Source Code\nFor reference, here's the complete implementation:\n\"\"\"\nSimple ADK Context Debugger\n\nA minimal example showing how to debug and inspect the LLM context\nwith datetime injection and session state visibility.\n\"\"\"\nimport\nasyncio\nfrom\ndatetime\nimport\ndatetime\nfrom\ngoogle.genai\nimport\ntypes\nfrom\ngoogle.adk.agents\nimport\nAgent\nfrom\ngoogle.adk.agents.callback_context\nimport\nCallbackContext\nfrom\ngoogle.adk.models\nimport\nLlmRequest\nfrom\ngoogle.adk.runners\nimport\nRunner\nfrom\ngoogle.adk.sessions\nimport\nInMemorySessionService\ndef\ndebug_and_inject_context\n(\ncallback_context: CallbackContext,\n    llm_request: LlmRequest\n):\n\"\"\"\n    Single callback that:\n    1. Injects current datetime into system instruction\n    2. Injects session state into system instruction\n    3. Prints debug information about the request\n    \"\"\"\n# ===== INJECT DATETIME =====\nnow = datetime.now()\n    datetime_text =\nf\"\"\"\nCurrent Date and Time:\n{now.strftime(\n\"%A, %B %d, %Y at %I:%M:%S %p\"\n)}\n\"\"\"\n# ===== INJECT SESSION STATE =====\nstate_text =\n\"\\nSession State:\\n\"\nstate_dict = callback_context.state.to_dict()\nif\ncallback_context.state\nelse\n{}\nif\nstate_dict:\nfor\nkey, value\nin\nstate_dict.items():\nif\nnot\nkey.startswith(\n\"_\"\n):\n# Skip internal keys\nstate_text +=\nf\"  -\n{key}\n:\n{value}\n\\n\"\nelse\n:\n        state_text +=\n\"  (empty)\\n\"\nstate_text +=\n\"\\n\"\n+\n\"=\"\n*\n70\n+\n\"\\n\"\n# ===== MODIFY SYSTEM INSTRUCTION =====\noriginal_instruction = llm_request.config.system_instruction\nor\n\"\"\nllm_request.config.system_instruction = (\n        datetime_text + state_text + original_instruction\n    )\n# ===== DEBUG OUTPUT =====\nprint(\n\"\\n\"\n+\n\"=\"\n*\n70\n)\n    print(\n\"🔍 DEBUG: LLM REQUEST\"\n)\n    print(\n\"=\"\n*\n70\n)\n\n    print(\nf\"\\n📌 Agent:\n{callback_context.agent_name}\n\"\n)\n    print(\nf\"📌 User:\n{callback_context.user_id}\n\"\n)\n    print(\nf\"📌 Session:\n{callback_context.session.id\nif\ncallback_context.session\nelse\n'N/A'\n}\n\"\n)\n\n    print(\nf\"\\n📋 System Instruction:\"\n)\n    print(\n\"-\"\n*\n70\n)\n    instruction_preview = llm_request.config.system_instruction[:\n500\n]\nif\nlen(llm_request.config.system_instruction) >\n500\n:\n        instruction_preview +=\n\"...\"\nprint(instruction_preview)\n    print(\n\"-\"\n*\n70\n)\n\n    print(\nf\"\\n💾 Session State:\n{callback_context.state.to_dict()}\n\"\n)\n\n    print(\nf\"\\n💬 Messages (\n{len(llm_request.contents)}\n):\"\n)\nfor\ni, content\nin\nenumerate(llm_request.contents):\n        role_emoji =\n\"👤\"\nif\ncontent.role ==\n\"user\"\nelse\n\"🤖\"\nprint(\nf\"  [\n{i}\n]\n{role_emoji}\n{content.role}\n:\"\n, end=\n\" \"\n)\nif\ncontent.parts:\nfor\npart\nin\ncontent.parts:\nif\npart.text:\n                    text = part.text[:\n80\n] +\n\"...\"\nif\nlen(part.text) >\n80\nelse\npart.text\n                    print(\nf\"\n{text}\n\"\n)\nelif\npart.function_call:\n                    print(\nf\"[Tool:\n{part.function_call.name}\n]\"\n)\nelif\npart.function_response:\n                    print(\nf\"[Tool Result:\n{part.function_response.name}\n]\"\n)\n\n    print(\n\"\\n\"\n+\n\"=\"\n*\n70\n+\n\"\\n\"\n)\nreturn\nNone\nasync\ndef\nrun_turn\n(\nrunner: Runner, user_id: str, session_id: str, query: str\n):\n\"\"\"\n    Execute a single conversation turn with the agent.\n    \"\"\"\nprint(\nf\"\\n\n{\n'─'\n*\n70\n}\n\"\n)\n    print(\nf\"👤 USER:\n{query}\n\"\n)\n    print(\n'─'\n*\n70\n)\n\n    msg = types.Content(role=\n'user'\n, parts=[types.Part(text=query)])\nasync\nfor\nevent\nin\nrunner.run_async(\n        user_id=user_id,\n        session_id=session_id,\n        new_message=msg\n    ):\nif\nevent.is_final_response():\n            response_text = event.content.parts[\n0\n].text\nif\nevent.content\nand\nevent.content.parts\nelse\n\"No response\"\nprint(\nf\"\\n🤖 AGENT:\n{response_text}\n\\n\"\n)\nasync\ndef\nmain\n():\n\"\"\"\n    Simple example demonstrating context debugging.\n    \"\"\"\nprint(\n\"\\n\"\n+\n\"=\"\n*\n70\n)\n    print(\n\"🚀 SIMPLE ADK CONTEXT DEBUGGER\"\n)\n    print(\n\"=\"\n*\n70\n)\n    print(\n\"This example shows how to debug the LLM context.\"\n)\n    print(\n\"=\"\n*\n70\n+\n\"\\n\"\n)\n\n    agent = Agent(\n        name=\n\"debug_agent\"\n,\n        model=\n\"gemini-2.0-flash-exp\"\n,\n        instruction=\n\"You are a helpful assistant. Use the information provided above to answer questions.\"\n,\n        before_model_callback=debug_and_inject_context\n    )\n\n    runner = Runner(\n        app_name=\n\"simple_debug_app\"\n,\n        agent=agent,\n        session_service=InMemorySessionService()\n    )\n\n    user_id =\n\"user123\"\nsession_id =\n\"session456\"\nawait\nrunner.session_service.create_session(\n        app_name=\n\"simple_debug_app\"\n,\n        user_id=user_id,\n        session_id=session_id,\n        state={\n\"location\"\n:\n\"San Francisco\"\n,\n\"membership_level\"\n:\n\"premium\"\n}\n    )\n\n    print(\n\"Type 'exit' to quit\\n\"\n)\nwhile\nTrue\n:\n        query = input(\n\"👤 YOU: \"\n).strip()\nif\nquery.lower() ==\n'exit'\n:\nbreak\nif\nquery:\nawait\nrun_turn(runner, user_id, session_id, query)\nif\n__name__ ==\n\"__main__\"\n:\n    asyncio.run(main())\n#\nagentic-ai\n#\ngoogle-adk\n#\nlarge-language-models\n#\nartificial-intelligence",
  "metadata": {
    "title": "Debug and Inject Data/Session to the Context in ADK",
    "description": "Ever stared at your AI agent wondering why on earth it gave that response? You're not alone. Debugging LLM-powered agents feels like shouting into a void—you send a prompt, something mysterious happens, and out comes... chaos.\nHere's the problem: mos...",
    "keywords": null,
    "author": null,
    "og:title": "Debug and Inject Data/Session to the Context in ADK",
    "og:description": "Ever stared at your AI agent wondering why on earth it gave that response? You're not alone. Debugging LLM-powered agents feels like shouting into a void—you send a prompt, something mysterious happens, and out comes... chaos.\nHere's the problem: mos...",
    "og:url": "https://juancolamendy.hashnode.dev/debug-and-inject-datasession-to-the-context-in-adk",
    "og:site_name": "Juan C Olamendy",
    "og:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1769110195616/8544b78c-2eef-41bb-a153-85061913194b.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": "Debug and Inject Data/Session to the Context in ADK",
    "twitter:description": "Ever stared at your AI agent wondering why on earth it gave that response? You're not alone. Debugging LLM-powered agents feels like shouting into a void—you send a prompt, something mysterious happens, and out comes... chaos.\nHere's the problem: mos...",
    "twitter:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1769110195616/8544b78c-2eef-41bb-a153-85061913194b.png",
    "article:published_time": "2026-01-22T19:31:39.955Z",
    "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/e88b56545582/code/body-000.txt",
      "chars": 310,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-001.txt",
      "chars": 100,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-002.txt",
      "chars": 146,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-003.txt",
      "chars": 388,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-004.txt",
      "chars": 205,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-005.txt",
      "chars": 92,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-006.txt",
      "chars": 186,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-007.txt",
      "chars": 285,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-008.txt",
      "chars": 64,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-009.txt",
      "chars": 631,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-010.txt",
      "chars": 812,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-011.txt",
      "chars": 1427,
      "language": "text"
    },
    {
      "file": "attachments/e88b56545582/code/body-012.txt",
      "chars": 4849,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1769110195616/8544b78c-2eef-41bb-a153-85061913194b.png",
      "bytes": 1492548,
      "reused": true,
      "local_path": "attachments/e88b56545582/images/000.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1769110195616/8544b78c-2eef-41bb-a153-85061913194b.png",
      "alt": "Debug and Inject Data/Session to the Context in ADK",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://juancolamendy.hashnode.dev/debug-and-inject-datasession-to-the-context-in-adk.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": "http://asyncio.run/",
      "label": "asyncio.run",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/agentic-ai",
      "label": "# agentic-ai",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/google-adk",
      "label": "# google-adk",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/large-language-models",
      "label": "# large-language-models",
      "type": "a"
    },
    {
      "href": "https://juancolamendy.hashnode.dev/tag/artificial-intelligence",
      "label": "# artificial-intelligence",
      "type": "a"
    }
  ],
  "retry_at": "2026-10-03T08:05:32",
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:50:33Z",
  "source_url": "https://juancolamendy.hashnode.dev/debug-and-inject-datasession-to-the-context-in-adk",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 22462,
  "expected_body_images": 1,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/e88b56545582/pages/source.html",
  "local_html": "attachments/e88b56545582/pages/article.html",
  "body_base_path": "attachments/e88b56545582/pages/",
  "body_markdown_path": "attachments/e88b56545582/pages/article.md"
}