15
15
from google .adk .events import Event , EventActions
16
16
from google .adk .tools import FunctionTool , ToolContext
17
17
from google .genai .types import Content , Part , FunctionDeclaration
18
-
18
+ from google .adk .models import LlmResponse , LlmRequest
19
+ from google .genai import types
19
20
20
21
21
22
from pydantic import BaseModel , Field
@@ -157,7 +158,7 @@ def on_before_agent(callback_context: CallbackContext):
157
158
"""
158
159
Initialize recipe state if it doesn't exist.
159
160
"""
160
-
161
+ print ( 'recipe state ==>' , callback_context . state . get ( 'recipe' ))
161
162
if "recipe" not in callback_context .state :
162
163
# Initialize with default recipe
163
164
default_recipe = {
@@ -173,55 +174,48 @@ def on_before_agent(callback_context: CallbackContext):
173
174
return None
174
175
175
176
177
+ # --- Define the Callback Function ---
178
+ # modifying the agent's system prompt to incude the current state of recipe
179
+ def before_model_modifier (
180
+ callback_context : CallbackContext , llm_request : LlmRequest
181
+ ) -> Optional [LlmResponse ]:
182
+ """Inspects/modifies the LLM request or skips the call."""
183
+ agent_name = callback_context .agent_name
184
+ print (f"[Callback] Before model call for agent: { agent_name } " )
185
+ if agent_name == "RecipeAgent" :
186
+ recipe_json = "No recipe yet"
187
+ if "recipe" in callback_context .state and callback_context .state ["recipe" ] is not None :
188
+ try :
189
+ recipe_json = json .dumps (callback_context .state ["recipe" ], indent = 2 )
190
+ except Exception as e :
191
+ recipe_json = f"Error serializing recipe: { str (e )} "
192
+ # --- Modification Example ---
193
+ # Add a prefix to the system instruction
194
+ original_instruction = llm_request .config .system_instruction or types .Content (role = "system" , parts = [])
195
+ prefix = f"""You are a helpful assistant for creating recipes.
196
+ This is the current state of the recipe: { recipe_json }
197
+ You can improve the recipe by calling the generate_recipe tool."""
198
+ # Ensure system_instruction is Content and parts list exists
199
+ if not isinstance (original_instruction , types .Content ):
200
+ # Handle case where it might be a string (though config expects Content)
201
+ original_instruction = types .Content (role = "system" , parts = [types .Part (text = str (original_instruction ))])
202
+ if not original_instruction .parts :
203
+ original_instruction .parts .append (types .Part (text = "" )) # Add an empty part if none exist
204
+
205
+ # Modify the text of the first part
206
+ modified_text = prefix + (original_instruction .parts [0 ].text or "" )
207
+ original_instruction .parts [0 ].text = modified_text
208
+ llm_request .config .system_instruction = original_instruction
176
209
177
- shared_state_agent = LlmAgent (
178
- name = "RecipeAgent" ,
179
- model = "gemini-2.5-pro" ,
180
- instruction = f"""You are a helpful recipe assistant.
181
-
182
- When a user asks for a recipe or wants to modify one, you MUST use the generate_recipe tool.
183
210
184
- IMPORTANT RULES:
185
- 1. Always use the generate_recipe tool for any recipe-related requests
186
- 2. When creating a new recipe, provide at least skill_level, ingredients, and instructions
187
- 3. When modifying an existing recipe, include the changes parameter to describe what was modified
188
- 4. Be creative and helpful in generating complete, practical recipes
189
- 5. After using the tool, provide a brief summary of what you created or changed
190
211
191
- Examples of when to use the tool:
192
- - "Create a pasta recipe" → Use tool with skill_level, ingredients, instructions
193
- - "Make it vegetarian" → Use tool with special_preferences="vegetarian" and changes describing the modification
194
- - "Add some herbs" → Use tool with updated ingredients and changes describing the addition
212
+ return None
195
213
196
- Always provide complete, practical recipes that users can actually cook.
197
- """ ,
198
- tools = [generate_recipe ],
199
- before_agent_callback = on_before_agent
200
- )
201
214
202
- async def run_recipe_agent (user_message : str , app_name : str = "recipe_app" ,
203
- user_id : str = "user1" , session_id : str = "session1" ):
204
- """
205
- Run the recipe agent with a user message.
206
-
207
- Args:
208
- user_message: The user's input message
209
- app_name: Application name for the session
210
- user_id: User identifier
211
- session_id: Session identifier
212
-
213
- Returns:
214
- The agent's response and updated session state
215
- """
216
-
217
- # Create session service
218
-
219
- session_service = InMemorySessionService ()
220
- agent = LlmAgent (
215
+ shared_state_agent = LlmAgent (
221
216
name = "RecipeAgent" ,
222
217
model = "gemini-2.5-pro" ,
223
- instruction = f"""You are a helpful recipe assistant.
224
-
218
+ instruction = f"""
225
219
When a user asks for a recipe or wants to modify one, you MUST use the generate_recipe tool.
226
220
227
221
IMPORTANT RULES:
@@ -237,92 +231,9 @@ async def run_recipe_agent(user_message: str, app_name: str = "recipe_app",
237
231
- "Add some herbs" → Use tool with updated ingredients and changes describing the addition
238
232
239
233
Always provide complete, practical recipes that users can actually cook.
240
- USER:{ user_message }
241
234
""" ,
242
235
tools = [generate_recipe ],
243
- before_agent_callback = on_before_agent
244
- )
245
-
246
- # Create the agent
247
-
248
- # Create runner
249
- runner = Runner (
250
- agent = agent ,
251
- app_name = app_name ,
252
- session_service = session_service
253
- )
254
-
255
- # Create or get session
256
-
257
- session = await session_service .get_session (
258
- app_name = app_name ,
259
- user_id = user_id ,
260
- session_id = session_id
261
- )
262
- print ('session already exist with session_id' ,session_id )
263
- if not session :
264
- print ('creating session with session_id' ,session_id )
265
- session = await session_service .create_session (
266
- app_name = app_name ,
267
- user_id = user_id ,
268
- session_id = session_id
236
+ before_agent_callback = on_before_agent ,
237
+ before_model_callback = before_model_modifier
269
238
)
270
239
271
- # Create new session if it doesn't exist
272
- # Create user message content
273
- user_content = Content (parts = [Part (text = user_message )])
274
- print ('user_message==>' ,user_message )
275
- # Run the agent
276
- response_content = None
277
- async for event in runner .run_async (
278
- user_id = user_id ,
279
- session_id = session_id ,
280
- new_message = user_content
281
- ):
282
- print (f"Event emitted: { response_content } " )
283
- if event .is_final_response ():
284
- response_content = event .content
285
- print (f"Agent responded: { response_content } " )
286
-
287
- # Get updated session to check state
288
- updated_session = await session_service .get_session (
289
- app_name = app_name ,
290
- user_id = user_id ,
291
- session_id = session_id
292
- )
293
-
294
- return {
295
- "response" : response_content ,
296
- "recipe_state" : updated_session .state .get ("recipe" ),
297
- "session_state" : updated_session .state
298
- }
299
-
300
-
301
- # Example usage
302
- async def main ():
303
- """
304
- Example usage of the recipe agent.
305
- """
306
-
307
- # Test the agent
308
- print ("=== Recipe Agent Test ===" )
309
-
310
- # First interaction - create a recipe
311
- result1 = await run_recipe_agent ("I want to cook Biryani, create a simple Biryani recipe and use generate_recipe tool for this" ,session_id = '123121' )
312
- print (f"Response 1: { result1 ['response' ]} " )
313
- print (f"Recipe State: { json .dumps (result1 ['recipe_state' ], indent = 2 )} " )
314
-
315
- # # Second interaction - modify the recipe
316
- # result2 = await run_recipe_agent("Make it vegetarian and add some herbs")
317
- # print(f"Response 2: {result2['response']}")
318
- # print(f"Updated Recipe State: {json.dumps(result2['recipe_state'], indent=2)}")
319
-
320
- # # Third interaction - adjust cooking time
321
- # result3 = await run_recipe_agent("Make it a quick 15-minute recipe")
322
- # print(f"Response 3: {result3['response']}")
323
- # print(f"Final Recipe State: {json.dumps(result3['recipe_state'], indent=2)}")
324
-
325
-
326
- if __name__ == "__main__" :
327
- import asyncio
328
- asyncio .run (main ())
0 commit comments