Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/strands/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/strands/event_loop/event_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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,
Expand Down
18 changes: 9 additions & 9 deletions tests/strands/agent/test_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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():
Expand All @@ -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
Expand Down Expand Up @@ -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():
Expand All @@ -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():
Expand All @@ -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():
Expand All @@ -1996,23 +1996,23 @@ 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():
"""Test initialization with 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():
"""Test initialization with 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():
Expand Down
2 changes: 1 addition & 1 deletion tests/strands/event_loop/test_event_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
5 changes: 4 additions & 1 deletion tests/strands/vended_plugins/skills/test_agent_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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."""
Expand Down