# This file was auto-generated by Fern from our API Definition.

import typing
from ..core.client_wrapper import SyncClientWrapper
from .context.client import ContextClient
from .tools.client import ToolsClient
from .sources.client import SourcesClient
from .core_memory.client import CoreMemoryClient
from .blocks.client import BlocksClient
from .passages.client import PassagesClient
from .messages.client import MessagesClient
from .templates.client import TemplatesClient
from .memory_variables.client import MemoryVariablesClient
from ..core.request_options import RequestOptions
from ..types.agent_state import AgentState
from ..core.unchecked_base_model import construct_type
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.http_validation_error import HttpValidationError
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.create_block import CreateBlock
from .types.create_agent_request_tool_rules_item import CreateAgentRequestToolRulesItem
from ..types.agent_type import AgentType
from ..types.llm_config import LlmConfig
from ..types.embedding_config import EmbeddingConfig
from ..types.message_create import MessageCreate
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.jsonable_encoder import jsonable_encoder
from .. import core
from .types.update_agent_tool_rules_item import UpdateAgentToolRulesItem
import datetime as dt
from ..types.passage import Passage
from ..types.group import Group
from .types.agents_search_request_search_item import AgentsSearchRequestSearchItem
from .types.agents_search_response import AgentsSearchResponse
from ..core.client_wrapper import AsyncClientWrapper
from .context.client import AsyncContextClient
from .tools.client import AsyncToolsClient
from .sources.client import AsyncSourcesClient
from .core_memory.client import AsyncCoreMemoryClient
from .blocks.client import AsyncBlocksClient
from .passages.client import AsyncPassagesClient
from .messages.client import AsyncMessagesClient
from .templates.client import AsyncTemplatesClient
from .memory_variables.client import AsyncMemoryVariablesClient

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class AgentsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper
        self.context = ContextClient(client_wrapper=self._client_wrapper)
        self.tools = ToolsClient(client_wrapper=self._client_wrapper)
        self.sources = SourcesClient(client_wrapper=self._client_wrapper)
        self.core_memory = CoreMemoryClient(client_wrapper=self._client_wrapper)
        self.blocks = BlocksClient(client_wrapper=self._client_wrapper)
        self.passages = PassagesClient(client_wrapper=self._client_wrapper)
        self.messages = MessagesClient(client_wrapper=self._client_wrapper)
        self.templates = TemplatesClient(client_wrapper=self._client_wrapper)
        self.memory_variables = MemoryVariablesClient(client_wrapper=self._client_wrapper)

    def list(
        self,
        *,
        name: typing.Optional[str] = None,
        tags: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        match_all_tags: typing.Optional[bool] = None,
        before: typing.Optional[str] = None,
        after: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        query_text: typing.Optional[str] = None,
        project_id: typing.Optional[str] = None,
        template_id: typing.Optional[str] = None,
        base_template_id: typing.Optional[str] = None,
        identity_id: typing.Optional[str] = None,
        identifier_keys: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        include_relationships: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        ascending: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[AgentState]:
        """
        List all agents associated with a given user.

        This endpoint retrieves a list of all agents and their configurations
        associated with the specified user ID.

        Parameters
        ----------
        name : typing.Optional[str]
            Name of the agent

        tags : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            List of tags to filter agents by

        match_all_tags : typing.Optional[bool]
            If True, only returns agents that match ALL given tags. Otherwise, return agents that have ANY of the passed-in tags.

        before : typing.Optional[str]
            Cursor for pagination

        after : typing.Optional[str]
            Cursor for pagination

        limit : typing.Optional[int]
            Limit for pagination

        query_text : typing.Optional[str]
            Search agents by name

        project_id : typing.Optional[str]
            Search agents by project ID

        template_id : typing.Optional[str]
            Search agents by template ID

        base_template_id : typing.Optional[str]
            Search agents by base template ID

        identity_id : typing.Optional[str]
            Search agents by identity ID

        identifier_keys : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Search agents by identifier keys

        include_relationships : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Specify which relational fields (e.g., 'tools', 'sources', 'memory') to include in the response. If not provided, all relationships are loaded by default. Using this can optimize performance by reducing unnecessary joins.

        ascending : typing.Optional[bool]
            Whether to sort agents oldest to newest (True) or newest to oldest (False, default)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[AgentState]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.list()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/agents/",
            method="GET",
            params={
                "name": name,
                "tags": tags,
                "match_all_tags": match_all_tags,
                "before": before,
                "after": after,
                "limit": limit,
                "query_text": query_text,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_id": identity_id,
                "identifier_keys": identifier_keys,
                "include_relationships": include_relationships,
                "ascending": ascending,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[AgentState],
                    construct_type(
                        type_=typing.List[AgentState],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(
        self,
        *,
        project: typing.Optional[str] = None,
        name: typing.Optional[str] = OMIT,
        memory_blocks: typing.Optional[typing.Sequence[CreateBlock]] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tool_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        source_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        block_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        tool_rules: typing.Optional[typing.Sequence[CreateAgentRequestToolRulesItem]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        system: typing.Optional[str] = OMIT,
        agent_type: typing.Optional[AgentType] = OMIT,
        llm_config: typing.Optional[LlmConfig] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        initial_message_sequence: typing.Optional[typing.Sequence[MessageCreate]] = OMIT,
        include_base_tools: typing.Optional[bool] = OMIT,
        include_multi_agent_tools: typing.Optional[bool] = OMIT,
        include_base_tool_rules: typing.Optional[bool] = OMIT,
        description: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        model: typing.Optional[str] = OMIT,
        embedding: typing.Optional[str] = OMIT,
        context_window_limit: typing.Optional[int] = OMIT,
        embedding_chunk_size: typing.Optional[int] = OMIT,
        max_tokens: typing.Optional[int] = OMIT,
        max_reasoning_tokens: typing.Optional[int] = OMIT,
        enable_reasoner: typing.Optional[bool] = OMIT,
        from_template: typing.Optional[str] = OMIT,
        template: typing.Optional[bool] = OMIT,
        create_agent_request_project: typing.Optional[str] = OMIT,
        tool_exec_environment_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        memory_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        template_id: typing.Optional[str] = OMIT,
        base_template_id: typing.Optional[str] = OMIT,
        identity_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        message_buffer_autoclear: typing.Optional[bool] = OMIT,
        enable_sleeptime: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Create a new agent with the specified configuration.

        Parameters
        ----------
        project : typing.Optional[str]

        name : typing.Optional[str]
            The name of the agent.

        memory_blocks : typing.Optional[typing.Sequence[CreateBlock]]
            The blocks to create in the agent's in-context memory.

        tools : typing.Optional[typing.Sequence[str]]
            The tools used by the agent.

        tool_ids : typing.Optional[typing.Sequence[str]]
            The ids of the tools used by the agent.

        source_ids : typing.Optional[typing.Sequence[str]]
            The ids of the sources used by the agent.

        block_ids : typing.Optional[typing.Sequence[str]]
            The ids of the blocks used by the agent.

        tool_rules : typing.Optional[typing.Sequence[CreateAgentRequestToolRulesItem]]
            The tool rules governing the agent.

        tags : typing.Optional[typing.Sequence[str]]
            The tags associated with the agent.

        system : typing.Optional[str]
            The system prompt used by the agent.

        agent_type : typing.Optional[AgentType]
            The type of agent.

        llm_config : typing.Optional[LlmConfig]
            The LLM configuration used by the agent.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the agent.

        initial_message_sequence : typing.Optional[typing.Sequence[MessageCreate]]
            The initial set of messages to put in the agent's in-context memory.

        include_base_tools : typing.Optional[bool]
            If true, attaches the Letta core tools (e.g. archival_memory and core_memory related functions).

        include_multi_agent_tools : typing.Optional[bool]
            If true, attaches the Letta multi-agent tools (e.g. sending a message to another agent).

        include_base_tool_rules : typing.Optional[bool]
            If true, attaches the Letta base tool rules (e.g. deny all tools not explicitly allowed).

        description : typing.Optional[str]
            The description of the agent.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the agent.

        model : typing.Optional[str]
            The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config.

        embedding : typing.Optional[str]
            The embedding configuration handle used by the agent, specified in the format provider/model-name.

        context_window_limit : typing.Optional[int]
            The context window limit used by the agent.

        embedding_chunk_size : typing.Optional[int]
            The embedding chunk size used by the agent.

        max_tokens : typing.Optional[int]
            The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value.

        max_reasoning_tokens : typing.Optional[int]
            The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value.

        enable_reasoner : typing.Optional[bool]
            Whether to enable internal extended thinking step for a reasoner model.

        from_template : typing.Optional[str]
            The template id used to configure the agent

        template : typing.Optional[bool]
            Whether the agent is a template

        create_agent_request_project : typing.Optional[str]
            Deprecated: Project should now be passed via the X-Project header instead of in the request body. If using the sdk, this can be done via the new x_project field below.

        tool_exec_environment_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The environment variables for tool execution specific to this agent.

        memory_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The variables that should be set for the agent.

        project_id : typing.Optional[str]
            The id of the project the agent belongs to.

        template_id : typing.Optional[str]
            The id of the template the agent belongs to.

        base_template_id : typing.Optional[str]
            The base template id of the agent.

        identity_ids : typing.Optional[typing.Sequence[str]]
            The ids of the identities associated with this agent.

        message_buffer_autoclear : typing.Optional[bool]
            If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.

        enable_sleeptime : typing.Optional[bool]
            If set to True, memory management will move to a background agent thread.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.create()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/agents/",
            method="POST",
            json={
                "name": name,
                "memory_blocks": convert_and_respect_annotation_metadata(
                    object_=memory_blocks, annotation=typing.Sequence[CreateBlock], direction="write"
                ),
                "tools": tools,
                "tool_ids": tool_ids,
                "source_ids": source_ids,
                "block_ids": block_ids,
                "tool_rules": convert_and_respect_annotation_metadata(
                    object_=tool_rules, annotation=typing.Sequence[CreateAgentRequestToolRulesItem], direction="write"
                ),
                "tags": tags,
                "system": system,
                "agent_type": agent_type,
                "llm_config": convert_and_respect_annotation_metadata(
                    object_=llm_config, annotation=LlmConfig, direction="write"
                ),
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "initial_message_sequence": convert_and_respect_annotation_metadata(
                    object_=initial_message_sequence, annotation=typing.Sequence[MessageCreate], direction="write"
                ),
                "include_base_tools": include_base_tools,
                "include_multi_agent_tools": include_multi_agent_tools,
                "include_base_tool_rules": include_base_tool_rules,
                "description": description,
                "metadata": metadata,
                "model": model,
                "embedding": embedding,
                "context_window_limit": context_window_limit,
                "embedding_chunk_size": embedding_chunk_size,
                "max_tokens": max_tokens,
                "max_reasoning_tokens": max_reasoning_tokens,
                "enable_reasoner": enable_reasoner,
                "from_template": from_template,
                "template": template,
                "project": create_agent_request_project,
                "tool_exec_environment_variables": tool_exec_environment_variables,
                "memory_variables": memory_variables,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_ids": identity_ids,
                "message_buffer_autoclear": message_buffer_autoclear,
                "enable_sleeptime": enable_sleeptime,
            },
            headers={
                "content-type": "application/json",
                "X-Project": str(project) if project is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def export_agent_serialized(self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> str:
        """
        Export the serialized JSON representation of an agent, formatted with indentation.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        str
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.export_agent_serialized(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/export",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    str,
                    construct_type(
                        type_=str,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def import_agent_serialized(
        self,
        *,
        file: core.File,
        append_copy_suffix: typing.Optional[bool] = None,
        override_existing_tools: typing.Optional[bool] = None,
        project_id: typing.Optional[str] = None,
        strip_messages: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Import a serialized agent file and recreate the agent in the system.

        Parameters
        ----------
        file : core.File
            See core.File for more documentation

        append_copy_suffix : typing.Optional[bool]
            If set to True, appends "_copy" to the end of the agent name.

        override_existing_tools : typing.Optional[bool]
            If set to True, existing tools can get their source code overwritten by the uploaded tool definitions. Note that Letta core tools can never be updated externally.

        project_id : typing.Optional[str]
            The project ID to associate the uploaded agent with.

        strip_messages : typing.Optional[bool]
            If set to True, strips all messages from the agent before importing.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.import_agent_serialized()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/agents/import",
            method="POST",
            params={
                "append_copy_suffix": append_copy_suffix,
                "override_existing_tools": override_existing_tools,
                "project_id": project_id,
                "strip_messages": strip_messages,
            },
            data={},
            files={
                "file": file,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def retrieve(self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentState:
        """
        Get the state of the agent.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.retrieve(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Delete an agent.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.delete(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Optional[typing.Any],
                    construct_type(
                        type_=typing.Optional[typing.Any],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def modify(
        self,
        agent_id: str,
        *,
        name: typing.Optional[str] = OMIT,
        tool_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        source_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        block_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        system: typing.Optional[str] = OMIT,
        tool_rules: typing.Optional[typing.Sequence[UpdateAgentToolRulesItem]] = OMIT,
        llm_config: typing.Optional[LlmConfig] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        message_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        description: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        tool_exec_environment_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        template_id: typing.Optional[str] = OMIT,
        base_template_id: typing.Optional[str] = OMIT,
        identity_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        message_buffer_autoclear: typing.Optional[bool] = OMIT,
        model: typing.Optional[str] = OMIT,
        embedding: typing.Optional[str] = OMIT,
        enable_sleeptime: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Update an existing agent

        Parameters
        ----------
        agent_id : str

        name : typing.Optional[str]
            The name of the agent.

        tool_ids : typing.Optional[typing.Sequence[str]]
            The ids of the tools used by the agent.

        source_ids : typing.Optional[typing.Sequence[str]]
            The ids of the sources used by the agent.

        block_ids : typing.Optional[typing.Sequence[str]]
            The ids of the blocks used by the agent.

        tags : typing.Optional[typing.Sequence[str]]
            The tags associated with the agent.

        system : typing.Optional[str]
            The system prompt used by the agent.

        tool_rules : typing.Optional[typing.Sequence[UpdateAgentToolRulesItem]]
            The tool rules governing the agent.

        llm_config : typing.Optional[LlmConfig]
            The LLM configuration used by the agent.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the agent.

        message_ids : typing.Optional[typing.Sequence[str]]
            The ids of the messages in the agent's in-context memory.

        description : typing.Optional[str]
            The description of the agent.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the agent.

        tool_exec_environment_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The environment variables for tool execution specific to this agent.

        project_id : typing.Optional[str]
            The id of the project the agent belongs to.

        template_id : typing.Optional[str]
            The id of the template the agent belongs to.

        base_template_id : typing.Optional[str]
            The base template id of the agent.

        identity_ids : typing.Optional[typing.Sequence[str]]
            The ids of the identities associated with this agent.

        message_buffer_autoclear : typing.Optional[bool]
            If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.

        model : typing.Optional[str]
            The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config.

        embedding : typing.Optional[str]
            The embedding configuration handle used by the agent, specified in the format provider/model-name.

        enable_sleeptime : typing.Optional[bool]
            If set to True, memory management will move to a background agent thread.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.modify(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="PATCH",
            json={
                "name": name,
                "tool_ids": tool_ids,
                "source_ids": source_ids,
                "block_ids": block_ids,
                "tags": tags,
                "system": system,
                "tool_rules": convert_and_respect_annotation_metadata(
                    object_=tool_rules, annotation=typing.Sequence[UpdateAgentToolRulesItem], direction="write"
                ),
                "llm_config": convert_and_respect_annotation_metadata(
                    object_=llm_config, annotation=LlmConfig, direction="write"
                ),
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "message_ids": message_ids,
                "description": description,
                "metadata": metadata,
                "tool_exec_environment_variables": tool_exec_environment_variables,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_ids": identity_ids,
                "message_buffer_autoclear": message_buffer_autoclear,
                "model": model,
                "embedding": embedding,
                "enable_sleeptime": enable_sleeptime,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def modify_passage(
        self,
        agent_id: str,
        memory_id: str,
        *,
        id: str,
        created_by_id: typing.Optional[str] = OMIT,
        last_updated_by_id: typing.Optional[str] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        is_deleted: typing.Optional[bool] = OMIT,
        passage_update_agent_id: typing.Optional[str] = OMIT,
        source_id: typing.Optional[str] = OMIT,
        file_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        text: typing.Optional[str] = OMIT,
        embedding: typing.Optional[typing.Sequence[float]] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Modify a memory in the agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        memory_id : str

        id : str
            The unique identifier of the passage.

        created_by_id : typing.Optional[str]
            The id of the user that made this object.

        last_updated_by_id : typing.Optional[str]
            The id of the user that made this object.

        created_at : typing.Optional[dt.datetime]
            The timestamp when the object was created.

        updated_at : typing.Optional[dt.datetime]
            The timestamp when the object was last updated.

        is_deleted : typing.Optional[bool]
            Whether this passage is deleted or not.

        passage_update_agent_id : typing.Optional[str]
            The unique identifier of the agent associated with the passage.

        source_id : typing.Optional[str]
            The data source of the passage.

        file_id : typing.Optional[str]
            The unique identifier of the file associated with the passage.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the passage.

        text : typing.Optional[str]
            The text of the passage.

        embedding : typing.Optional[typing.Sequence[float]]
            The embedding of the passage.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the passage.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.modify_passage(
            agent_id="agent_id",
            memory_id="memory_id",
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/archival-memory/{jsonable_encoder(memory_id)}",
            method="PATCH",
            json={
                "created_by_id": created_by_id,
                "last_updated_by_id": last_updated_by_id,
                "created_at": created_at,
                "updated_at": updated_at,
                "is_deleted": is_deleted,
                "agent_id": passage_update_agent_id,
                "source_id": source_id,
                "file_id": file_id,
                "metadata_": metadata,
                "text": text,
                "embedding": embedding,
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "id": id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Passage],
                    construct_type(
                        type_=typing.List[Passage],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def reset_messages(
        self,
        agent_id: str,
        *,
        add_default_initial_messages: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Resets the messages for an agent

        Parameters
        ----------
        agent_id : str

        add_default_initial_messages : typing.Optional[bool]
            If true, adds the default initial messages after resetting.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.reset_messages(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/reset-messages",
            method="PATCH",
            params={
                "add_default_initial_messages": add_default_initial_messages,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def list_agent_groups(
        self,
        agent_id: str,
        *,
        manager_type: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Group]:
        """
        Lists the groups for an agent

        Parameters
        ----------
        agent_id : str

        manager_type : typing.Optional[str]
            Manager type to filter groups by

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Group]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.list_agent_groups(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/groups",
            method="GET",
            params={
                "manager_type": manager_type,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Group],
                    construct_type(
                        type_=typing.List[Group],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def search(
        self,
        *,
        search: typing.Optional[typing.Sequence[AgentsSearchRequestSearchItem]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        combinator: typing.Optional[typing.Literal["AND"]] = OMIT,
        limit: typing.Optional[float] = OMIT,
        after: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentsSearchResponse:
        """
        <Note>This endpoint is only available on Letta Cloud.</Note>

        Search deployed agents.

        Parameters
        ----------
        search : typing.Optional[typing.Sequence[AgentsSearchRequestSearchItem]]

        project_id : typing.Optional[str]

        combinator : typing.Optional[typing.Literal["AND"]]

        limit : typing.Optional[float]

        after : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentsSearchResponse
            200

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            token="YOUR_TOKEN",
        )
        client.agents.search()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/agents/search",
            method="POST",
            json={
                "search": convert_and_respect_annotation_metadata(
                    object_=search, annotation=typing.Sequence[AgentsSearchRequestSearchItem], direction="write"
                ),
                "project_id": project_id,
                "combinator": combinator,
                "limit": limit,
                "after": after,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentsSearchResponse,
                    construct_type(
                        type_=AgentsSearchResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncAgentsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper
        self.context = AsyncContextClient(client_wrapper=self._client_wrapper)
        self.tools = AsyncToolsClient(client_wrapper=self._client_wrapper)
        self.sources = AsyncSourcesClient(client_wrapper=self._client_wrapper)
        self.core_memory = AsyncCoreMemoryClient(client_wrapper=self._client_wrapper)
        self.blocks = AsyncBlocksClient(client_wrapper=self._client_wrapper)
        self.passages = AsyncPassagesClient(client_wrapper=self._client_wrapper)
        self.messages = AsyncMessagesClient(client_wrapper=self._client_wrapper)
        self.templates = AsyncTemplatesClient(client_wrapper=self._client_wrapper)
        self.memory_variables = AsyncMemoryVariablesClient(client_wrapper=self._client_wrapper)

    async def list(
        self,
        *,
        name: typing.Optional[str] = None,
        tags: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        match_all_tags: typing.Optional[bool] = None,
        before: typing.Optional[str] = None,
        after: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        query_text: typing.Optional[str] = None,
        project_id: typing.Optional[str] = None,
        template_id: typing.Optional[str] = None,
        base_template_id: typing.Optional[str] = None,
        identity_id: typing.Optional[str] = None,
        identifier_keys: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        include_relationships: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        ascending: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[AgentState]:
        """
        List all agents associated with a given user.

        This endpoint retrieves a list of all agents and their configurations
        associated with the specified user ID.

        Parameters
        ----------
        name : typing.Optional[str]
            Name of the agent

        tags : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            List of tags to filter agents by

        match_all_tags : typing.Optional[bool]
            If True, only returns agents that match ALL given tags. Otherwise, return agents that have ANY of the passed-in tags.

        before : typing.Optional[str]
            Cursor for pagination

        after : typing.Optional[str]
            Cursor for pagination

        limit : typing.Optional[int]
            Limit for pagination

        query_text : typing.Optional[str]
            Search agents by name

        project_id : typing.Optional[str]
            Search agents by project ID

        template_id : typing.Optional[str]
            Search agents by template ID

        base_template_id : typing.Optional[str]
            Search agents by base template ID

        identity_id : typing.Optional[str]
            Search agents by identity ID

        identifier_keys : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Search agents by identifier keys

        include_relationships : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Specify which relational fields (e.g., 'tools', 'sources', 'memory') to include in the response. If not provided, all relationships are loaded by default. Using this can optimize performance by reducing unnecessary joins.

        ascending : typing.Optional[bool]
            Whether to sort agents oldest to newest (True) or newest to oldest (False, default)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[AgentState]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.list()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/agents/",
            method="GET",
            params={
                "name": name,
                "tags": tags,
                "match_all_tags": match_all_tags,
                "before": before,
                "after": after,
                "limit": limit,
                "query_text": query_text,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_id": identity_id,
                "identifier_keys": identifier_keys,
                "include_relationships": include_relationships,
                "ascending": ascending,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[AgentState],
                    construct_type(
                        type_=typing.List[AgentState],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(
        self,
        *,
        project: typing.Optional[str] = None,
        name: typing.Optional[str] = OMIT,
        memory_blocks: typing.Optional[typing.Sequence[CreateBlock]] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tool_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        source_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        block_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        tool_rules: typing.Optional[typing.Sequence[CreateAgentRequestToolRulesItem]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        system: typing.Optional[str] = OMIT,
        agent_type: typing.Optional[AgentType] = OMIT,
        llm_config: typing.Optional[LlmConfig] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        initial_message_sequence: typing.Optional[typing.Sequence[MessageCreate]] = OMIT,
        include_base_tools: typing.Optional[bool] = OMIT,
        include_multi_agent_tools: typing.Optional[bool] = OMIT,
        include_base_tool_rules: typing.Optional[bool] = OMIT,
        description: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        model: typing.Optional[str] = OMIT,
        embedding: typing.Optional[str] = OMIT,
        context_window_limit: typing.Optional[int] = OMIT,
        embedding_chunk_size: typing.Optional[int] = OMIT,
        max_tokens: typing.Optional[int] = OMIT,
        max_reasoning_tokens: typing.Optional[int] = OMIT,
        enable_reasoner: typing.Optional[bool] = OMIT,
        from_template: typing.Optional[str] = OMIT,
        template: typing.Optional[bool] = OMIT,
        create_agent_request_project: typing.Optional[str] = OMIT,
        tool_exec_environment_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        memory_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        template_id: typing.Optional[str] = OMIT,
        base_template_id: typing.Optional[str] = OMIT,
        identity_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        message_buffer_autoclear: typing.Optional[bool] = OMIT,
        enable_sleeptime: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Create a new agent with the specified configuration.

        Parameters
        ----------
        project : typing.Optional[str]

        name : typing.Optional[str]
            The name of the agent.

        memory_blocks : typing.Optional[typing.Sequence[CreateBlock]]
            The blocks to create in the agent's in-context memory.

        tools : typing.Optional[typing.Sequence[str]]
            The tools used by the agent.

        tool_ids : typing.Optional[typing.Sequence[str]]
            The ids of the tools used by the agent.

        source_ids : typing.Optional[typing.Sequence[str]]
            The ids of the sources used by the agent.

        block_ids : typing.Optional[typing.Sequence[str]]
            The ids of the blocks used by the agent.

        tool_rules : typing.Optional[typing.Sequence[CreateAgentRequestToolRulesItem]]
            The tool rules governing the agent.

        tags : typing.Optional[typing.Sequence[str]]
            The tags associated with the agent.

        system : typing.Optional[str]
            The system prompt used by the agent.

        agent_type : typing.Optional[AgentType]
            The type of agent.

        llm_config : typing.Optional[LlmConfig]
            The LLM configuration used by the agent.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the agent.

        initial_message_sequence : typing.Optional[typing.Sequence[MessageCreate]]
            The initial set of messages to put in the agent's in-context memory.

        include_base_tools : typing.Optional[bool]
            If true, attaches the Letta core tools (e.g. archival_memory and core_memory related functions).

        include_multi_agent_tools : typing.Optional[bool]
            If true, attaches the Letta multi-agent tools (e.g. sending a message to another agent).

        include_base_tool_rules : typing.Optional[bool]
            If true, attaches the Letta base tool rules (e.g. deny all tools not explicitly allowed).

        description : typing.Optional[str]
            The description of the agent.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the agent.

        model : typing.Optional[str]
            The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config.

        embedding : typing.Optional[str]
            The embedding configuration handle used by the agent, specified in the format provider/model-name.

        context_window_limit : typing.Optional[int]
            The context window limit used by the agent.

        embedding_chunk_size : typing.Optional[int]
            The embedding chunk size used by the agent.

        max_tokens : typing.Optional[int]
            The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value.

        max_reasoning_tokens : typing.Optional[int]
            The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value.

        enable_reasoner : typing.Optional[bool]
            Whether to enable internal extended thinking step for a reasoner model.

        from_template : typing.Optional[str]
            The template id used to configure the agent

        template : typing.Optional[bool]
            Whether the agent is a template

        create_agent_request_project : typing.Optional[str]
            Deprecated: Project should now be passed via the X-Project header instead of in the request body. If using the sdk, this can be done via the new x_project field below.

        tool_exec_environment_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The environment variables for tool execution specific to this agent.

        memory_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The variables that should be set for the agent.

        project_id : typing.Optional[str]
            The id of the project the agent belongs to.

        template_id : typing.Optional[str]
            The id of the template the agent belongs to.

        base_template_id : typing.Optional[str]
            The base template id of the agent.

        identity_ids : typing.Optional[typing.Sequence[str]]
            The ids of the identities associated with this agent.

        message_buffer_autoclear : typing.Optional[bool]
            If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.

        enable_sleeptime : typing.Optional[bool]
            If set to True, memory management will move to a background agent thread.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.create()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/agents/",
            method="POST",
            json={
                "name": name,
                "memory_blocks": convert_and_respect_annotation_metadata(
                    object_=memory_blocks, annotation=typing.Sequence[CreateBlock], direction="write"
                ),
                "tools": tools,
                "tool_ids": tool_ids,
                "source_ids": source_ids,
                "block_ids": block_ids,
                "tool_rules": convert_and_respect_annotation_metadata(
                    object_=tool_rules, annotation=typing.Sequence[CreateAgentRequestToolRulesItem], direction="write"
                ),
                "tags": tags,
                "system": system,
                "agent_type": agent_type,
                "llm_config": convert_and_respect_annotation_metadata(
                    object_=llm_config, annotation=LlmConfig, direction="write"
                ),
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "initial_message_sequence": convert_and_respect_annotation_metadata(
                    object_=initial_message_sequence, annotation=typing.Sequence[MessageCreate], direction="write"
                ),
                "include_base_tools": include_base_tools,
                "include_multi_agent_tools": include_multi_agent_tools,
                "include_base_tool_rules": include_base_tool_rules,
                "description": description,
                "metadata": metadata,
                "model": model,
                "embedding": embedding,
                "context_window_limit": context_window_limit,
                "embedding_chunk_size": embedding_chunk_size,
                "max_tokens": max_tokens,
                "max_reasoning_tokens": max_reasoning_tokens,
                "enable_reasoner": enable_reasoner,
                "from_template": from_template,
                "template": template,
                "project": create_agent_request_project,
                "tool_exec_environment_variables": tool_exec_environment_variables,
                "memory_variables": memory_variables,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_ids": identity_ids,
                "message_buffer_autoclear": message_buffer_autoclear,
                "enable_sleeptime": enable_sleeptime,
            },
            headers={
                "content-type": "application/json",
                "X-Project": str(project) if project is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def export_agent_serialized(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> str:
        """
        Export the serialized JSON representation of an agent, formatted with indentation.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        str
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.export_agent_serialized(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/export",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    str,
                    construct_type(
                        type_=str,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def import_agent_serialized(
        self,
        *,
        file: core.File,
        append_copy_suffix: typing.Optional[bool] = None,
        override_existing_tools: typing.Optional[bool] = None,
        project_id: typing.Optional[str] = None,
        strip_messages: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Import a serialized agent file and recreate the agent in the system.

        Parameters
        ----------
        file : core.File
            See core.File for more documentation

        append_copy_suffix : typing.Optional[bool]
            If set to True, appends "_copy" to the end of the agent name.

        override_existing_tools : typing.Optional[bool]
            If set to True, existing tools can get their source code overwritten by the uploaded tool definitions. Note that Letta core tools can never be updated externally.

        project_id : typing.Optional[str]
            The project ID to associate the uploaded agent with.

        strip_messages : typing.Optional[bool]
            If set to True, strips all messages from the agent before importing.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.import_agent_serialized()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/agents/import",
            method="POST",
            params={
                "append_copy_suffix": append_copy_suffix,
                "override_existing_tools": override_existing_tools,
                "project_id": project_id,
                "strip_messages": strip_messages,
            },
            data={},
            files={
                "file": file,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def retrieve(self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentState:
        """
        Get the state of the agent.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.retrieve(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Delete an agent.

        Parameters
        ----------
        agent_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.delete(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Optional[typing.Any],
                    construct_type(
                        type_=typing.Optional[typing.Any],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def modify(
        self,
        agent_id: str,
        *,
        name: typing.Optional[str] = OMIT,
        tool_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        source_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        block_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        system: typing.Optional[str] = OMIT,
        tool_rules: typing.Optional[typing.Sequence[UpdateAgentToolRulesItem]] = OMIT,
        llm_config: typing.Optional[LlmConfig] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        message_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        description: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        tool_exec_environment_variables: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        template_id: typing.Optional[str] = OMIT,
        base_template_id: typing.Optional[str] = OMIT,
        identity_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        message_buffer_autoclear: typing.Optional[bool] = OMIT,
        model: typing.Optional[str] = OMIT,
        embedding: typing.Optional[str] = OMIT,
        enable_sleeptime: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Update an existing agent

        Parameters
        ----------
        agent_id : str

        name : typing.Optional[str]
            The name of the agent.

        tool_ids : typing.Optional[typing.Sequence[str]]
            The ids of the tools used by the agent.

        source_ids : typing.Optional[typing.Sequence[str]]
            The ids of the sources used by the agent.

        block_ids : typing.Optional[typing.Sequence[str]]
            The ids of the blocks used by the agent.

        tags : typing.Optional[typing.Sequence[str]]
            The tags associated with the agent.

        system : typing.Optional[str]
            The system prompt used by the agent.

        tool_rules : typing.Optional[typing.Sequence[UpdateAgentToolRulesItem]]
            The tool rules governing the agent.

        llm_config : typing.Optional[LlmConfig]
            The LLM configuration used by the agent.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the agent.

        message_ids : typing.Optional[typing.Sequence[str]]
            The ids of the messages in the agent's in-context memory.

        description : typing.Optional[str]
            The description of the agent.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the agent.

        tool_exec_environment_variables : typing.Optional[typing.Dict[str, typing.Optional[str]]]
            The environment variables for tool execution specific to this agent.

        project_id : typing.Optional[str]
            The id of the project the agent belongs to.

        template_id : typing.Optional[str]
            The id of the template the agent belongs to.

        base_template_id : typing.Optional[str]
            The base template id of the agent.

        identity_ids : typing.Optional[typing.Sequence[str]]
            The ids of the identities associated with this agent.

        message_buffer_autoclear : typing.Optional[bool]
            If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.

        model : typing.Optional[str]
            The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config.

        embedding : typing.Optional[str]
            The embedding configuration handle used by the agent, specified in the format provider/model-name.

        enable_sleeptime : typing.Optional[bool]
            If set to True, memory management will move to a background agent thread.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.modify(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}",
            method="PATCH",
            json={
                "name": name,
                "tool_ids": tool_ids,
                "source_ids": source_ids,
                "block_ids": block_ids,
                "tags": tags,
                "system": system,
                "tool_rules": convert_and_respect_annotation_metadata(
                    object_=tool_rules, annotation=typing.Sequence[UpdateAgentToolRulesItem], direction="write"
                ),
                "llm_config": convert_and_respect_annotation_metadata(
                    object_=llm_config, annotation=LlmConfig, direction="write"
                ),
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "message_ids": message_ids,
                "description": description,
                "metadata": metadata,
                "tool_exec_environment_variables": tool_exec_environment_variables,
                "project_id": project_id,
                "template_id": template_id,
                "base_template_id": base_template_id,
                "identity_ids": identity_ids,
                "message_buffer_autoclear": message_buffer_autoclear,
                "model": model,
                "embedding": embedding,
                "enable_sleeptime": enable_sleeptime,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def modify_passage(
        self,
        agent_id: str,
        memory_id: str,
        *,
        id: str,
        created_by_id: typing.Optional[str] = OMIT,
        last_updated_by_id: typing.Optional[str] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        is_deleted: typing.Optional[bool] = OMIT,
        passage_update_agent_id: typing.Optional[str] = OMIT,
        source_id: typing.Optional[str] = OMIT,
        file_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        text: typing.Optional[str] = OMIT,
        embedding: typing.Optional[typing.Sequence[float]] = OMIT,
        embedding_config: typing.Optional[EmbeddingConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Modify a memory in the agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        memory_id : str

        id : str
            The unique identifier of the passage.

        created_by_id : typing.Optional[str]
            The id of the user that made this object.

        last_updated_by_id : typing.Optional[str]
            The id of the user that made this object.

        created_at : typing.Optional[dt.datetime]
            The timestamp when the object was created.

        updated_at : typing.Optional[dt.datetime]
            The timestamp when the object was last updated.

        is_deleted : typing.Optional[bool]
            Whether this passage is deleted or not.

        passage_update_agent_id : typing.Optional[str]
            The unique identifier of the agent associated with the passage.

        source_id : typing.Optional[str]
            The data source of the passage.

        file_id : typing.Optional[str]
            The unique identifier of the file associated with the passage.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata of the passage.

        text : typing.Optional[str]
            The text of the passage.

        embedding : typing.Optional[typing.Sequence[float]]
            The embedding of the passage.

        embedding_config : typing.Optional[EmbeddingConfig]
            The embedding configuration used by the passage.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.modify_passage(
                agent_id="agent_id",
                memory_id="memory_id",
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/archival-memory/{jsonable_encoder(memory_id)}",
            method="PATCH",
            json={
                "created_by_id": created_by_id,
                "last_updated_by_id": last_updated_by_id,
                "created_at": created_at,
                "updated_at": updated_at,
                "is_deleted": is_deleted,
                "agent_id": passage_update_agent_id,
                "source_id": source_id,
                "file_id": file_id,
                "metadata_": metadata,
                "text": text,
                "embedding": embedding,
                "embedding_config": convert_and_respect_annotation_metadata(
                    object_=embedding_config, annotation=EmbeddingConfig, direction="write"
                ),
                "id": id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Passage],
                    construct_type(
                        type_=typing.List[Passage],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def reset_messages(
        self,
        agent_id: str,
        *,
        add_default_initial_messages: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Resets the messages for an agent

        Parameters
        ----------
        agent_id : str

        add_default_initial_messages : typing.Optional[bool]
            If true, adds the default initial messages after resetting.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentState
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.reset_messages(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/reset-messages",
            method="PATCH",
            params={
                "add_default_initial_messages": add_default_initial_messages,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentState,
                    construct_type(
                        type_=AgentState,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def list_agent_groups(
        self,
        agent_id: str,
        *,
        manager_type: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Group]:
        """
        Lists the groups for an agent

        Parameters
        ----------
        agent_id : str

        manager_type : typing.Optional[str]
            Manager type to filter groups by

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Group]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.list_agent_groups(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/groups",
            method="GET",
            params={
                "manager_type": manager_type,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Group],
                    construct_type(
                        type_=typing.List[Group],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        construct_type(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def search(
        self,
        *,
        search: typing.Optional[typing.Sequence[AgentsSearchRequestSearchItem]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        combinator: typing.Optional[typing.Literal["AND"]] = OMIT,
        limit: typing.Optional[float] = OMIT,
        after: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentsSearchResponse:
        """
        <Note>This endpoint is only available on Letta Cloud.</Note>

        Search deployed agents.

        Parameters
        ----------
        search : typing.Optional[typing.Sequence[AgentsSearchRequestSearchItem]]

        project_id : typing.Optional[str]

        combinator : typing.Optional[typing.Literal["AND"]]

        limit : typing.Optional[float]

        after : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AgentsSearchResponse
            200

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.search()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/agents/search",
            method="POST",
            json={
                "search": convert_and_respect_annotation_metadata(
                    object_=search, annotation=typing.Sequence[AgentsSearchRequestSearchItem], direction="write"
                ),
                "project_id": project_id,
                "combinator": combinator,
                "limit": limit,
                "after": after,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AgentsSearchResponse,
                    construct_type(
                        type_=AgentsSearchResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
