Thanks to visit codestin.com
Credit goes to github.com

Skip to content

after_agent_callback sets Content to None, even if None is returned from callback function #772

@adt5-uiuc

Description

@adt5-uiuc

Describe the bug
Documentation is unclear whether the following is an expected behavior:

In a custom agent that executes an LlmAgent that has an after_agent_callback, if None is returned but changes are made to the callback_context, Content is deleted from the agent's final response. Is this expected behavior? If yes, it should be documented. If not, there is a bug.

According to the documentation, if the provided after_agent_callback returns None, no modification is done to content. However, modifying the state through callback_context yields a different behavior.

Minimal example to reproduce

from dotenv import load_dotenv
from google.adk.sessions import InMemorySessionService
from google.adk.agents.callback_context import CallbackContext
from google.adk.agents.invocation_context import InvocationContext
from google.genai import types
from google.adk.agents import LlmAgent, BaseAgent
from google.adk.events import Event
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from typing import Optional, AsyncGenerator

import pprint
import json

load_dotenv(dotenv_path=".env")


APP_NAME 		= "adk-summit"
USER_ID 		= "user1"
SESSION_ID	= "session001"
validator_model_id = "azure/o_series/o3-mini"


session_service = InMemorySessionService()
initial_state = {"idea" : {}}

session = session_service.create_session(
	app_name=APP_NAME,
	user_id=USER_ID,
	session_id=SESSION_ID,
	state=initial_state
)

def evaluate_decision(
	callback_context: CallbackContext) -> Optional[types.Content] :
	"""
	"""
	print(callback_context.state.get("idea"))
	try :
		response = json.loads(callback_context.state.get("idea"))

	except json.JSONDecodeError :
		pass

	except KeyError :
		pass

	else :
		callback_context.state["idea"] = response["type"]

	print("After mod :::")
	print(callback_context.state.get("idea"))
	return None

class GiftAgent(BaseAgent) :
	main_agent: LlmAgent

	def __init__(self, name: str, main_agent: LlmAgent) :
		"""
		"""
		super().__init__(name=name, main_agent=main_agent)

	async def _run_async_impl(
		self, ctx: InvocationContext) -> AsyncGenerator[Event, None] :
		"""
		"""
		async for event in self.main_agent.run_async(ctx) :
			pprint.pp(event.dict(), indent=2)

			yield event

main_agent = LlmAgent(
	name="main_agent",
	model=LiteLlm(model=validator_model_id),
	sub_agents=[],
	description="""You're a helpful assistant.""",
	instruction="""Come up with a nice gift idea. Return a JSON that contains
	the following properties: type, price_estimate, rarity.
	""",
	input_schema=None,
	output_key="idea",
	after_agent_callback=evaluate_decision,
)

gift_agent = GiftAgent(name="gift_agent", main_agent=main_agent)

def call_agent(runner_arg: Runner) :
	"""
	"""
	current_session = session_service.get_session(app_name=APP_NAME, user_id=USER_ID, session_id=SESSION_ID)
	if not current_session :
		print("Session not found...")
		return

	events = runner_arg.run(
		user_id=USER_ID, session_id=SESSION_ID, new_message=types.Content(
			role="user", parts=[types.Part(text="Execute")]))

	final_response = "No final response captured."

	for event in events :
		if event.is_final_response() and event.content and event.content.parts :
			final_response = event.content.parts[0].text

	final_session = session_service.get_session(app_name=APP_NAME, user_id=USER_ID, session_id=SESSION_ID)

if __name__ == "__main__" :

	runner = Runner(
		agent=gift_agent,
		app_name=APP_NAME,
		session_service=session_service
	)
	call_agent(runner)

Desktop (please complete the following information):

  • OS: Mac OS 15.4.1
  • Python version(python -V): 1.13.2
  • ADK version(pip show google-adk): 0.5.0

Metadata

Metadata

Assignees

Labels

core[Component] This issue is related to the core interface and implementation

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions