# 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.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,
        identifier_id: typing.Optional[str] = None,
        identifier_keys: typing.Optional[typing.Union[str, typing.Sequence[str]]] = 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

        identifier_id : typing.Optional[str]
            Search agents by identifier id

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

        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,
                "identifier_id": identifier_id,
                "identifier_keys": identifier_keys,
            },
            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,
        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,
        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.

        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.

        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,
                "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,
            },
            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 download_agent_serialized(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Download the serialized JSON representation of 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.download_agent_serialized(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/download",
            method="GET",
            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 upload_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,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Upload a serialized agent JSON 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.

        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.upload_agent_serialized()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/agents/upload",
            method="POST",
            params={
                "append_copy_suffix": append_copy_suffix,
                "override_existing_tools": override_existing_tools,
                "project_id": project_id,
            },
            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,
        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.

        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,
            },
            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 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,
        identifier_id: typing.Optional[str] = None,
        identifier_keys: typing.Optional[typing.Union[str, typing.Sequence[str]]] = 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

        identifier_id : typing.Optional[str]
            Search agents by identifier id

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

        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,
                "identifier_id": identifier_id,
                "identifier_keys": identifier_keys,
            },
            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,
        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,
        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.

        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.

        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,
                "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,
            },
            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 download_agent_serialized(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Download the serialized JSON representation of 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.download_agent_serialized(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/agents/{jsonable_encoder(agent_id)}/download",
            method="GET",
            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 upload_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,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentState:
        """
        Upload a serialized agent JSON 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.

        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.upload_agent_serialized()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/agents/upload",
            method="POST",
            params={
                "append_copy_suffix": append_copy_suffix,
                "override_existing_tools": override_existing_tools,
                "project_id": project_id,
            },
            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,
        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.

        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,
            },
            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 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)
