diff --git a/src/strands/agent/agent.py b/src/strands/agent/agent.py index 3a23133de..d084d132f 100644 --- a/src/strands/agent/agent.py +++ b/src/strands/agent/agent.py @@ -412,6 +412,18 @@ def system_prompt(self, value: str | list[SystemContentBlock] | None) -> None: """ self._system_prompt, self._system_prompt_content = self._initialize_system_prompt(value) + @property + def system_prompt_content(self) -> list[SystemContentBlock] | None: + """Get the system prompt as content blocks. + + Returns the full content block representation, preserving cache control + and non-text content. Returns None if no system prompt is set. + + Returns: + The system prompt as a list of SystemContentBlock objects, or None. + """ + return self._system_prompt_content + @property def tool(self) -> _ToolCaller: """Call tool as a function. diff --git a/src/strands/event_loop/event_loop.py b/src/strands/event_loop/event_loop.py index 374cfe129..dd114ec4d 100644 --- a/src/strands/event_loop/event_loop.py +++ b/src/strands/event_loop/event_loop.py @@ -314,7 +314,7 @@ async def _handle_model_execution( model_id=model_id, custom_trace_attributes=agent.trace_attributes, system_prompt=agent.system_prompt, - system_prompt_content=agent._system_prompt_content, + system_prompt_content=agent.system_prompt_content, ) with trace_api.use_span(model_invoke_span, end_on_exit=True): await agent.hooks.invoke_callbacks_async( @@ -335,7 +335,7 @@ async def _handle_model_execution( agent.system_prompt, agent.messages, tool_specs, - system_prompt_content=agent._system_prompt_content, + system_prompt_content=agent.system_prompt_content, tool_choice=structured_output_context.tool_choice, invocation_state=invocation_state, model_state=agent._model_state, diff --git a/tests/strands/agent/test_agent.py b/tests/strands/agent/test_agent.py index 5a3cce11c..018e287ce 100644 --- a/tests/strands/agent/test_agent.py +++ b/tests/strands/agent/test_agent.py @@ -1140,7 +1140,7 @@ def test_system_prompt_setter_string(): agent.system_prompt = "updated prompt" assert agent.system_prompt == "updated prompt" - assert agent._system_prompt_content == [{"text": "updated prompt"}] + assert agent.system_prompt_content == [{"text": "updated prompt"}] def test_system_prompt_setter_list(): @@ -1151,7 +1151,7 @@ def test_system_prompt_setter_list(): agent.system_prompt = content_blocks assert agent.system_prompt == "You are helpful" - assert agent._system_prompt_content == content_blocks + assert agent.system_prompt_content == content_blocks def test_system_prompt_setter_none(): @@ -1161,7 +1161,7 @@ def test_system_prompt_setter_none(): agent.system_prompt = None assert agent.system_prompt is None - assert agent._system_prompt_content is None + assert agent.system_prompt_content is None @pytest.mark.asyncio @@ -1964,7 +1964,7 @@ def test_agent_string_system_prompt(): agent = Agent(system_prompt=system_prompt) assert agent.system_prompt == system_prompt - assert agent._system_prompt_content == [{"text": system_prompt}] + assert agent.system_prompt_content == [{"text": system_prompt}] def test_agent_single_text_block_system_prompt(): @@ -1974,7 +1974,7 @@ def test_agent_single_text_block_system_prompt(): agent = Agent(system_prompt=system_prompt_content) assert agent.system_prompt == text - assert agent._system_prompt_content == system_prompt_content + assert agent.system_prompt_content == system_prompt_content def test_agent_multiple_blocks_system_prompt(): @@ -1987,7 +1987,7 @@ def test_agent_multiple_blocks_system_prompt(): agent = Agent(system_prompt=system_prompt_content) assert agent.system_prompt == "You are a helpful assistant.\nAdditional instructions." - assert agent._system_prompt_content == system_prompt_content + assert agent.system_prompt_content == system_prompt_content def test_agent_single_non_text_block_system_prompt(): @@ -1996,7 +1996,7 @@ def test_agent_single_non_text_block_system_prompt(): agent = Agent(system_prompt=system_prompt_content) assert agent.system_prompt is None - assert agent._system_prompt_content == system_prompt_content + assert agent.system_prompt_content == system_prompt_content def test_agent_none_system_prompt(): @@ -2004,7 +2004,7 @@ def test_agent_none_system_prompt(): agent = Agent(system_prompt=None) assert agent.system_prompt is None - assert agent._system_prompt_content is None + assert agent.system_prompt_content is None def test_agent_empty_list_system_prompt(): @@ -2012,7 +2012,7 @@ def test_agent_empty_list_system_prompt(): agent = Agent(system_prompt=[]) assert agent.system_prompt is None - assert agent._system_prompt_content == [] + assert agent.system_prompt_content == [] def test_agent_backwards_compatibility_string_access(): diff --git a/tests/strands/event_loop/test_event_loop.py b/tests/strands/event_loop/test_event_loop.py index 2f57f5560..371b7a793 100644 --- a/tests/strands/event_loop/test_event_loop.py +++ b/tests/strands/event_loop/test_event_loop.py @@ -551,7 +551,7 @@ async def test_event_loop_cycle_creates_spans( mock_tracer.start_model_invoke_span.assert_called_once() call_kwargs = mock_tracer.start_model_invoke_span.call_args[1] assert call_kwargs["system_prompt"] == agent.system_prompt - assert call_kwargs["system_prompt_content"] == agent._system_prompt_content + assert call_kwargs["system_prompt_content"] == agent.system_prompt_content mock_tracer.end_model_invoke_span.assert_called_once() mock_tracer.end_event_loop_cycle_span.assert_called_once() diff --git a/tests/strands/vended_plugins/skills/test_agent_skills.py b/tests/strands/vended_plugins/skills/test_agent_skills.py index 52802a6c1..851e77fd0 100644 --- a/tests/strands/vended_plugins/skills/test_agent_skills.py +++ b/tests/strands/vended_plugins/skills/test_agent_skills.py @@ -38,6 +38,9 @@ def _mock_agent(): lambda self, value: _set_system_prompt(self, value), ) + # Make system_prompt_content property behave like the real Agent + type(agent).system_prompt_content = property(lambda self: self._system_prompt_content) + agent.hooks = HookRegistry() agent.add_hook = MagicMock( side_effect=lambda callback, event_type=None: agent.hooks.add_callback(event_type, callback) @@ -419,7 +422,7 @@ def test_uses_public_system_prompt_setter(self): # The public setter should have been used, so _system_prompt_content # should be consistent with _system_prompt - assert agent._system_prompt_content == [{"text": agent._system_prompt}] + assert agent.system_prompt_content == [{"text": agent._system_prompt}] def test_warns_when_previous_xml_not_found(self, caplog): """Test that a warning is logged when the previously injected XML is missing from the prompt."""