from __future__ import annotations

from dataclasses import dataclass
from typing import (
    Any,
    AsyncIterator,
    Callable,
    Coroutine,
    Dict,
    Iterator,
    List,
    Literal,
    Optional,
    Sequence,
    Set,
    Tuple,
    Type,
    Union,
    overload,
)

from pydantic import BaseModel

from agno.agent import Agent
from agno.compression.manager import CompressionManager
from agno.db.base import AsyncBaseDb, BaseDb, ComponentType, UserMemory
from agno.eval.base import BaseEval
from agno.filters import FilterExpr
from agno.guardrails import BaseGuardrail
from agno.knowledge.protocol import KnowledgeProtocol
from agno.learn.machine import LearningMachine
from agno.media import Audio, File, Image, Video
from agno.memory import MemoryManager
from agno.metrics import SessionMetrics
from agno.models.base import Model
from agno.models.message import Message
from agno.models.metrics import RunMetrics
from agno.models.response import ModelResponse
from agno.registry.registry import Registry
from agno.run import RunContext, RunStatus
from agno.run.agent import RunEvent, RunOutput, RunOutputEvent
from agno.run.team import (
    TeamRunEvent,
    TeamRunOutput,
    TeamRunOutputEvent,
)
from agno.session import SessionSummaryManager, TeamSession
from agno.session.summary import SessionSummary
from agno.team import (
    _cli,
    _default_tools,
    _init,
    _managers,
    _messages,
    _response,
    _run,
    _session,
    _storage,
    _tools,
    _utils,
)
from agno.team.mode import TeamMode
from agno.tools import Toolkit
from agno.tools.function import Function
from agno.utils.log import (
    log_error,
)


@dataclass(init=False)
class Team:
    """
    A class representing a team of agents.
    """

    members: Union[List[Union[Agent, "Team"]], Callable[..., List]]

    # Model for this Team
    model: Optional[Model] = None

    # --- Team settings ---
    # Team UUID (autogenerated if not set)
    id: Optional[str] = None
    # Name of the team
    name: Optional[str] = None
    # If this team is part of a team itself, this is the role of the team
    role: Optional[str] = None

    # --- If this Team is part of a team itself ---
    # If this team is part of a team itself, this is the ID of the parent team. This is set automatically.
    parent_team_id: Optional[str] = None

    # --- If this Team is part of a workflow ---
    # Optional workflow ID. Indicates this team is part of a workflow. This is set automatically.
    workflow_id: Optional[str] = None

    # --- Team execution settings ---
    # Team execution mode. When set, overrides the boolean flags below.
    mode: Optional[TeamMode] = None
    # If True, the team leader won't process responses from the members and instead will return them directly
    # Should not be used in combination with delegate_to_all_members
    respond_directly: bool = False
    # If True, the team leader will delegate the task to all members, instead of deciding for a subset
    delegate_to_all_members: bool = False
    # Set to false if you want to send the run input directly to the member agents
    determine_input_for_members: bool = True
    # Maximum number of iterations for autonomous task loop (mode=tasks)
    max_iterations: int = 10

    # --- User settings ---
    # Default user ID for this team
    user_id: Optional[str] = None

    # --- Session settings ---
    # Default Session ID for this team (autogenerated if not set)
    session_id: Optional[str] = None
    # Session state (stored in the database to persist across runs)
    session_state: Optional[Dict[str, Any]] = None
    # Set to True to add the session_state to the context
    add_session_state_to_context: bool = False
    # Set to True to give the team tools to update the session_state dynamically
    enable_agentic_state: bool = False
    # Set to True to overwrite the stored session_state with the session_state provided in the run
    overwrite_db_session_state: bool = False
    # If True, cache the current Team session in memory for faster access
    cache_session: bool = False

    # Add this flag to control if the workflow should send the team history to the members. This means sending the team-level history to the members, not the agent-level history.
    add_team_history_to_members: bool = False
    # Number of historical runs to include in the messages sent to the members
    num_team_history_runs: int = 3
    # If True, send all member interactions (request/response) during the current run to members that have been delegated a task to
    share_member_interactions: bool = False

    # If True, adds a tool to allow searching through previous sessions
    search_session_history: Optional[bool] = False
    # Number of past sessions to include in the search
    num_history_sessions: Optional[int] = None

    # If True, adds a tool to allow the team to read the chat history
    read_chat_history: bool = False

    # --- System message settings ---
    # A description of the Team that is added to the start of the system message.
    description: Optional[str] = None
    # List of instructions for the team.
    instructions: Optional[Union[str, List[str], Callable]] = None
    # If True, wrap instructions in <instructions> tags. Default is False.
    use_instruction_tags: bool = False
    # Provide the expected output from the Team.
    expected_output: Optional[str] = None
    # Additional context added to the end of the system message.
    additional_context: Optional[str] = None
    # If markdown=true, add instructions to format the output using markdown
    markdown: bool = False
    # If True, add the current datetime to the instructions to give the team a sense of time
    # This allows for relative times like "tomorrow" to be used in the prompt
    add_datetime_to_context: bool = False
    # If True, add the current location to the instructions to give the team a sense of location
    add_location_to_context: bool = False
    # Allows for custom timezone for datetime instructions following the TZ Database format (e.g. "Etc/UTC")
    timezone_identifier: Optional[str] = None
    # If True, add the team name to the instructions
    add_name_to_context: bool = False
    # If True, add the tools available to team members to the context
    add_member_tools_to_context: bool = False

    # Provide the system message as a string or function
    system_message: Optional[Union[str, Callable, Message]] = None
    # Role for the system message
    system_message_role: str = "system"
    # Introduction for the team
    introduction: Optional[str] = None

    # If True, resolve the session_state, dependencies, and metadata in the user and system messages
    resolve_in_context: bool = True

    # --- Extra Messages ---
    # A list of extra messages added after the system message and before the user message.
    # Use these for few-shot learning or to provide additional context to the Model.
    # Note: these are not retained in memory, they are added directly to the messages sent to the model.
    additional_input: Optional[List[Union[str, Dict, BaseModel, Message]]] = None

    # --- Database ---
    # Database to use for this agent
    db: Optional[Union[BaseDb, AsyncBaseDb]] = None

    # Memory manager to use for this agent
    memory_manager: Optional[MemoryManager] = None

    # --- User provided dependencies ---
    # User provided dependencies
    dependencies: Optional[Dict[str, Any]] = None
    # If True, add the dependencies to the user prompt
    add_dependencies_to_context: bool = False

    # --- Agent Knowledge ---
    knowledge: Optional[Union[KnowledgeProtocol, Callable[..., KnowledgeProtocol]]] = None
    # Add knowledge_filters to the Agent class attributes
    knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
    # Let the agent choose the knowledge filters
    enable_agentic_knowledge_filters: Optional[bool] = False
    # Add a tool that allows the Team to update Knowledge.
    update_knowledge: bool = False
    # If True, add references to the user prompt
    add_knowledge_to_context: bool = False
    # Retrieval function to get references
    # This function, if provided, is used instead of the default search_knowledge function
    # Signature:
    # def knowledge_retriever(team: Team, query: str, num_documents: Optional[int], **kwargs) -> Optional[list[dict]]:
    #     ...
    knowledge_retriever: Optional[Callable[..., Optional[List[Union[Dict, str]]]]] = None
    references_format: Literal["json", "yaml"] = "json"

    # --- Tools ---
    # If True, add a tool to get information about the team members
    get_member_information_tool: bool = False
    # Add a tool to search the knowledge base (aka Agentic RAG)
    # Only added if knowledge is provided.
    search_knowledge: bool = True
    # If True, add search_knowledge instructions to the system prompt
    add_search_knowledge_instructions: bool = True

    # If False, media (images, videos, audio, files) is only available to tools and not sent to the LLM
    send_media_to_model: bool = True
    # If True, store media in run output
    store_media: bool = True
    # If True, store tool results in run output
    store_tool_messages: bool = True
    # If True, store history messages in run output
    store_history_messages: bool = False

    # --- Team Tools ---
    # A list of tools provided to the Model.
    # Tools are functions the model may generate JSON inputs for.
    # Can also be a callable factory that returns a list of tools at runtime.
    tools: Optional[Union[List[Union[Toolkit, Callable, Function, Dict]], Callable[..., List]]] = None

    # Controls which (if any) tool is called by the team model.
    # "none" means the model will not call a tool and instead generates a message.
    # "auto" means the model can pick between generating a message or calling a tool.
    # Specifying a particular function via {"type: "function", "function": {"name": "my_function"}}
    #   forces the model to call that tool.
    # "none" is the default when no tools are present. "auto" is the default if tools are present.
    tool_choice: Optional[Union[str, Dict[str, Any]]] = None
    # Maximum number of tool calls allowed.
    tool_call_limit: Optional[int] = None
    # A list of hooks to be called before and after the tool call
    tool_hooks: Optional[List[Callable]] = None

    # --- Team Hooks ---
    # Functions called right after team session is loaded, before processing starts
    pre_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]] = None
    # Functions called after output is generated but before the response is returned
    post_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]] = None
    # If True, run hooks as FastAPI background tasks (non-blocking). Set by AgentOS.
    _run_hooks_in_background: Optional[bool] = None

    # --- Structured output ---
    # Input schema for validating input
    input_schema: Optional[Type[BaseModel]] = None
    # Provide a response model to get the response in the implied format.
    # You can use a Pydantic model or a JSON fitting the provider's expected schema.
    output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None
    # Provide a secondary model to parse the response from the primary model
    parser_model: Optional[Model] = None
    # Provide a prompt for the parser model
    parser_model_prompt: Optional[str] = None
    # Provide an output model to parse the response from the team
    output_model: Optional[Model] = None
    # Provide a prompt for the output model
    output_model_prompt: Optional[str] = None
    # Intead of providing the model with the Pydantic output schema, add a JSON description of the output schema to the system message instead.
    use_json_mode: bool = False
    # If True, parse the response
    parse_response: bool = True

    # --- History ---
    # Enable the agent to manage memories of the user
    enable_agentic_memory: bool = False
    # If True, the agent creates/updates user memories at the end of runs
    update_memory_on_run: bool = False
    # Soon to be deprecated. Use update_memory_on_run
    enable_user_memories: Optional[bool] = None
    # If True, the agent adds a reference to the user memories in the response
    add_memories_to_context: Optional[bool] = None
    # If True, the agent creates/updates session summaries at the end of runs
    enable_session_summaries: bool = False
    # # Session summary model
    # session_summary_model: Optional[Model] = None
    # # Session summary prompt
    # session_summary_prompt: Optional[str] = None
    session_summary_manager: Optional[SessionSummaryManager] = None
    # If True, the team adds session summaries to the context
    add_session_summary_to_context: Optional[bool] = None

    # --- Learning Machine ---
    # LearningMachine for unified learning capabilities
    learning: Optional[Union[bool, LearningMachine]] = None
    # Add learnings context to system prompt
    add_learnings_to_context: bool = True

    # --- Context Compression ---
    # If True, compress tool call results to save context
    compress_tool_results: bool = False
    # Compression manager for compressing tool call results
    compression_manager: Optional["CompressionManager"] = None

    # --- Team History ---
    # add_history_to_context=true adds messages from the chat history to the messages list sent to the Model.
    add_history_to_context: bool = False
    # Number of historical runs to include in the messages
    num_history_runs: Optional[int] = None
    # Number of historical messages to include in the messages list sent to the Model.
    num_history_messages: Optional[int] = None
    # Maximum number of tool calls to include from history (None = no limit)
    max_tool_calls_from_history: Optional[int] = None

    # --- Team Storage ---
    # Metadata stored with this team
    metadata: Optional[Dict[str, Any]] = None

    # --- Team Reasoning ---
    reasoning: bool = False
    reasoning_model: Optional[Model] = None
    reasoning_agent: Optional[Agent] = None
    reasoning_min_steps: int = 1
    reasoning_max_steps: int = 10

    # --- Team Streaming ---
    # Stream the response from the Team
    stream: Optional[bool] = None
    # Stream the intermediate steps from the Agent
    stream_events: Optional[bool] = None
    # Stream the member events from the Team
    stream_member_events: bool = True

    # Store the events from the Team
    store_events: bool = False
    # List of events to skip from the Team
    events_to_skip: Optional[List[Union[RunEvent, TeamRunEvent]]] = None
    # Store member agent runs inside the team's RunOutput
    store_member_responses: bool = False

    # --- Debug ---
    # Enable debug logs
    debug_mode: bool = False
    # Debug level: 1 = basic, 2 = detailed
    debug_level: Literal[1, 2] = 1
    # Enable member logs - Sets the debug_mode for team and members
    show_members_responses: bool = False

    # --- Team Response Settings ---
    # Number of retries to attempt
    retries: int = 0
    # Delay between retries (in seconds)
    delay_between_retries: int = 1
    # Exponential backoff: if True, the delay between retries is doubled each time
    exponential_backoff: bool = False

    # --- Telemetry ---
    # telemetry=True logs minimal telemetry for analytics
    # This helps us improve the Teams implementation and provide better support
    telemetry: bool = True

    # --- Callable factory settings ---
    # Enable caching of callable factory results
    cache_callables: bool = True
    # Custom cache key function for tools callable factory
    callable_tools_cache_key: Optional[Callable[..., Optional[str]]] = None
    # Custom cache key function for knowledge callable factory
    callable_knowledge_cache_key: Optional[Callable[..., Optional[str]]] = None
    # Custom cache key function for members callable factory
    callable_members_cache_key: Optional[Callable[..., Optional[str]]] = None

    # --- Internal attributes (set during __init__, not user-facing) ---
    # Media generated during this session (TODO: Remove these)
    images: Optional[List[Image]] = None
    audio: Optional[List[Audio]] = None
    videos: Optional[List[Video]] = None
    # Cached session
    _cached_session: Optional[TeamSession] = None
    # Tool instructions
    _tool_instructions: Optional[List[str]] = None
    # Member response model
    _member_response_model: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None
    # Safe formatter for template resolution
    _formatter: Optional[Any] = None
    # Hooks normalised flag
    _hooks_normalised: bool = False
    # MCP tools initialized on the last run
    _mcp_tools_initialized_on_run: Optional[List[Any]] = None
    # Connectable tools initialized on the last run
    _connectable_tools_initialized_on_run: Optional[List[Any]] = None
    # Internal resolved LearningMachine instance
    _learning: Optional[LearningMachine] = None
    # Whether learning init has been attempted (prevents repeated attempts when db is None)
    _learning_init_attempted: bool = False
    # Lazy-initialized shared thread pool executor for background tasks
    _background_executor: Optional[Any] = None
    # Callable factory caches
    _callable_tools_cache: Dict[str, List[Any]] = None  # type: ignore[assignment]
    _callable_knowledge_cache: Dict[str, Any] = None  # type: ignore[assignment]
    _callable_members_cache: Dict[str, List[Any]] = None  # type: ignore[assignment]

    def __init__(
        self,
        members: Union[List[Union[Agent, "Team"]], Callable[..., List]],
        id: Optional[str] = None,
        model: Optional[Union[Model, str]] = None,
        name: Optional[str] = None,
        role: Optional[str] = None,
        mode: Optional[TeamMode] = None,
        respond_directly: bool = False,
        determine_input_for_members: bool = True,
        delegate_to_all_members: bool = False,
        max_iterations: int = 10,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        add_session_state_to_context: bool = False,
        enable_agentic_state: bool = False,
        overwrite_db_session_state: bool = False,
        resolve_in_context: bool = True,
        cache_session: bool = False,
        add_team_history_to_members: bool = False,
        num_team_history_runs: int = 3,
        search_session_history: Optional[bool] = False,
        num_history_sessions: Optional[int] = None,
        description: Optional[str] = None,
        instructions: Optional[Union[str, List[str], Callable]] = None,
        use_instruction_tags: bool = False,
        expected_output: Optional[str] = None,
        additional_context: Optional[str] = None,
        markdown: bool = False,
        add_datetime_to_context: bool = False,
        add_location_to_context: bool = False,
        timezone_identifier: Optional[str] = None,
        add_name_to_context: bool = False,
        add_member_tools_to_context: bool = False,
        system_message: Optional[Union[str, Callable, Message]] = None,
        system_message_role: str = "system",
        introduction: Optional[str] = None,
        additional_input: Optional[List[Union[str, Dict, BaseModel, Message]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        add_dependencies_to_context: bool = False,
        knowledge: Optional[Union[KnowledgeProtocol, Callable[..., KnowledgeProtocol]]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_knowledge_to_context: bool = False,
        enable_agentic_knowledge_filters: Optional[bool] = False,
        update_knowledge: bool = False,
        knowledge_retriever: Optional[Callable[..., Optional[List[Union[Dict, str]]]]] = None,
        references_format: Literal["json", "yaml"] = "json",
        share_member_interactions: bool = False,
        get_member_information_tool: bool = False,
        search_knowledge: bool = True,
        add_search_knowledge_instructions: bool = True,
        read_chat_history: bool = False,
        store_media: bool = True,
        store_tool_messages: bool = True,
        store_history_messages: bool = False,
        send_media_to_model: bool = True,
        add_history_to_context: bool = False,
        num_history_runs: Optional[int] = None,
        num_history_messages: Optional[int] = None,
        max_tool_calls_from_history: Optional[int] = None,
        tools: Optional[Union[List[Union[Toolkit, Callable, Function, Dict]], Callable[..., List]]] = None,
        tool_call_limit: Optional[int] = None,
        tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
        tool_hooks: Optional[List[Callable]] = None,
        pre_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]] = None,
        post_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]] = None,
        input_schema: Optional[Type[BaseModel]] = None,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        parser_model: Optional[Union[Model, str]] = None,
        parser_model_prompt: Optional[str] = None,
        output_model: Optional[Union[Model, str]] = None,
        output_model_prompt: Optional[str] = None,
        use_json_mode: bool = False,
        parse_response: bool = True,
        db: Optional[Union[BaseDb, AsyncBaseDb]] = None,
        enable_agentic_memory: bool = False,
        update_memory_on_run: bool = False,
        enable_user_memories: Optional[bool] = None,  # Soon to be deprecated. Use update_memory_on_run
        add_memories_to_context: Optional[bool] = None,
        memory_manager: Optional[MemoryManager] = None,
        enable_session_summaries: bool = False,
        session_summary_manager: Optional[SessionSummaryManager] = None,
        add_session_summary_to_context: Optional[bool] = None,
        learning: Optional[Union[bool, LearningMachine]] = None,
        add_learnings_to_context: bool = True,
        compress_tool_results: bool = False,
        compression_manager: Optional["CompressionManager"] = None,
        metadata: Optional[Dict[str, Any]] = None,
        reasoning: bool = False,
        reasoning_model: Optional[Union[Model, str]] = None,
        reasoning_agent: Optional[Agent] = None,
        reasoning_min_steps: int = 1,
        reasoning_max_steps: int = 10,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = None,
        store_events: bool = False,
        events_to_skip: Optional[List[Union[RunEvent, TeamRunEvent]]] = None,
        store_member_responses: bool = False,
        stream_member_events: bool = True,
        debug_mode: bool = False,
        debug_level: Literal[1, 2] = 1,
        show_members_responses: bool = False,
        retries: int = 0,
        delay_between_retries: int = 1,
        exponential_backoff: bool = False,
        telemetry: bool = True,
        cache_callables: bool = True,
        callable_tools_cache_key: Optional[Callable[..., Optional[str]]] = None,
        callable_knowledge_cache_key: Optional[Callable[..., Optional[str]]] = None,
        callable_members_cache_key: Optional[Callable[..., Optional[str]]] = None,
    ):
        _init.__init__(
            self,
            members=members,
            id=id,
            model=model,
            name=name,
            role=role,
            mode=mode,
            respond_directly=respond_directly,
            determine_input_for_members=determine_input_for_members,
            delegate_to_all_members=delegate_to_all_members,
            max_iterations=max_iterations,
            user_id=user_id,
            session_id=session_id,
            session_state=session_state,
            add_session_state_to_context=add_session_state_to_context,
            enable_agentic_state=enable_agentic_state,
            overwrite_db_session_state=overwrite_db_session_state,
            resolve_in_context=resolve_in_context,
            cache_session=cache_session,
            add_team_history_to_members=add_team_history_to_members,
            num_team_history_runs=num_team_history_runs,
            search_session_history=search_session_history,
            num_history_sessions=num_history_sessions,
            description=description,
            instructions=instructions,
            use_instruction_tags=use_instruction_tags,
            expected_output=expected_output,
            additional_context=additional_context,
            markdown=markdown,
            add_datetime_to_context=add_datetime_to_context,
            add_location_to_context=add_location_to_context,
            timezone_identifier=timezone_identifier,
            add_name_to_context=add_name_to_context,
            add_member_tools_to_context=add_member_tools_to_context,
            system_message=system_message,
            system_message_role=system_message_role,
            introduction=introduction,
            additional_input=additional_input,
            dependencies=dependencies,
            add_dependencies_to_context=add_dependencies_to_context,
            knowledge=knowledge,
            knowledge_filters=knowledge_filters,
            add_knowledge_to_context=add_knowledge_to_context,
            enable_agentic_knowledge_filters=enable_agentic_knowledge_filters,
            update_knowledge=update_knowledge,
            knowledge_retriever=knowledge_retriever,
            references_format=references_format,
            share_member_interactions=share_member_interactions,
            get_member_information_tool=get_member_information_tool,
            search_knowledge=search_knowledge,
            add_search_knowledge_instructions=add_search_knowledge_instructions,
            read_chat_history=read_chat_history,
            store_media=store_media,
            store_tool_messages=store_tool_messages,
            store_history_messages=store_history_messages,
            send_media_to_model=send_media_to_model,
            add_history_to_context=add_history_to_context,
            num_history_runs=num_history_runs,
            num_history_messages=num_history_messages,
            max_tool_calls_from_history=max_tool_calls_from_history,
            tools=tools,
            tool_call_limit=tool_call_limit,
            tool_choice=tool_choice,
            tool_hooks=tool_hooks,
            pre_hooks=pre_hooks,
            post_hooks=post_hooks,
            input_schema=input_schema,
            output_schema=output_schema,
            parser_model=parser_model,
            parser_model_prompt=parser_model_prompt,
            output_model=output_model,
            output_model_prompt=output_model_prompt,
            use_json_mode=use_json_mode,
            parse_response=parse_response,
            db=db,
            enable_agentic_memory=enable_agentic_memory,
            update_memory_on_run=update_memory_on_run,
            enable_user_memories=enable_user_memories,
            add_memories_to_context=add_memories_to_context,
            memory_manager=memory_manager,
            enable_session_summaries=enable_session_summaries,
            session_summary_manager=session_summary_manager,
            add_session_summary_to_context=add_session_summary_to_context,
            learning=learning,
            add_learnings_to_context=add_learnings_to_context,
            compress_tool_results=compress_tool_results,
            compression_manager=compression_manager,
            metadata=metadata,
            reasoning=reasoning,
            reasoning_model=reasoning_model,
            reasoning_agent=reasoning_agent,
            reasoning_min_steps=reasoning_min_steps,
            reasoning_max_steps=reasoning_max_steps,
            stream=stream,
            stream_events=stream_events,
            store_events=store_events,
            events_to_skip=events_to_skip,
            store_member_responses=store_member_responses,
            stream_member_events=stream_member_events,
            debug_mode=debug_mode,
            debug_level=debug_level,
            show_members_responses=show_members_responses,
            retries=retries,
            delay_between_retries=delay_between_retries,
            exponential_backoff=exponential_backoff,
            telemetry=telemetry,
            cache_callables=cache_callables,
            callable_tools_cache_key=callable_tools_cache_key,
            callable_knowledge_cache_key=callable_knowledge_cache_key,
            callable_members_cache_key=callable_members_cache_key,
        )

        # Component metadata (set by get_teams during DB loading)
        self._version: Optional[int] = None
        self._stage: Optional[str] = None

    @property
    def background_executor(self) -> Any:
        return _init.background_executor(self)

    @property
    def cached_session(self) -> Optional[TeamSession]:
        return _init.cached_session(self)

    def set_id(self) -> None:
        return _init.set_id(self)

    def _initialize_member(self, member: Union["Team", Agent], debug_mode: Optional[bool] = None) -> None:
        # Set debug mode for all members
        return _init._initialize_member(self, member=member, debug_mode=debug_mode)

    def propagate_run_hooks_in_background(self, run_in_background: bool = True) -> None:
        return _init.propagate_run_hooks_in_background(self, run_in_background=run_in_background)

    def _set_default_model(self) -> None:
        # Set the default model
        return _init._set_default_model(self)

    def initialize_team(self, debug_mode: Optional[bool] = None) -> None:
        # Make sure for the team, we are using the team logger
        return _init.initialize_team(self, debug_mode=debug_mode)

    @property
    def learning_machine(self) -> Optional[LearningMachine]:
        if (
            self._learning is None
            and not self._learning_init_attempted
            and self.learning is not None
            and self.learning is not False
        ):
            _init._set_learning_machine(self)
        return self._learning

    def add_tool(self, tool: Union[Toolkit, Callable, Function, Dict]):
        return _init.add_tool(self, tool=tool)

    def set_tools(self, tools: Union[List[Union[Toolkit, Callable, Function, Dict]], Callable[..., List]]):
        return _init.set_tools(self, tools=tools)

    def clear_callable_cache(
        self,
        kind: Optional[Literal["tools", "knowledge", "members"]] = None,
        close: bool = False,
    ) -> None:
        from agno.utils.callables import clear_callable_cache

        clear_callable_cache(self, kind=kind, close=close)

    async def aclear_callable_cache(
        self,
        kind: Optional[Literal["tools", "knowledge", "members"]] = None,
        close: bool = False,
    ) -> None:
        from agno.utils.callables import aclear_callable_cache

        await aclear_callable_cache(self, kind=kind, close=close)

    @staticmethod
    def cancel_run(run_id: str) -> bool:
        return _run.cancel_run(run_id=run_id)

    @staticmethod
    async def acancel_run(run_id: str) -> bool:
        return await _run.acancel_run(run_id=run_id)

    @overload
    def run(
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Literal[False] = False,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_context: Optional[RunContext] = None,
        user_id: Optional[str] = None,
        run_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        **kwargs: Any,
    ) -> TeamRunOutput: ...

    @overload
    def run(
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Literal[True] = True,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_context: Optional[RunContext] = None,
        user_id: Optional[str] = None,
        run_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        **kwargs: Any,
    ) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...

    def run(
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_context: Optional[RunContext] = None,
        run_id: Optional[str] = None,
        user_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        **kwargs: Any,
    ) -> Union[TeamRunOutput, Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
        return _run.run_dispatch(
            self,
            input=input,
            stream=stream,
            stream_events=stream_events,
            session_id=session_id,
            session_state=session_state,
            run_context=run_context,
            run_id=run_id,
            user_id=user_id,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            knowledge_filters=knowledge_filters,
            add_history_to_context=add_history_to_context,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            dependencies=dependencies,
            metadata=metadata,
            debug_mode=debug_mode,
            yield_run_output=yield_run_output,
            output_schema=output_schema,
            **kwargs,
        )

    @overload
    def arun(
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Literal[False] = False,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_id: Optional[str] = None,
        run_context: Optional[RunContext] = None,
        user_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        background: bool = False,
        **kwargs: Any,
    ) -> Coroutine[Any, Any, TeamRunOutput]: ...

    @overload
    def arun(
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Literal[True] = True,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_id: Optional[str] = None,
        run_context: Optional[RunContext] = None,
        user_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        **kwargs: Any,
    ) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...

    def arun(  # type: ignore
        self,
        input: Union[str, List, Dict, Message, BaseModel, List[Message]],
        *,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        run_id: Optional[str] = None,
        run_context: Optional[RunContext] = None,
        user_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        output_schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
        background: bool = False,
        **kwargs: Any,
    ) -> Union[TeamRunOutput, AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
        return _run.arun_dispatch(
            self,
            input=input,
            stream=stream,
            stream_events=stream_events,
            session_id=session_id,
            session_state=session_state,
            run_id=run_id,
            run_context=run_context,
            user_id=user_id,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            knowledge_filters=knowledge_filters,
            add_history_to_context=add_history_to_context,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            dependencies=dependencies,
            metadata=metadata,
            debug_mode=debug_mode,
            yield_run_output=yield_run_output,
            output_schema=output_schema,
            background=background,
            **kwargs,
        )

    ###########################################################################
    # Continue Run (HITL)
    ###########################################################################

    @overload
    def continue_run(
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        stream: Literal[False] = False,
        stream_events: Optional[bool] = None,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
    ) -> TeamRunOutput: ...

    @overload
    def continue_run(
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        stream: Literal[True] = True,
        stream_events: Optional[bool] = False,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
    ) -> Iterator[Union[TeamRunOutputEvent, RunOutputEvent]]: ...

    def continue_run(
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = False,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        run_context: Optional[RunContext] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        **kwargs,
    ) -> Union[TeamRunOutput, Iterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]]:
        return _run.continue_run_dispatch(
            self,
            run_response=run_response,
            run_id=run_id,
            requirements=requirements,
            stream=stream,
            stream_events=stream_events,
            user_id=user_id,
            session_id=session_id,
            run_context=run_context,
            knowledge_filters=knowledge_filters,
            dependencies=dependencies,
            metadata=metadata,
            debug_mode=debug_mode,
            yield_run_output=yield_run_output,
            **kwargs,
        )

    @overload
    def acontinue_run(
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        stream: Literal[False] = False,
        stream_events: Optional[bool] = None,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        **kwargs: Any,
    ) -> Coroutine[Any, Any, TeamRunOutput]: ...

    @overload
    def acontinue_run(
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        stream: Literal[True] = True,
        stream_events: Optional[bool] = None,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        **kwargs: Any,
    ) -> AsyncIterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]: ...

    def acontinue_run(  # type: ignore
        self,
        run_response: Optional[TeamRunOutput] = None,
        *,
        run_id: Optional[str] = None,
        requirements: Optional[List[Any]] = None,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = None,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
        run_context: Optional[RunContext] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        yield_run_output: bool = False,
        **kwargs: Any,
    ) -> Union[TeamRunOutput, AsyncIterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]]:
        return _run.acontinue_run_dispatch(
            self,
            run_response=run_response,
            run_id=run_id,
            requirements=requirements,
            stream=stream,
            stream_events=stream_events,
            user_id=user_id,
            session_id=session_id,
            run_context=run_context,
            knowledge_filters=knowledge_filters,
            dependencies=dependencies,
            metadata=metadata,
            debug_mode=debug_mode,
            yield_run_output=yield_run_output,
            **kwargs,
        )

    def _handle_model_response_chunk(
        self,
        session: TeamSession,
        run_response: TeamRunOutput,
        full_model_response: ModelResponse,
        model_response_event: Union[ModelResponse, TeamRunOutputEvent, RunOutputEvent],
        reasoning_state: Optional[Dict[str, Any]] = None,
        stream_events: bool = False,
        parse_structured_output: bool = False,
        session_state: Optional[Dict[str, Any]] = None,
        run_context: Optional[RunContext] = None,
    ) -> Iterator[Union[TeamRunOutputEvent, RunOutputEvent]]:
        yield from _response._handle_model_response_chunk(
            self,
            session=session,
            run_response=run_response,
            full_model_response=full_model_response,
            model_response_event=model_response_event,
            reasoning_state=reasoning_state,
            stream_events=stream_events,
            parse_structured_output=parse_structured_output,
            session_state=session_state,
            run_context=run_context,
        )

    ###########################################################################
    # Print Response
    ###########################################################################

    def print_response(
        self,
        input: Union[List, Dict, str, Message, BaseModel, List[Message]],
        *,
        stream: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        user_id: Optional[str] = None,
        run_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        markdown: Optional[bool] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        show_message: bool = True,
        show_reasoning: bool = True,
        show_full_reasoning: bool = False,
        show_member_responses: Optional[bool] = None,
        console: Optional[Any] = None,
        tags_to_include_in_markdown: Optional[Set[str]] = None,
        **kwargs: Any,
    ) -> None:
        return _cli.team_print_response(
            self,
            input=input,
            stream=stream,
            session_id=session_id,
            session_state=session_state,
            user_id=user_id,
            run_id=run_id,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            markdown=markdown,
            knowledge_filters=knowledge_filters,
            add_history_to_context=add_history_to_context,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            dependencies=dependencies,
            metadata=metadata,
            debug_mode=debug_mode,
            show_message=show_message,
            show_reasoning=show_reasoning,
            show_full_reasoning=show_full_reasoning,
            show_member_responses=show_member_responses,
            console=console,
            tags_to_include_in_markdown=tags_to_include_in_markdown,
            **kwargs,
        )

    async def aprint_response(
        self,
        input: Union[List, Dict, str, Message, BaseModel, List[Message]],
        *,
        stream: Optional[bool] = None,
        session_id: Optional[str] = None,
        session_state: Optional[Dict[str, Any]] = None,
        user_id: Optional[str] = None,
        run_id: Optional[str] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        markdown: Optional[bool] = None,
        knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        add_history_to_context: Optional[bool] = None,
        dependencies: Optional[Dict[str, Any]] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        metadata: Optional[Dict[str, Any]] = None,
        debug_mode: Optional[bool] = None,
        show_message: bool = True,
        show_reasoning: bool = True,
        show_full_reasoning: bool = False,
        show_member_responses: Optional[bool] = None,
        console: Optional[Any] = None,
        tags_to_include_in_markdown: Optional[Set[str]] = None,
        **kwargs: Any,
    ) -> None:
        return await _cli.team_aprint_response(
            self,
            input=input,
            stream=stream,
            session_id=session_id,
            session_state=session_state,
            user_id=user_id,
            run_id=run_id,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            markdown=markdown,
            knowledge_filters=knowledge_filters,
            add_history_to_context=add_history_to_context,
            dependencies=dependencies,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            metadata=metadata,
            debug_mode=debug_mode,
            show_message=show_message,
            show_reasoning=show_reasoning,
            show_full_reasoning=show_full_reasoning,
            show_member_responses=show_member_responses,
            console=console,
            tags_to_include_in_markdown=tags_to_include_in_markdown,
            **kwargs,
        )

    def _get_member_name(self, entity_id: str) -> str:
        return _cli._get_member_name(self, entity_id=entity_id)

    def scrub_run_output_for_storage(self, run_response: TeamRunOutput) -> bool:
        return _run.scrub_run_output_for_storage(self, run_response=run_response)

    def _scrub_member_responses(self, member_responses: List[Union[TeamRunOutput, RunOutput]]) -> None:
        return _run._scrub_member_responses(self, member_responses=member_responses)

    def cli_app(
        self,
        input: Optional[str] = None,
        user: str = "User",
        emoji: str = ":sunglasses:",
        stream: bool = False,
        markdown: bool = False,
        exit_on: Optional[List[str]] = None,
        **kwargs: Any,
    ) -> None:
        return _cli.cli_app(
            self, input=input, user=user, emoji=emoji, stream=stream, markdown=markdown, exit_on=exit_on, **kwargs
        )

    async def acli_app(
        self,
        input: Optional[str] = None,
        session_id: Optional[str] = None,
        user_id: Optional[str] = None,
        user: str = "User",
        emoji: str = ":sunglasses:",
        stream: bool = False,
        markdown: bool = False,
        exit_on: Optional[List[str]] = None,
        **kwargs: Any,
    ) -> None:
        return await _cli.acli_app(
            self,
            input=input,
            session_id=session_id,
            user_id=user_id,
            user=user,
            emoji=emoji,
            stream=stream,
            markdown=markdown,
            exit_on=exit_on,
            **kwargs,
        )

    ###########################################################################
    # Helpers
    ###########################################################################

    def _calculate_metrics(
        self, messages: List[Message], current_run_metrics: Optional[RunMetrics] = None
    ) -> RunMetrics:
        # Metrics are now accumulated immediately during model calls
        return current_run_metrics or RunMetrics()

    def _update_session_metrics(self, session: TeamSession, run_response: TeamRunOutput):
        _session.update_session_metrics(self, session, run_response)

    def _determine_tools_for_model(
        self,
        model: Model,
        run_response: TeamRunOutput,
        run_context: RunContext,
        team_run_context: Dict[str, Any],
        session: TeamSession,
        user_id: Optional[str] = None,
        async_mode: bool = False,
        input_message: Optional[Union[str, List, Dict, Message, BaseModel, List[Message]]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        audio: Optional[Sequence[Audio]] = None,
        files: Optional[Sequence[File]] = None,
        debug_mode: Optional[bool] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        stream: Optional[bool] = None,
        stream_events: Optional[bool] = None,
        check_mcp_tools: bool = True,
    ) -> List[Union[Function, dict]]:
        # Connect tools that require connection management
        return _tools._determine_tools_for_model(
            self,
            model=model,
            run_response=run_response,
            run_context=run_context,
            team_run_context=team_run_context,
            session=session,
            user_id=user_id,
            async_mode=async_mode,
            input_message=input_message,
            images=images,
            videos=videos,
            audio=audio,
            files=files,
            debug_mode=debug_mode,
            add_history_to_context=add_history_to_context,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            stream=stream,
            stream_events=stream_events,
            check_mcp_tools=check_mcp_tools,
        )

    def get_members_system_message_content(self, indent: int = 0, run_context: Optional[RunContext] = None) -> str:
        return _messages.get_members_system_message_content(self, indent=indent, run_context=run_context)

    def get_system_message(
        self,
        session: TeamSession,
        run_context: Optional[RunContext] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        tools: Optional[List[Union[Function, dict]]] = None,
        add_session_state_to_context: Optional[bool] = None,
    ) -> Optional[Message]:
        return _messages.get_system_message(
            self,
            session=session,
            run_context=run_context,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            tools=tools,
            add_session_state_to_context=add_session_state_to_context,
        )

    async def aget_system_message(
        self,
        session: TeamSession,
        run_context: Optional[RunContext] = None,
        audio: Optional[Sequence[Audio]] = None,
        images: Optional[Sequence[Image]] = None,
        videos: Optional[Sequence[Video]] = None,
        files: Optional[Sequence[File]] = None,
        tools: Optional[List[Union[Function, dict]]] = None,
        add_session_state_to_context: Optional[bool] = None,
    ) -> Optional[Message]:
        return await _messages.aget_system_message(
            self,
            session=session,
            run_context=run_context,
            audio=audio,
            images=images,
            videos=videos,
            files=files,
            tools=tools,
            add_session_state_to_context=add_session_state_to_context,
        )

    ###########################################################################
    # Built-in Tools
    ###########################################################################

    def get_member_information(self, run_context: Optional[RunContext] = None) -> str:
        return _tools.get_member_information(self, run_context=run_context)

    def _find_member_by_id(
        self, member_id: str, run_context: Optional[RunContext] = None
    ) -> Optional[Tuple[int, Union[Agent, "Team"]]]:
        return _tools._find_member_by_id(self, member_id=member_id, run_context=run_context)

    def _find_member_route_by_id(
        self, member_id: str, run_context: Optional[RunContext] = None
    ) -> Optional[Tuple[int, Union[Agent, "Team"]]]:
        return _tools._find_member_route_by_id(self, member_id=member_id, run_context=run_context)

    def _get_delegate_task_function(
        self,
        run_response: TeamRunOutput,
        run_context: RunContext,
        session: TeamSession,
        team_run_context: Dict[str, Any],
        user_id: Optional[str] = None,
        stream: bool = False,
        stream_events: bool = False,
        async_mode: bool = False,
        input: Optional[str] = None,  # Used for determine_input_for_members=False
        images: Optional[List[Image]] = None,
        videos: Optional[List[Video]] = None,
        audio: Optional[List[Audio]] = None,
        files: Optional[List[File]] = None,
        add_history_to_context: Optional[bool] = None,
        add_dependencies_to_context: Optional[bool] = None,
        add_session_state_to_context: Optional[bool] = None,
        debug_mode: Optional[bool] = None,
    ) -> Function:
        return _default_tools._get_delegate_task_function(
            self,
            run_response=run_response,
            run_context=run_context,
            session=session,
            team_run_context=team_run_context,
            user_id=user_id,
            stream=stream,
            stream_events=stream_events,
            async_mode=async_mode,
            input=input,
            images=images,
            videos=videos,
            audio=audio,
            files=files,
            add_history_to_context=add_history_to_context,
            add_dependencies_to_context=add_dependencies_to_context,
            add_session_state_to_context=add_session_state_to_context,
            debug_mode=debug_mode,
        )

    ###########################################################################
    # Session Management
    ###########################################################################

    # -*- Serialization Functions
    def to_dict(self) -> Dict[str, Any]:
        return _storage.to_dict(self)

    @classmethod
    def from_dict(
        cls,
        data: Dict[str, Any],
        db: Optional["BaseDb"] = None,
        registry: Optional["Registry"] = None,
    ) -> "Team":
        return _storage.from_dict(cls, data=data, db=db, registry=registry)

    def save(
        self,
        *,
        db: Optional["BaseDb"] = None,
        stage: str = "published",
        label: Optional[str] = None,
        notes: Optional[str] = None,
    ) -> Optional[int]:
        return _storage.save(self, db=db, stage=stage, label=label, notes=notes)

    @classmethod
    def load(
        cls,
        id: str,
        *,
        db: "BaseDb",
        registry: Optional["Registry"] = None,
        label: Optional[str] = None,
        version: Optional[int] = None,
    ) -> Optional["Team"]:
        return _storage.load(cls, id=id, db=db, registry=registry, label=label, version=version)

    def delete(
        self,
        *,
        db: Optional["BaseDb"] = None,
        hard_delete: bool = False,
    ) -> bool:
        return _storage.delete(self, db=db, hard_delete=hard_delete)

    # -*- Public convenience functions
    def get_run_output(
        self, run_id: str, session_id: Optional[str] = None
    ) -> Optional[Union[TeamRunOutput, RunOutput]]:
        return _storage.get_run_output(self, run_id=run_id, session_id=session_id)

    async def aget_run_output(
        self, run_id: str, session_id: Optional[str] = None
    ) -> Optional[Union[TeamRunOutput, RunOutput]]:
        return await _storage.aget_run_output(self, run_id=run_id, session_id=session_id)

    def get_last_run_output(self, session_id: Optional[str] = None) -> Optional[TeamRunOutput]:
        return _storage.get_last_run_output(self, session_id=session_id)

    async def aget_last_run_output(self, session_id: Optional[str] = None) -> Optional[TeamRunOutput]:
        return await _storage.aget_last_run_output(self, session_id=session_id)

    def get_session(
        self,
        session_id: Optional[str] = None,
        user_id: Optional[str] = None,
    ) -> Optional[TeamSession]:
        return _session.get_session(self, session_id=session_id, user_id=user_id)

    async def aget_session(
        self,
        session_id: Optional[str] = None,
        user_id: Optional[str] = None,
    ) -> Optional[TeamSession]:
        return await _session.aget_session(self, session_id=session_id, user_id=user_id)

    def save_session(self, session: TeamSession) -> None:
        return _session.save_session(self, session=session)

    async def asave_session(self, session: TeamSession) -> None:
        return await _session.asave_session(self, session=session)

    def generate_session_name(self, session: TeamSession) -> str:
        return _session.generate_session_name(self, session=session)

    def set_session_name(
        self, session_id: Optional[str] = None, autogenerate: bool = False, session_name: Optional[str] = None
    ) -> TeamSession:
        return _session.set_session_name(
            self, session_id=session_id, autogenerate=autogenerate, session_name=session_name
        )

    async def aset_session_name(
        self, session_id: Optional[str] = None, autogenerate: bool = False, session_name: Optional[str] = None
    ) -> TeamSession:
        return await _session.aset_session_name(
            self, session_id=session_id, autogenerate=autogenerate, session_name=session_name
        )

    def get_session_name(self, session_id: Optional[str] = None) -> str:
        return _session.get_session_name(self, session_id=session_id)

    async def aget_session_name(self, session_id: Optional[str] = None) -> str:
        return await _session.aget_session_name(self, session_id=session_id)

    def get_session_state(self, session_id: Optional[str] = None) -> Dict[str, Any]:
        return _session.get_session_state(self, session_id=session_id)

    async def aget_session_state(self, session_id: Optional[str] = None) -> Dict[str, Any]:
        return await _session.aget_session_state(self, session_id=session_id)

    def update_session_state(self, session_state_updates: Dict[str, Any], session_id: Optional[str] = None) -> str:
        return _session.update_session_state(self, session_state_updates=session_state_updates, session_id=session_id)

    async def aupdate_session_state(
        self, session_state_updates: Dict[str, Any], session_id: Optional[str] = None
    ) -> str:
        return await _session.aupdate_session_state(
            self, session_state_updates=session_state_updates, session_id=session_id
        )

    def get_session_metrics(self, session_id: Optional[str] = None) -> Optional[SessionMetrics]:
        return _session.get_session_metrics(self, session_id=session_id)

    async def aget_session_metrics(self, session_id: Optional[str] = None) -> Optional[SessionMetrics]:
        return await _session.aget_session_metrics(self, session_id=session_id)

    def delete_session(self, session_id: str, user_id: Optional[str] = None):
        return _session.delete_session(self, session_id=session_id, user_id=user_id)

    async def adelete_session(self, session_id: str, user_id: Optional[str] = None):
        return await _session.adelete_session(self, session_id=session_id, user_id=user_id)

    def get_session_messages(
        self,
        session_id: Optional[str] = None,
        member_ids: Optional[List[str]] = None,
        last_n_runs: Optional[int] = None,
        limit: Optional[int] = None,
        skip_roles: Optional[List[str]] = None,
        skip_statuses: Optional[List[RunStatus]] = None,
        skip_history_messages: bool = True,
        skip_member_messages: bool = True,
    ) -> List[Message]:
        return _session.get_session_messages(
            self,
            session_id=session_id,
            member_ids=member_ids,
            last_n_runs=last_n_runs,
            limit=limit,
            skip_roles=skip_roles,
            skip_statuses=skip_statuses,
            skip_history_messages=skip_history_messages,
            skip_member_messages=skip_member_messages,
        )

    async def aget_session_messages(
        self,
        session_id: Optional[str] = None,
        member_ids: Optional[List[str]] = None,
        last_n_runs: Optional[int] = None,
        limit: Optional[int] = None,
        skip_roles: Optional[List[str]] = None,
        skip_statuses: Optional[List[RunStatus]] = None,
        skip_history_messages: bool = True,
        skip_member_messages: bool = True,
    ) -> List[Message]:
        return await _session.aget_session_messages(
            self,
            session_id=session_id,
            member_ids=member_ids,
            last_n_runs=last_n_runs,
            limit=limit,
            skip_roles=skip_roles,
            skip_statuses=skip_statuses,
            skip_history_messages=skip_history_messages,
            skip_member_messages=skip_member_messages,
        )

    def get_chat_history(self, session_id: Optional[str] = None, last_n_runs: Optional[int] = None) -> List[Message]:
        return _session.get_chat_history(self, session_id=session_id, last_n_runs=last_n_runs)

    async def aget_chat_history(
        self, session_id: Optional[str] = None, last_n_runs: Optional[int] = None
    ) -> List[Message]:
        return await _session.aget_chat_history(self, session_id=session_id, last_n_runs=last_n_runs)

    def get_session_summary(self, session_id: Optional[str] = None) -> Optional[SessionSummary]:
        return _session.get_session_summary(self, session_id=session_id)

    async def aget_session_summary(self, session_id: Optional[str] = None) -> Optional[SessionSummary]:
        return await _session.aget_session_summary(self, session_id=session_id)

    def get_user_memories(self, user_id: Optional[str] = None) -> Optional[List[UserMemory]]:
        return _managers.get_user_memories(self, user_id=user_id)

    async def aget_user_memories(self, user_id: Optional[str] = None) -> Optional[List[UserMemory]]:
        return await _managers.aget_user_memories(self, user_id=user_id)

    ###########################################################################
    # Knowledge
    ###########################################################################

    def add_to_knowledge(self, query: str, result: str) -> str:
        return _default_tools.add_to_knowledge(self, query=query, result=result)

    def get_relevant_docs_from_knowledge(
        self,
        query: str,
        num_documents: Optional[int] = None,
        filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        run_context: Optional[RunContext] = None,
        **kwargs,
    ) -> Optional[List[Union[Dict[str, Any], str]]]:
        return _default_tools.get_relevant_docs_from_knowledge(
            self, query=query, num_documents=num_documents, filters=filters, run_context=run_context, **kwargs
        )

    async def aget_relevant_docs_from_knowledge(
        self,
        query: str,
        num_documents: Optional[int] = None,
        filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
        run_context: Optional[RunContext] = None,
        **kwargs,
    ) -> Optional[List[Union[Dict[str, Any], str]]]:
        return await _default_tools.aget_relevant_docs_from_knowledge(
            self, query=query, num_documents=num_documents, filters=filters, run_context=run_context, **kwargs
        )

    ###########################################################################
    # Logging
    ###########################################################################

    def deep_copy(self, *, update: Optional[Dict[str, Any]] = None) -> "Team":
        return _utils.deep_copy(self, update=update)


def get_team_by_id(
    db: "BaseDb",
    id: str,
    version: Optional[int] = None,
    label: Optional[str] = None,
    registry: Optional["Registry"] = None,
) -> Optional["Team"]:
    """
    Get a Team by id from the database.

    Resolution order:
    - if version is provided: load that version
    - elif label is provided: load that labeled version
    - else: load component.current_version

    Args:
        db: Database handle.
        id: Team component_id.
        version: Optional integer config version.
        label: Optional version_label.
        registry: Optional Registry for reconstructing unserializable components.

    Returns:
        Team instance or None.
    """
    try:
        row = db.get_config(component_id=id, version=version, label=label)
        if row is None:
            return None

        cfg = row.get("config") if isinstance(row, dict) else None
        if cfg is None:
            raise ValueError(f"Invalid config found for team {id}")

        team = Team.from_dict(cfg, db=db, registry=registry)
        # Ensure team.id is set to the component_id
        team.id = id

        return team

    except Exception as e:
        log_error(f"Error loading Team {id} from database: {e}")
        return None


def get_teams(
    db: "BaseDb",
    registry: Optional["Registry"] = None,
    exclude_component_ids: Optional[Set[str]] = None,
) -> List["Team"]:
    """
    Get all teams from the database.

    Args:
        db: Database to load teams from
        registry: Optional registry for rehydrating tools
        exclude_component_ids: Component IDs to exclude from results.

    Returns:
        List of Team instances loaded from the database
    """
    teams: List[Team] = []
    try:
        components, _ = db.list_components(
            component_type=ComponentType.TEAM, exclude_component_ids=exclude_component_ids
        )
        for component in components:
            component_id = component["component_id"]
            config = db.get_config(component_id=component_id)
            if config is not None:
                team_config = config.get("config")
                if team_config is not None:
                    if "id" not in team_config:
                        team_config["id"] = component_id
                    team = Team.from_dict(team_config, db=db, registry=registry)
                    team.id = component_id
                    team._version = component.get("current_version")
                    team._stage = config.get("stage")
                    teams.append(team)
        return teams

    except Exception as e:
        log_error(f"Error loading Teams from database: {e}")
        return []
