Skip to content

state

strands_teams.display.state

Mutable display state and phase/discovery models for event rendering.

This module provides the runtime state a consumer accumulates while an agent run streams: active/completed tool calls, phase progression, discovery events, and dispatched-team status. All types are domain-agnostic — phase identity and names come from an injected :class:~strands_teams.phases.PhaseSpec, and discovery-event kinds are plain strings supplied by the use case.

DiscoveryEvent

Bases: FrozenModel

A notable discovery made during a run.

kind is a free-form string tag supplied by the use case's discovery extractor (e.g. "files_discovered"); the framework imposes no enum.

PhaseState

Bases: StrictModel

Mutable runtime state for a single run phase.

The phase index and name/description are resolved against the injected :class:~strands_teams.phases.PhaseSpec when the phase is entered.

is_complete property

is_complete

Whether this phase has completed.

elapsed_seconds property

elapsed_seconds

Seconds elapsed since phase started (or total if completed).

TeamDispatchState

Bases: StrictModel

State for a dispatched specialist team.

Attributes:

Name Type Description
team_id str

Unique identifier for the team (e.g., "security", "architecture").

mandate str

One-line description of the team's investigation focus.

agent_count int

Number of agents in the team swarm.

status str

Current status ("running", "done", "error").

started_at float | None

Monotonic timestamp when the team was dispatched.

duration_seconds float

Total elapsed seconds (set when completed).

ToolCallState

Bases: StrictModel

State for a single tool call.

Attributes:

Name Type Description
tool_call_id str

Unique identifier for the tool call.

tool_name str

Name of the tool being executed.

agent_name str

Name of the agent that invoked this tool.

args_buffer str

Accumulated tool arguments (streaming).

result Any

Tool execution result (when complete).

status str

Current status ("running", "completed", "error").

AgentDisplayState

Bases: StrictModel

Mutable state for agent display rendering.

This class tracks all state needed to render an agent's progress in a terminal or UI. It accumulates streaming text, tracks active and completed tool calls, phase progression, discoveries, dispatched teams, and error state. Phase identity is resolved against the injected phase_spec.

Attributes:

Name Type Description
phase_spec PhaseSpec

Injected phase specification (names, count, tool map).

current_phase str

Description of the current phase.

text_buffer str

Accumulated streaming text from the agent.

active_message_id str | None

ID of currently streaming message.

active_tool ToolCallState | None

Currently executing tool state (if any).

completed_tools list[ToolCallState]

List of completed tool executions.

state_snapshot dict[str, Any]

Latest state snapshot from the agent.

error str | None

Error message if the run failed.

completed bool

Whether the run has finished.

thread_id str | None

Current thread identifier.

run_id str | None

Current run identifier.

Example

state = AgentDisplayState(phase_spec=my_spec) state.text_buffer += "Analyzing repository..."

clear_text_buffer

clear_text_buffer()

Clear and return the text buffer.

Returns:

Type Description
str

The text buffer contents before clearing.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def clear_text_buffer(self) -> str:
    """Clear and return the text buffer.

    Returns:
        The text buffer contents before clearing.
    """
    text = self.text_buffer
    self.text_buffer = ""
    return text

complete_active_tool

complete_active_tool(result=None)

Mark the active tool as completed and move to history.

Parameters:

Name Type Description Default
result Any

Optional result to store with the tool call.

None
Source code in packages/strands-teams/src/strands_teams/display/state.py
def complete_active_tool(self, result: Any = None) -> None:
    """Mark the active tool as completed and move to history.

    Args:
        result: Optional result to store with the tool call.
    """
    if self.active_tool:
        self.active_tool.status = "completed"
        self.active_tool.result = result
        self.completed_tools.append(self.active_tool)
        self.active_tool = None

record_tool

record_tool(*, tool_id, tool_name, status, result)

Record a tool call's start or completion for the dashboard.

Called by ToolDisplayHook on both the before- and after-tool-call events. A running status opens a new active tool (and advances the phase resolved from the tool name); any other status closes it and moves it to history, counting errors.

Parameters:

Name Type Description Default
tool_id str

The tool-use identifier from the event.

required
tool_name str

Name of the tool being executed.

required
status str

"running" to open the call, "completed"/"error" to close it.

required
result str

Truncated result string to store when closing the call.

required
Source code in packages/strands-teams/src/strands_teams/display/state.py
def record_tool(self, *, tool_id: str, tool_name: str, status: str, result: str) -> None:
    """Record a tool call's start or completion for the dashboard.

    Called by ``ToolDisplayHook`` on both the before- and after-tool-call
    events. A ``running`` status opens a new active tool (and advances the
    phase resolved from the tool name); any other status closes it and moves
    it to history, counting errors.

    Args:
        tool_id: The tool-use identifier from the event.
        tool_name: Name of the tool being executed.
        status: ``"running"`` to open the call, ``"completed"``/``"error"`` to close it.
        result: Truncated result string to store when closing the call.
    """
    if status == "running":
        self.active_tool = ToolCallState(tool_call_id=tool_id, tool_name=tool_name, status="running")
        self.tool_start_time = time.monotonic()
        phase = self.phase_spec.resolve(tool_name)
        if phase is not None:
            self.advance_phase(phase)
        return

    if self.active_tool is not None:
        self.active_tool.status = status
        self.active_tool.result = result
        self.completed_tools.append(self.active_tool)
        self.active_tool = None
    else:
        self.completed_tools.append(
            ToolCallState(tool_call_id=tool_id, tool_name=tool_name, status=status, result=result)
        )
    if status == "error":
        self.tool_errors += 1
    self.tool_start_time = None

get_recent_tools

get_recent_tools(count=5)

Get the most recent completed tools.

Parameters:

Name Type Description Default
count int

Maximum number of tools to return.

5

Returns:

Type Description
list[ToolCallState]

List of recently completed tool states.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def get_recent_tools(self, count: int = 5) -> list[ToolCallState]:
    """Get the most recent completed tools.

    Args:
        count: Maximum number of tools to return.

    Returns:
        List of recently completed tool states.
    """
    return self.completed_tools[-count:]

get_tool_stats

get_tool_stats()

Get tool call counts grouped by prefix.

Groups tools by their name prefix (e.g., lsp_*, git_*) for display in the TUI dashboard.

Returns:

Type Description
dict[str, int]

Dictionary mapping tool prefixes to call counts.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def get_tool_stats(self) -> dict[str, int]:
    """Get tool call counts grouped by prefix.

    Groups tools by their name prefix (e.g., ``lsp_*``, ``git_*``) for
    display in the TUI dashboard.

    Returns:
        Dictionary mapping tool prefixes to call counts.
    """
    stats: dict[str, int] = {}
    for tool in self.completed_tools:
        parts = tool.tool_name.split("_")
        prefix = parts[0] + "_*" if len(parts) > 1 else tool.tool_name
        stats[prefix] = stats.get(prefix, 0) + 1
    return stats

get_elapsed_seconds

get_elapsed_seconds()

Get elapsed time since the run started.

Returns:

Type Description
float

Elapsed seconds, or 0.0 if not started.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def get_elapsed_seconds(self) -> float:
    """Get elapsed time since the run started.

    Returns:
        Elapsed seconds, or 0.0 if not started.
    """
    if self.start_time is None:
        return 0.0
    return time.monotonic() - self.start_time

get_tool_elapsed_seconds

get_tool_elapsed_seconds()

Get elapsed time for the current tool.

Returns:

Type Description
float

Elapsed seconds for the active tool, or 0.0 if no active tool.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def get_tool_elapsed_seconds(self) -> float:
    """Get elapsed time for the current tool.

    Returns:
        Elapsed seconds for the active tool, or 0.0 if no active tool.
    """
    if self.tool_start_time is None:
        return 0.0
    return time.monotonic() - self.tool_start_time

get_success_count

get_success_count()

Get count of successful tool calls.

Returns:

Type Description
int

Number of completed tools minus errors.

Source code in packages/strands-teams/src/strands_teams/display/state.py
def get_success_count(self) -> int:
    """Get count of successful tool calls.

    Returns:
        Number of completed tools minus errors.
    """
    return len(self.completed_tools) - self.tool_errors

advance_phase

advance_phase(phase)

Advance to a new phase if it is higher than the current one.

Phase name and description are resolved from the injected phase_spec.

Parameters:

Name Type Description Default
phase int

1-based phase index to advance to.

required
Source code in packages/strands-teams/src/strands_teams/display/state.py
def advance_phase(self, phase: int) -> None:
    """Advance to a new phase if it is higher than the current one.

    Phase name and description are resolved from the injected
    ``phase_spec``.

    Args:
        phase: 1-based phase index to advance to.
    """
    # Don't regress to a lower phase
    if self.phases and phase <= self.phases[-1].phase:
        return

    now = time.monotonic()
    if self.phases and not self.phases[-1].is_complete:
        self.phases[-1].completed_at = now

    self.phases.append(
        PhaseState(
            phase=phase,
            name=self.phase_spec.name(phase),
            description=self.phase_spec.description(phase),
            started_at=now,
        ),
    )
    self.current_phase_index = len(self.phases) - 1

add_discovery

add_discovery(event)

Add a discovery event, evicting oldest if at capacity.

Parameters:

Name Type Description Default
event DiscoveryEvent

DiscoveryEvent to add.

required
Source code in packages/strands-teams/src/strands_teams/display/state.py
def add_discovery(self, event: DiscoveryEvent) -> None:
    """Add a discovery event, evicting oldest if at capacity.

    Args:
        event: DiscoveryEvent to add.
    """
    self.discoveries.append(event)
    while len(self.discoveries) > self.max_discoveries:
        self.discoveries.pop(0)

start_team

start_team(team_id, mandate, agent_count=0)

Register a newly dispatched team.

Parameters:

Name Type Description Default
team_id str

Unique team identifier.

required
mandate str

One-line description of the team's focus.

required
agent_count int

Number of agents in the team.

0
Source code in packages/strands-teams/src/strands_teams/display/state.py
def start_team(self, team_id: str, mandate: str, agent_count: int = 0) -> None:
    """Register a newly dispatched team.

    Args:
        team_id: Unique team identifier.
        mandate: One-line description of the team's focus.
        agent_count: Number of agents in the team.
    """
    self.teams.append(
        TeamDispatchState(
            team_id=team_id,
            mandate=mandate,
            agent_count=agent_count,
            status="running",
            started_at=time.monotonic(),
        ),
    )

complete_team

complete_team(team_id, status='done')

Mark a team as completed.

Parameters:

Name Type Description Default
team_id str

Team identifier to mark complete.

required
status str

Final status ("done" or "error").

'done'
Source code in packages/strands-teams/src/strands_teams/display/state.py
def complete_team(self, team_id: str, status: str = "done") -> None:
    """Mark a team as completed.

    Args:
        team_id: Team identifier to mark complete.
        status: Final status ("done" or "error").
    """
    for team in self.teams:
        if team.team_id == team_id:
            team.status = status
            if team.started_at is not None:
                team.duration_seconds = time.monotonic() - team.started_at
            break

reset

reset()

Reset state for a new run (preserves the injected phase_spec).

Source code in packages/strands-teams/src/strands_teams/display/state.py
def reset(self) -> None:
    """Reset state for a new run (preserves the injected ``phase_spec``)."""
    self.current_phase = ""
    self.text_buffer = ""
    self.active_message_id = None
    self.active_tool = None
    self.completed_tools = []
    self.state_snapshot = {}
    self.error = None
    self.completed = False
    self.start_time = None
    self.turn_count = 0
    self.tool_errors = 0
    self.tool_start_time = None
    self.phases = []
    self.current_phase_index = -1
    self.discoveries = []
    self.teams = []