|
28 | 28 |
|
29 | 29 | if TYPE_CHECKING: |
30 | 30 | from ...agents.invocation_context import InvocationContext |
| 31 | + from ...agents.llm_agent import LlmAgent |
31 | 32 | from ...models.llm_request import LlmRequest |
32 | 33 |
|
33 | 34 |
|
34 | | -class _InstructionsLlmRequestProcessor(BaseLlmRequestProcessor): |
35 | | - """Handles instructions and global instructions for LLM flow.""" |
| 35 | +async def _process_agent_instruction( |
| 36 | + agent: 'LlmAgent', |
| 37 | + invocation_context: 'InvocationContext', |
| 38 | +) -> str: |
| 39 | + """Process agent instruction with state injection. |
| 40 | +
|
| 41 | + Resolves the agent's instruction and injects session state variables |
| 42 | + unless bypass_state_injection is set. |
| 43 | +
|
| 44 | + Args: |
| 45 | + agent: The agent with instruction to process. |
| 46 | + invocation_context: The invocation context. |
| 47 | +
|
| 48 | + Returns: |
| 49 | + The processed instruction text with state variables injected. |
| 50 | + """ |
| 51 | + raw_si, bypass_state_injection = await agent.canonical_instruction( |
| 52 | + ReadonlyContext(invocation_context) |
| 53 | + ) |
| 54 | + si = raw_si |
| 55 | + if not bypass_state_injection: |
| 56 | + si = await instructions_utils.inject_session_state( |
| 57 | + raw_si, ReadonlyContext(invocation_context) |
| 58 | + ) |
| 59 | + return si |
| 60 | + |
| 61 | + |
| 62 | +async def _build_instructions( |
| 63 | + invocation_context: 'InvocationContext', |
| 64 | + llm_request: 'LlmRequest', |
| 65 | +) -> None: |
| 66 | + """Build and append instructions to the LLM request. |
| 67 | +
|
| 68 | + Handles global instructions (deprecated), static_instruction, and |
| 69 | + dynamic instruction based on agent configuration. |
36 | 70 |
|
37 | | - async def _process_agent_instruction( |
38 | | - self, agent, invocation_context: InvocationContext |
39 | | - ) -> str: |
40 | | - """Process agent instruction with state injection. |
| 71 | + Args: |
| 72 | + invocation_context: The invocation context. |
| 73 | + llm_request: The LlmRequest to populate with instructions. |
| 74 | + """ |
| 75 | + from ...agents.base_agent import BaseAgent |
| 76 | + from ...agents.llm_agent import LlmAgent |
41 | 77 |
|
42 | | - Args: |
43 | | - agent: The agent with instruction to process |
44 | | - invocation_context: The invocation context |
| 78 | + agent = invocation_context.agent |
45 | 79 |
|
46 | | - Returns: |
47 | | - The processed instruction text |
48 | | - """ |
49 | | - raw_si, bypass_state_injection = await agent.canonical_instruction( |
50 | | - ReadonlyContext(invocation_context) |
| 80 | + root_agent: BaseAgent = agent.root_agent |
| 81 | + |
| 82 | + # Handle global instructions (DEPRECATED - use GlobalInstructionPlugin instead) |
| 83 | + # TODO: Remove this code block when global_instruction field is removed |
| 84 | + if isinstance(root_agent, LlmAgent) and root_agent.global_instruction: |
| 85 | + raw_si, bypass_state_injection = ( |
| 86 | + await root_agent.canonical_global_instruction( |
| 87 | + ReadonlyContext(invocation_context) |
| 88 | + ) |
51 | 89 | ) |
52 | 90 | si = raw_si |
53 | 91 | if not bypass_state_injection: |
54 | 92 | si = await instructions_utils.inject_session_state( |
55 | 93 | raw_si, ReadonlyContext(invocation_context) |
56 | 94 | ) |
57 | | - return si |
| 95 | + llm_request.append_instructions([si]) |
| 96 | + |
| 97 | + # Handle static_instruction - add via append_instructions |
| 98 | + if agent.static_instruction: |
| 99 | + from google.genai import _transformers |
| 100 | + |
| 101 | + # Convert ContentUnion to Content using genai transformer |
| 102 | + static_content = _transformers.t_content(agent.static_instruction) |
| 103 | + llm_request.append_instructions(static_content) |
| 104 | + |
| 105 | + # Handle instruction based on whether static_instruction exists |
| 106 | + if agent.instruction and not agent.static_instruction: |
| 107 | + # Only add to system instructions if no static instruction exists |
| 108 | + si = await _process_agent_instruction(agent, invocation_context) |
| 109 | + llm_request.append_instructions([si]) |
| 110 | + elif agent.instruction and agent.static_instruction: |
| 111 | + # Static instruction exists, so add dynamic instruction to content |
| 112 | + from google.genai import types |
| 113 | + |
| 114 | + si = await _process_agent_instruction(agent, invocation_context) |
| 115 | + # Create user content for dynamic instruction |
| 116 | + dynamic_content = types.Content(role='user', parts=[types.Part(text=si)]) |
| 117 | + llm_request.contents.append(dynamic_content) |
| 118 | + |
| 119 | + |
| 120 | +class _InstructionsLlmRequestProcessor(BaseLlmRequestProcessor): |
| 121 | + """Handles instructions and global instructions for LLM flow.""" |
58 | 122 |
|
59 | 123 | @override |
60 | 124 | async def run_async( |
61 | 125 | self, invocation_context: InvocationContext, llm_request: LlmRequest |
62 | 126 | ) -> AsyncGenerator[Event, None]: |
63 | | - from ...agents.base_agent import BaseAgent |
64 | | - from ...agents.llm_agent import LlmAgent |
65 | | - |
66 | | - agent = invocation_context.agent |
67 | | - |
68 | | - root_agent: BaseAgent = agent.root_agent |
69 | | - |
70 | | - # Handle global instructions (DEPRECATED - use GlobalInstructionPlugin instead) |
71 | | - # TODO: Remove this code block when global_instruction field is removed |
72 | | - if isinstance(root_agent, LlmAgent) and root_agent.global_instruction: |
73 | | - raw_si, bypass_state_injection = ( |
74 | | - await root_agent.canonical_global_instruction( |
75 | | - ReadonlyContext(invocation_context) |
76 | | - ) |
77 | | - ) |
78 | | - si = raw_si |
79 | | - if not bypass_state_injection: |
80 | | - si = await instructions_utils.inject_session_state( |
81 | | - raw_si, ReadonlyContext(invocation_context) |
82 | | - ) |
83 | | - llm_request.append_instructions([si]) |
84 | | - |
85 | | - # Handle static_instruction - add via append_instructions |
86 | | - if agent.static_instruction: |
87 | | - from google.genai import _transformers |
88 | | - |
89 | | - # Convert ContentUnion to Content using genai transformer |
90 | | - static_content = _transformers.t_content(agent.static_instruction) |
91 | | - llm_request.append_instructions(static_content) |
92 | | - |
93 | | - # Handle instruction based on whether static_instruction exists |
94 | | - if agent.instruction and not agent.static_instruction: |
95 | | - # Only add to system instructions if no static instruction exists |
96 | | - si = await self._process_agent_instruction(agent, invocation_context) |
97 | | - llm_request.append_instructions([si]) |
98 | | - elif agent.instruction and agent.static_instruction: |
99 | | - # Static instruction exists, so add dynamic instruction to content |
100 | | - from google.genai import types |
101 | | - |
102 | | - si = await self._process_agent_instruction(agent, invocation_context) |
103 | | - # Create user content for dynamic instruction |
104 | | - dynamic_content = types.Content(role='user', parts=[types.Part(text=si)]) |
105 | | - llm_request.contents.append(dynamic_content) |
| 127 | + await _build_instructions(invocation_context, llm_request) |
106 | 128 |
|
107 | 129 | # Maintain async generator behavior |
108 | 130 | return |
|
0 commit comments