From f7c67a2c8ea501f01634b08d456b3a6f28508dcf Mon Sep 17 00:00:00 2001 From: Nick Clegg Date: Fri, 27 Jun 2025 19:00:27 +0000 Subject: [PATCH 1/3] Add Agent State to docs --- docs/user-guide/concepts/agents/agent-loop.md | 2 +- docs/user-guide/concepts/agents/prompts.md | 2 +- .../{sessions-state.md => state-sessions.md} | 167 ++++++++++++------ .../concepts/tools/tools_overview.md | 2 +- docs/user-guide/quickstart.md | 2 +- mkdocs.yml | 2 +- 6 files changed, 115 insertions(+), 62 deletions(-) rename docs/user-guide/concepts/agents/{sessions-state.md => state-sessions.md} (64%) diff --git a/docs/user-guide/concepts/agents/agent-loop.md b/docs/user-guide/concepts/agents/agent-loop.md index 0de55d90..ae5f56b0 100644 --- a/docs/user-guide/concepts/agents/agent-loop.md +++ b/docs/user-guide/concepts/agents/agent-loop.md @@ -69,7 +69,7 @@ Messages flow through the agent loop in a structured format: 2. **Assistant messages**: Responses from the model that may include tool requests 3. **Tool result messages**: Results from tool executions fed back to the model -The SDK automatically formats these messages into the appropriate structure for model inputs and [session state](sessions-state.md). +The SDK automatically formats these messages into the appropriate structure for model inputs and [session state](state-sessions.md). ### Tool Execution diff --git a/docs/user-guide/concepts/agents/prompts.md b/docs/user-guide/concepts/agents/prompts.md index 2b94c890..85e66f2f 100644 --- a/docs/user-guide/concepts/agents/prompts.md +++ b/docs/user-guide/concepts/agents/prompts.md @@ -40,7 +40,7 @@ For programmatic control, you can call tools directly: result = agent.tool.current_time(timezone="US/Pacific") ``` -This bypasses the natural language interface and directly executes the tool with the specified parameters. By default, direct tool calls are added to the [session state](sessions-state.md) but can be optionally not included by specifying `record_direct_tool_call=False`. +This bypasses the natural language interface and directly executes the tool with the specified parameters. By default, direct tool calls are added to the [session state](state-sessions.md) but can be optionally not included by specifying `record_direct_tool_call=False`. ## Prompt Engineering diff --git a/docs/user-guide/concepts/agents/sessions-state.md b/docs/user-guide/concepts/agents/state-sessions.md similarity index 64% rename from docs/user-guide/concepts/agents/sessions-state.md rename to docs/user-guide/concepts/agents/state-sessions.md index 1cddb0b5..af4d3c6d 100644 --- a/docs/user-guide/concepts/agents/sessions-state.md +++ b/docs/user-guide/concepts/agents/state-sessions.md @@ -1,18 +1,18 @@ -# Sessions & State +# State & Sessions -This document explains how Strands agents maintain conversation context, handle state management, and support persistent sessions across interactions. +## State Management -Strands agents maintain state in several forms: +Strands Agents state is maintained in several forms: -1. **Conversation History**: The sequence of messages between the user and the agent -2. **Tool State**: Information about tool executions and results -3. **Request State**: Contextual information maintained within a single request +1. **Conversation History:** The sequence of messages between the user and the agent. +2. **Agent State**: Stateful information outside of conversation context, maintained across multiple requests. +3. **Request State**: Contextual information maintained within a single request. Understanding how state works in Strands is essential for building agents that can maintain context across multi-turn interactions and workflows. -## Conversation History +### Conversation History -The primary form of state in a Strands agent is the conversation history, directly accessible through the `agent.messages` property: +Conversation history is the primary form of context in a Strands agent, directly accessible through the `agent.messages` property: ```python from strands import Agent @@ -51,7 +51,30 @@ Conversation history is automatically: - Used for tool execution context - Managed to prevent context window overflow -## Conversation Manager +#### Direct Tool Calling + +Direct tool calls can also be recorded in the conversation history: + +```python +from strands import Agent +from strands_tools import calculator + +agent = Agent(tools=[calculator]) + +# Direct tool call with recording (default behavior) +agent.tool.calculator(expression="123 * 456") + +# Direct tool call without recording +agent.tool.calculator(expression="765 / 987", record_direct_tool_call=False) + +print(agent.messages) +``` + +In this example we can see that the first `agent.tool.calculator()` call is recorded in the agent's conversation history. + +The second `agent.tool.calculator()` call is **not** recorded in the history because we specified the `record_direct_tool_call=False` argument. + +#### Conversation Manager Strands uses a conversation manager to handle conversation history effectively. The default is the [`SlidingWindowConversationManager`](../../../api-reference/agent.md#strands.agent.conversation_manager.sliding_window_conversation_manager.SlidingWindowConversationManager), which keeps recent messages and removes older ones when needed: @@ -76,52 +99,102 @@ The sliding window conversation manager: - Handles context window overflow exceptions by reducing context - Ensures conversations don't exceed model context limits -## Tool State +See [`Context Management`](context-management.md) for more information about conversation managers. + + +### Agent State + +Agent state provides key-value storage for stateful information that exists outside of the conversation context. Unlike conversation history, agent state is not passed to the model during inference but can be accessed and modified by tools and application logic. -When an agent uses tools, the tool executions and results become part of the conversation state: +#### Basic Usage ```python from strands import Agent -from strands_tools import calculator -agent = Agent(tools=[calculator]) +# Create an agent with initial state +agent = Agent(state={"user_preferences": {"theme": "dark"}, "session_count": 0}) -# Tool use is recorded in the conversation history -agent("What is 123 × 456?") # Uses calculator tool and records result +agent2 Agent(state={"user_preferences": {"theme": "dark"}, "session_count": 0}) -# You can examine the tool interactions in the conversation history -print(agent.messages) # Shows tool calls and results -``` +# Access state values +theme = agent.state.get("user_preferences") +print(theme) # {"theme": "dark"} -Tool state includes: +# Set new state values +agent.state.set("last_action", "login") +agent.state.set("session_count", 1) -- Tool use requests from the model -- Tool execution parameters -- Tool execution results -- Any errors or exceptions that occurred +# Get entire state +all_state = agent.state.get() +print(all_state) # All state data as a dictionary -Direct tool calls can also be recorded in the conversation history: +# Delete state values +agent.state.delete("last_action") +``` + +#### State Validation and Safety + +Agent state enforces JSON serialization validation to ensure data can be persisted and restored: ```python from strands import Agent -from strands_tools import calculator -agent = Agent(tools=[calculator]) +agent = Agent() -# Direct tool call with recording (default behavior) -agent.tool.calculator(expression="123 * 456") +# Valid JSON-serializable values +agent.state.set("string_value", "hello") +agent.state.set("number_value", 42) +agent.state.set("boolean_value", True) +agent.state.set("list_value", [1, 2, 3]) +agent.state.set("dict_value", {"nested": "data"}) +agent.state.set("null_value", None) + +# Invalid values will raise ValueError +try: + agent.state.set("function", lambda x: x) # Not JSON serializable +except ValueError as e: + print(f"Error: {e}") +``` -# Direct tool call without recording -agent.tool.calculator(expression="765 / 987", record_direct_tool_call=False) +#### Using State in Tools -print(agent.messages) -``` +Agent state is particularly useful for maintaining information across tool executions: -In this example we can see that the first `agent.tool.calculator()` call is recorded in the agent's conversation history. +```python +from strands import Agent +from strands.tools.decorator import tool -The second `agent.tool.calculator()` call is **not** recorded in the history because we specified the `record_direct_tool_call=False` argument. +@tool +def track_user_action(action: str, agent: Agent): + """Track user actions in agent state.""" + # Get current action count + action_count = agent.state.get("action_count") or 0 + + # Update state + agent.state.set("action_count", action_count + 1) + agent.state.set("last_action", action) + + return f"Action '{action}' recorded. Total actions: {action_count + 1}" + +@tool +def get_user_stats(agent: Agent): + """Get user statistics from agent state.""" + action_count = agent.state.get("action_count") or 0 + last_action = agent.state.get("last_action") or "none" + + return f"Actions performed: {action_count}, Last action: {last_action}" + +# Create agent with tools +agent = Agent(tools=[track_user_action, get_user_stats]) + +# Use tools that modify and read state +agent("Track that I logged in") +agent("Track that I viewed my profile") +print(f"Actions taken: {agent.state.get('action_count')}") +print(f"Last action: {agent.state.get('last_action')}") +``` -## Request State +### Request State Each agent interaction maintains a request state dictionary that persists throughout the event loop cycles and is **not** included in the agent's context: @@ -149,12 +222,12 @@ The request state: - Is initialized at the beginning of each agent call - Persists through recursive event loop cycles -- Can be modified by tools and handlers +- Can be modified by callback handlers - Is returned in the AgentResult object ## Session Management -For applications requiring persistent sessions across separate interactions, Strands provides several approaches: +A session represents all of the stateful information that is needed by an agent to function. For applications requiring persistent sessions across separate interactions, Strands provides several approaches: ### 1. Object Persistence @@ -256,23 +329,3 @@ def chat(): return {"response": result.message} ``` -## Custom Conversation Management - -For specialized requirements, you can implement your own conversation manager: - -```python -from strands.agent.conversation_manager import ConversationManager -from strands.types.content import Messages -from typing import Optional - -class CustomConversationManager(ConversationManager): - def apply_management(self, messages: Messages) -> None: - """Apply management strategies to the messages list.""" - # Implement your management strategy - pass - - def reduce_context(self, messages: Messages, e: Optional[Exception] = None) -> None: - """Reduce context to handle overflow exceptions.""" - # Implement your reduction strategy - pass -``` \ No newline at end of file diff --git a/docs/user-guide/concepts/tools/tools_overview.md b/docs/user-guide/concepts/tools/tools_overview.md index 9fe89d8f..290b6240 100644 --- a/docs/user-guide/concepts/tools/tools_overview.md +++ b/docs/user-guide/concepts/tools/tools_overview.md @@ -56,7 +56,7 @@ agent = Agent(load_tools_from_directory=False) Tools can be invoked in two primary ways. -Agents have context about tool calls and their results as part of conversation history. See [sessions & state](../agents/sessions-state.md#tool-state) for more information. +Agents have context about tool calls and their results as part of conversation history. See [state & sessions](../agents/state-sessions.md#using-state-in-tools) for more information. ### Natural Language Invocation diff --git a/docs/user-guide/quickstart.md b/docs/user-guide/quickstart.md index cfb8e3ec..5a8dde79 100644 --- a/docs/user-guide/quickstart.md +++ b/docs/user-guide/quickstart.md @@ -327,7 +327,7 @@ Ready to learn more? Check out these resources: - [Example Built-in Tools](concepts/tools/example-tools-package.md) - The `strands-agents-tools` package provides many powerful example tools for your agents to use during development - [Strands Agent Builder]({{ agent_builder_repo_home }}) - Use the accompanying `strands-agents-builder` agent builder to harness the power of LLMs to generate your own tools and agents - [Agent Loop](concepts/agents/agent-loop.md) - Learn how Strands agents work under the hood -- [Sessions & State](concepts/agents/sessions-state.md) - Understand how agents maintain context and state across a conversation or workflow +- [State & Sessions](concepts/agents/state-sessions.md) - Understand how agents maintain context and state across a conversation or workflow - [Multi-agent](concepts/multi-agent/agents-as-tools.md) - Orchestrate multiple agents together as one system, with each agent completing specialized tasks - [Observability & Evaluation](observability-evaluation/observability.md) - Understand how agents make decisions and improve them with data - [Operating Agents in Production](deploy/operating-agents-in-production.md) - Taking agents from development to production, operating them responsibly at scale diff --git a/mkdocs.yml b/mkdocs.yml index 358501c5..e990af5a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,7 +72,7 @@ nav: - Concepts: - Agents: - Agent Loop: user-guide/concepts/agents/agent-loop.md - - Sessions & State: user-guide/concepts/agents/sessions-state.md + - State & Sessions: user-guide/concepts/agents/state-sessions.md - Prompts: user-guide/concepts/agents/prompts.md - Structured Output: user-guide/concepts/agents/structured-output.md - Context Management: user-guide/concepts/agents/context-management.md From 892bf0b566d65e4cf33f77331c449d08bb61d6cc Mon Sep 17 00:00:00 2001 From: Nick Clegg Date: Tue, 1 Jul 2025 10:07:32 -0400 Subject: [PATCH 2/3] Update docs/user-guide/concepts/agents/state-sessions.md Co-authored-by: Mackenzie Zastrow <3211021+zastrowm@users.noreply.github.com> --- docs/user-guide/concepts/agents/state-sessions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/concepts/agents/state-sessions.md b/docs/user-guide/concepts/agents/state-sessions.md index af4d3c6d..5379e3cb 100644 --- a/docs/user-guide/concepts/agents/state-sessions.md +++ b/docs/user-guide/concepts/agents/state-sessions.md @@ -53,7 +53,7 @@ Conversation history is automatically: #### Direct Tool Calling -Direct tool calls can also be recorded in the conversation history: +Direct tool calls are (by default) recorded in the conversation history: ```python from strands import Agent From 167e51cc1d21e2056fb7c1c23d29f8c07e0992c4 Mon Sep 17 00:00:00 2001 From: Nick Clegg Date: Tue, 1 Jul 2025 10:08:00 -0400 Subject: [PATCH 3/3] Update docs/user-guide/concepts/agents/state-sessions.md Co-authored-by: Mackenzie Zastrow <3211021+zastrowm@users.noreply.github.com> --- docs/user-guide/concepts/agents/state-sessions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/user-guide/concepts/agents/state-sessions.md b/docs/user-guide/concepts/agents/state-sessions.md index 5379e3cb..1915b1c4 100644 --- a/docs/user-guide/concepts/agents/state-sessions.md +++ b/docs/user-guide/concepts/agents/state-sessions.md @@ -114,7 +114,6 @@ from strands import Agent # Create an agent with initial state agent = Agent(state={"user_preferences": {"theme": "dark"}, "session_count": 0}) -agent2 Agent(state={"user_preferences": {"theme": "dark"}, "session_count": 0}) # Access state values theme = agent.state.get("user_preferences")