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

import typing
import urllib.parse
from json.decoder import JSONDecodeError

import httpx

from .core.api_error import ApiError
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .core.jsonable_encoder import jsonable_encoder
from .core.remove_none_from_dict import remove_none_from_dict
from .environment import JulepApiEnvironment
from .types.agent import Agent
from .types.agent_default_settings import AgentDefaultSettings
from .types.chat_input_data_tool_choice import ChatInputDataToolChoice
from .types.chat_response import ChatResponse
from .types.chat_settings_preset import ChatSettingsPreset
from .types.chat_settings_response_format import ChatSettingsResponseFormat
from .types.chat_settings_stop import ChatSettingsStop
from .types.create_agent_request_instructions import CreateAgentRequestInstructions
from .types.create_agent_request_metadata import CreateAgentRequestMetadata
from .types.create_doc import CreateDoc
from .types.create_session_request_metadata import CreateSessionRequestMetadata
from .types.create_tool_request import CreateToolRequest
from .types.create_user_request_metadata import CreateUserRequestMetadata
from .types.function_def import FunctionDef
from .types.get_agent_docs_request_order import GetAgentDocsRequestOrder
from .types.get_agent_docs_request_sort_by import GetAgentDocsRequestSortBy
from .types.get_agent_docs_response import GetAgentDocsResponse
from .types.get_agent_memories_response import GetAgentMemoriesResponse
from .types.get_agent_tools_response import GetAgentToolsResponse
from .types.get_history_response import GetHistoryResponse
from .types.get_suggestions_response import GetSuggestionsResponse
from .types.get_user_docs_request_order import GetUserDocsRequestOrder
from .types.get_user_docs_request_sort_by import GetUserDocsRequestSortBy
from .types.get_user_docs_response import GetUserDocsResponse
from .types.input_chat_ml_message import InputChatMlMessage
from .types.job_status import JobStatus
from .types.list_agents_request_order import ListAgentsRequestOrder
from .types.list_agents_request_sort_by import ListAgentsRequestSortBy
from .types.list_agents_response import ListAgentsResponse
from .types.list_sessions_request_order import ListSessionsRequestOrder
from .types.list_sessions_request_sort_by import ListSessionsRequestSortBy
from .types.list_sessions_response import ListSessionsResponse
from .types.list_users_request_order import ListUsersRequestOrder
from .types.list_users_request_sort_by import ListUsersRequestSortBy
from .types.list_users_response import ListUsersResponse
from .types.partial_function_def import PartialFunctionDef
from .types.patch_agent_request_instructions import PatchAgentRequestInstructions
from .types.patch_agent_request_metadata import PatchAgentRequestMetadata
from .types.patch_session_request_metadata import PatchSessionRequestMetadata
from .types.patch_user_request_metadata import PatchUserRequestMetadata
from .types.resource_created_response import ResourceCreatedResponse
from .types.resource_updated_response import ResourceUpdatedResponse
from .types.session import Session
from .types.tool import Tool
from .types.update_agent_request_instructions import UpdateAgentRequestInstructions
from .types.update_agent_request_metadata import UpdateAgentRequestMetadata
from .types.update_session_request_metadata import UpdateSessionRequestMetadata
from .types.update_user_request_metadata import UpdateUserRequestMetadata
from .types.user import User

try:
    import pydantic.v1 as pydantic  # type: ignore
except ImportError:
    import pydantic  # type: ignore

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


class JulepApi:
    def __init__(
        self,
        *,
        base_url: typing.Optional[str] = None,
        environment: JulepApiEnvironment = JulepApiEnvironment.DEFAULT,
        api_key: str,
        timeout: typing.Optional[float] = 300,
        httpx_client: typing.Optional[httpx.Client] = None,
    ):
        self._client_wrapper = SyncClientWrapper(
            base_url=_get_base_url(base_url=base_url, environment=environment),
            api_key=api_key,
            httpx_client=(
                httpx.Client(timeout=timeout) if httpx_client is None else httpx_client
            ),
        )

    def list_sessions(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListSessionsRequestSortBy] = None,
        order: typing.Optional[ListSessionsRequestOrder] = None,
    ) -> ListSessionsResponse:
        """
        List sessions created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of sessions to return

            - offset: typing.Optional[int]. Number of sessions to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListSessionsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListSessionsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.list_sessions()
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListSessionsResponse, _response.json())  # type: ignore
        try:
            _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_session(
        self,
        *,
        user_id: typing.Optional[str] = OMIT,
        agent_id: str,
        situation: typing.Optional[str] = OMIT,
        metadata: typing.Optional[CreateSessionRequestMetadata] = OMIT,
        render_templates: typing.Optional[bool] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a session between an agent and a user

        Parameters:
            - user_id: typing.Optional[str]. (Optional) User ID of user to associate with this session

            - agent_id: str. Agent ID of agent to associate with this session

            - situation: typing.Optional[str]. A specific situation that sets the background for this session

            - metadata: typing.Optional[CreateSessionRequestMetadata]. Optional metadata

            - render_templates: typing.Optional[bool]. Render system and assistant message content as jinja templates
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_session(
            agent_id="agent_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"agent_id": agent_id}
        if user_id is not OMIT:
            _request["user_id"] = user_id
        if situation is not OMIT:
            _request["situation"] = situation
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if render_templates is not OMIT:
            _request["render_templates"] = render_templates
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_users(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListUsersRequestSortBy] = None,
        order: typing.Optional[ListUsersRequestOrder] = None,
    ) -> ListUsersResponse:
        """
        List users created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of items to return

            - offset: typing.Optional[int]. Number of items to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListUsersRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListUsersRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.list_users()
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "users"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListUsersResponse, _response.json())  # type: ignore
        try:
            _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_user(
        self,
        *,
        name: typing.Optional[str] = OMIT,
        about: typing.Optional[str] = OMIT,
        docs: typing.Optional[typing.List[CreateDoc]] = OMIT,
        metadata: typing.Optional[CreateUserRequestMetadata] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a new user

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

            - about: typing.Optional[str]. About the user

            - docs: typing.Optional[typing.List[CreateDoc]]. List of docs about user

            - metadata: typing.Optional[CreateUserRequestMetadata]. (Optional) metadata
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_user()
        """
        _request: typing.Dict[str, typing.Any] = {}
        if name is not OMIT:
            _request["name"] = name
        if about is not OMIT:
            _request["about"] = about
        if docs is not OMIT:
            _request["docs"] = docs
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "users"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_agents(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListAgentsRequestSortBy] = None,
        order: typing.Optional[ListAgentsRequestOrder] = None,
    ) -> ListAgentsResponse:
        """
        List agents created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of items to return

            - offset: typing.Optional[int]. Number of items to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListAgentsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListAgentsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.list_agents()
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "agents"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListAgentsResponse, _response.json())  # type: ignore
        try:
            _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_agent(
        self,
        *,
        name: str,
        about: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.List[CreateToolRequest]] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        model: typing.Optional[str] = OMIT,
        docs: typing.Optional[typing.List[CreateDoc]] = OMIT,
        metadata: typing.Optional[CreateAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[CreateAgentRequestInstructions] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a new agent

        Parameters:
            - name: str. Name of the agent

            - about: typing.Optional[str]. About the agent

            - tools: typing.Optional[typing.List[CreateToolRequest]]. A list of tools the model may call. Currently, only `function`s are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for.

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - docs: typing.Optional[typing.List[CreateDoc]]. List of docs about agent

            - metadata: typing.Optional[CreateAgentRequestMetadata]. (Optional) metadata

            - instructions: typing.Optional[CreateAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_agent(
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"name": name}
        if about is not OMIT:
            _request["about"] = about
        if tools is not OMIT:
            _request["tools"] = tools
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if model is not OMIT:
            _request["model"] = model
        if docs is not OMIT:
            _request["docs"] = docs
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "agents"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 get_session(self, session_id: str) -> Session:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_session(
            session_id="session_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Session, _response.json())  # type: ignore
        try:
            _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 update_session(
        self,
        session_id: str,
        *,
        situation: str,
        metadata: typing.Optional[UpdateSessionRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - session_id: str.

            - situation: str. Updated situation for this session

            - metadata: typing.Optional[UpdateSessionRequestMetadata]. Optional metadata
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.update_session(
            session_id="session_id",
            situation="situation",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"situation": situation}
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_session(self, session_id: str) -> None:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_session(
            session_id="session_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_session(
        self,
        session_id: str,
        *,
        situation: typing.Optional[str] = OMIT,
        metadata: typing.Optional[PatchSessionRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - session_id: str.

            - situation: typing.Optional[str]. Updated situation for this session

            - metadata: typing.Optional[PatchSessionRequestMetadata]. Optional metadata
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.patch_session(
            session_id="session_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if situation is not OMIT:
            _request["situation"] = situation
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_suggestions(
        self,
        session_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetSuggestionsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - session_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_suggestions(
            session_id="session_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/suggestions",
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetSuggestionsResponse, _response.json())  # type: ignore
        try:
            _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 get_history(
        self,
        session_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetHistoryResponse:
        """
        Sorted (created_at ascending)

        Parameters:
            - session_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_history(
            session_id="session_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/history",
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetHistoryResponse, _response.json())  # type: ignore
        try:
            _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_session_history(self, session_id: str) -> None:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_session_history(
            session_id="session_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/history",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 chat(
        self,
        session_id: str,
        *,
        messages: typing.List[InputChatMlMessage],
        tools: typing.Optional[typing.List[Tool]] = OMIT,
        tool_choice: typing.Optional[ChatInputDataToolChoice] = OMIT,
        frequency_penalty: typing.Optional[float] = OMIT,
        length_penalty: typing.Optional[float] = OMIT,
        logit_bias: typing.Optional[typing.Dict[str, typing.Optional[int]]] = OMIT,
        max_tokens: typing.Optional[int] = OMIT,
        presence_penalty: typing.Optional[float] = OMIT,
        repetition_penalty: typing.Optional[float] = OMIT,
        response_format: typing.Optional[ChatSettingsResponseFormat] = OMIT,
        seed: typing.Optional[int] = OMIT,
        stop: typing.Optional[ChatSettingsStop] = OMIT,
        stream: typing.Optional[bool] = OMIT,
        temperature: typing.Optional[float] = OMIT,
        top_p: typing.Optional[float] = OMIT,
        min_p: typing.Optional[float] = OMIT,
        preset: typing.Optional[ChatSettingsPreset] = OMIT,
        recall: typing.Optional[bool] = OMIT,
        record: typing.Optional[bool] = OMIT,
        remember: typing.Optional[bool] = OMIT,
    ) -> ChatResponse:
        """


        Parameters:
            - session_id: str.

            - messages: typing.List[InputChatMlMessage]. A list of new input messages comprising the conversation so far.

            - tools: typing.Optional[typing.List[Tool]]. (Advanced) List of tools that are provided in addition to agent's default set of tools. Functions of same name in agent set are overriden

            - tool_choice: typing.Optional[ChatInputDataToolChoice]. Can be one of existing tools given to the agent earlier or the ones included in the request

            - frequency_penalty: typing.Optional[float]. (OpenAI-like) Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - length_penalty: typing.Optional[float]. (Huggingface-like) Number between 0 and 2.0. 1.0 is neutral and values larger than that penalize number of tokens generated.

            - logit_bias: typing.Optional[typing.Dict[str, typing.Optional[int]]]. Modify the likelihood of specified tokens appearing in the completion.

                                                                                   Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
            - max_tokens: typing.Optional[int]. The maximum number of tokens to generate in the chat completion.

                                                The total length of input tokens and generated tokens is limited by the model's context length.
            - presence_penalty: typing.Optional[float]. (OpenAI-like) Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - repetition_penalty: typing.Optional[float]. (Huggingface-like) Number between 0 and 2.0. 1.0 is neutral and values larger than that penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - response_format: typing.Optional[ChatSettingsResponseFormat]. An object specifying the format that the model must output.

                                                                            Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON.

                                                                            **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.
            - seed: typing.Optional[int]. This feature is in Beta.
                                          If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.
                                          Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.
            - stop: typing.Optional[ChatSettingsStop]. Up to 4 sequences where the API will stop generating further tokens.

            - stream: typing.Optional[bool]. If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).

            - temperature: typing.Optional[float]. What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.

            - top_p: typing.Optional[float]. Defaults to 1 An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both.

            - min_p: typing.Optional[float]. Minimum probability compared to leading token to be considered

            - preset: typing.Optional[ChatSettingsPreset]. Generation preset name (problem_solving|conversational|fun|prose|creative|business|deterministic|code|multilingual)

            - recall: typing.Optional[bool]. Whether previous memories should be recalled or not

            - record: typing.Optional[bool]. Whether this interaction should be recorded in history or not

            - remember: typing.Optional[bool]. Whether this interaction should form memories or not
        ---
        from julep import InputChatMlMessage, InputChatMlMessageRole
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.chat(
            session_id="session_id",
            min_p=0.01,
            messages=[
                InputChatMlMessage(
                    role=InputChatMlMessageRole.USER,
                    content="content",
                )
            ],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"messages": messages}
        if tools is not OMIT:
            _request["tools"] = tools
        if tool_choice is not OMIT:
            _request["tool_choice"] = tool_choice
        if frequency_penalty is not OMIT:
            _request["frequency_penalty"] = frequency_penalty
        if length_penalty is not OMIT:
            _request["length_penalty"] = length_penalty
        if logit_bias is not OMIT:
            _request["logit_bias"] = logit_bias
        if max_tokens is not OMIT:
            _request["max_tokens"] = max_tokens
        if presence_penalty is not OMIT:
            _request["presence_penalty"] = presence_penalty
        if repetition_penalty is not OMIT:
            _request["repetition_penalty"] = repetition_penalty
        if response_format is not OMIT:
            _request["response_format"] = response_format
        if seed is not OMIT:
            _request["seed"] = seed
        if stop is not OMIT:
            _request["stop"] = stop
        if stream is not OMIT:
            _request["stream"] = stream
        if temperature is not OMIT:
            _request["temperature"] = temperature
        if top_p is not OMIT:
            _request["top_p"] = top_p
        if min_p is not OMIT:
            _request["min_p"] = min_p
        if preset is not OMIT:
            _request["preset"] = preset.value  # type: ignore
        if recall is not OMIT:
            _request["recall"] = recall
        if record is not OMIT:
            _request["record"] = record
        if remember is not OMIT:
            _request["remember"] = remember
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}/chat"
            ),
            json=jsonable_encoder(_request),
            headers=remove_none_from_dict(
                {**self._client_wrapper.get_headers(), "Accept": "application/json"}
            ),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ChatResponse, _response.json())  # type: ignore
        try:
            _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 get_agent_memories(
        self,
        agent_id: str,
        *,
        query: str,
        user_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetAgentMemoriesResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - query: str.

            - user_id: typing.Optional[str].

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_agent_memories(
            agent_id="agent_id",
            query="query",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/memories"
            ),
            params=remove_none_from_dict(
                {"query": query, "user_id": user_id, "limit": limit, "offset": offset}
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentMemoriesResponse, _response.json())  # type: ignore
        try:
            _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 get_user(self, user_id: str) -> User:
        """


        Parameters:
            - user_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_user(
            user_id="user_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(User, _response.json())  # type: ignore
        try:
            _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 update_user(
        self,
        user_id: str,
        *,
        about: str,
        name: str,
        metadata: typing.Optional[UpdateUserRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - user_id: str.

            - about: str. About the user

            - name: str. Name of the user

            - metadata: typing.Optional[UpdateUserRequestMetadata]. Optional metadata
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.update_user(
            user_id="user_id",
            about="about",
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"about": about, "name": name}
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_user(self, user_id: str) -> None:
        """


        Parameters:
            - user_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_user(
            user_id="user_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_user(
        self,
        user_id: str,
        *,
        about: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        metadata: typing.Optional[PatchUserRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - user_id: str.

            - about: typing.Optional[str]. About the user

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

            - metadata: typing.Optional[PatchUserRequestMetadata]. Optional metadata
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.patch_user(
            user_id="user_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if about is not OMIT:
            _request["about"] = about
        if name is not OMIT:
            _request["name"] = name
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_agent(self, agent_id: str) -> Agent:
        """


        Parameters:
            - agent_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_agent(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Agent, _response.json())  # type: ignore
        try:
            _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 update_agent(
        self,
        agent_id: str,
        *,
        about: str,
        name: str,
        model: typing.Optional[str] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        metadata: typing.Optional[UpdateAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[UpdateAgentRequestInstructions] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - about: str. About the agent

            - name: str. Name of the agent

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - metadata: typing.Optional[UpdateAgentRequestMetadata]. Optional metadata

            - instructions: typing.Optional[UpdateAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.update_agent(
            agent_id="agent_id",
            about="about",
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"about": about, "name": name}
        if model is not OMIT:
            _request["model"] = model
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_agent(self, agent_id: str) -> None:
        """


        Parameters:
            - agent_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_agent(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_agent(
        self,
        agent_id: str,
        *,
        about: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        model: typing.Optional[str] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        metadata: typing.Optional[PatchAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[PatchAgentRequestInstructions] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - about: typing.Optional[str]. About the agent

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

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - metadata: typing.Optional[PatchAgentRequestMetadata]. Optional metadata

            - instructions: typing.Optional[PatchAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.patch_agent(
            agent_id="agent_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if about is not OMIT:
            _request["about"] = about
        if name is not OMIT:
            _request["name"] = name
        if model is not OMIT:
            _request["model"] = model
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_agent_docs(
        self,
        agent_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[GetAgentDocsRequestSortBy] = None,
        order: typing.Optional[GetAgentDocsRequestOrder] = None,
    ) -> GetAgentDocsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[GetAgentDocsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[GetAgentDocsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_agent_docs(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/docs"
            ),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentDocsResponse, _response.json())  # type: ignore
        try:
            _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_agent_doc(
        self, agent_id: str, *, request: CreateDoc
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - agent_id: str.

            - request: CreateDoc.
        ---
        from julep import CreateDoc
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_agent_doc(
            agent_id="agent_id",
            request=CreateDoc(
                title="title",
                content="content",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/docs"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 get_user_docs(
        self,
        user_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[GetUserDocsRequestSortBy] = None,
        order: typing.Optional[GetUserDocsRequestOrder] = None,
    ) -> GetUserDocsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - user_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[GetUserDocsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[GetUserDocsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_user_docs(
            user_id="user_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}/docs"
            ),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetUserDocsResponse, _response.json())  # type: ignore
        try:
            _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_user_doc(
        self, user_id: str, *, request: CreateDoc
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - user_id: str.

            - request: CreateDoc.
        ---
        from julep import CreateDoc
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_user_doc(
            user_id="user_id",
            request=CreateDoc(
                title="title",
                content="content",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}/docs"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_user_doc(self, user_id: str, doc_id: str) -> None:
        """


        Parameters:
            - user_id: str.

            - doc_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_user_doc(
            user_id="user_id",
            doc_id="doc_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"users/{user_id}/docs/{doc_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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_agent_doc(self, agent_id: str, doc_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - doc_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_agent_doc(
            agent_id="agent_id",
            doc_id="doc_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/docs/{doc_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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_agent_memory(self, agent_id: str, memory_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - memory_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_agent_memory(
            agent_id="agent_id",
            memory_id="memory_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/memories/{memory_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 get_agent_tools(
        self,
        agent_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetAgentToolsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_agent_tools(
            agent_id="agent_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/tools"
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentToolsResponse, _response.json())  # type: ignore
        try:
            _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_agent_tool(
        self, agent_id: str, *, request: CreateToolRequest
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - agent_id: str.

            - request: CreateToolRequest.
        ---
        from julep import CreateToolRequest, CreateToolRequestType, FunctionDef
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.create_agent_tool(
            agent_id="agent_id",
            request=CreateToolRequest(
                type=CreateToolRequestType.FUNCTION,
                function=FunctionDef(
                    name="name",
                    parameters={},
                ),
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/tools"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 update_agent_tool(
        self, agent_id: str, tool_id: str, *, function: FunctionDef
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.

            - function: FunctionDef. Function definition and parameters
        ---
        from julep import FunctionDef
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.update_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
            function=FunctionDef(
                name="name",
                parameters={},
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            json=jsonable_encoder({"function": function}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_agent_tool(self, agent_id: str, tool_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.delete_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_agent_tool(
        self, agent_id: str, tool_id: str, *, function: PartialFunctionDef
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.

            - function: PartialFunctionDef. Function definition and parameters
        ---
        from julep import PartialFunctionDef
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.patch_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
            function=PartialFunctionDef(),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            json=jsonable_encoder({"function": function}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_job_status(self, job_id: str) -> JobStatus:
        """


        Parameters:
            - job_id: str.
        ---
        from julep.client import JulepApi

        client = JulepApi(
            api_key="YOUR_API_KEY",
        )
        client.get_job_status(
            job_id="job_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"jobs/{job_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(JobStatus, _response.json())  # type: ignore
        try:
            _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 AsyncJulepApi:
    def __init__(
        self,
        *,
        base_url: typing.Optional[str] = None,
        environment: JulepApiEnvironment = JulepApiEnvironment.DEFAULT,
        api_key: str,
        timeout: typing.Optional[float] = 300,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
    ):
        self._client_wrapper = AsyncClientWrapper(
            base_url=_get_base_url(base_url=base_url, environment=environment),
            api_key=api_key,
            httpx_client=(
                httpx.AsyncClient(timeout=timeout)
                if httpx_client is None
                else httpx_client
            ),
        )

    async def list_sessions(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListSessionsRequestSortBy] = None,
        order: typing.Optional[ListSessionsRequestOrder] = None,
    ) -> ListSessionsResponse:
        """
        List sessions created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of sessions to return

            - offset: typing.Optional[int]. Number of sessions to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListSessionsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListSessionsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.list_sessions()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListSessionsResponse, _response.json())  # type: ignore
        try:
            _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_session(
        self,
        *,
        user_id: typing.Optional[str] = OMIT,
        agent_id: str,
        situation: typing.Optional[str] = OMIT,
        metadata: typing.Optional[CreateSessionRequestMetadata] = OMIT,
        render_templates: typing.Optional[bool] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a session between an agent and a user

        Parameters:
            - user_id: typing.Optional[str]. (Optional) User ID of user to associate with this session

            - agent_id: str. Agent ID of agent to associate with this session

            - situation: typing.Optional[str]. A specific situation that sets the background for this session

            - metadata: typing.Optional[CreateSessionRequestMetadata]. Optional metadata

            - render_templates: typing.Optional[bool]. Render system and assistant message content as jinja templates
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_session(
            agent_id="agent_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"agent_id": agent_id}
        if user_id is not OMIT:
            _request["user_id"] = user_id
        if situation is not OMIT:
            _request["situation"] = situation
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if render_templates is not OMIT:
            _request["render_templates"] = render_templates
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_users(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListUsersRequestSortBy] = None,
        order: typing.Optional[ListUsersRequestOrder] = None,
    ) -> ListUsersResponse:
        """
        List users created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of items to return

            - offset: typing.Optional[int]. Number of items to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListUsersRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListUsersRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.list_users()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "users"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListUsersResponse, _response.json())  # type: ignore
        try:
            _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_user(
        self,
        *,
        name: typing.Optional[str] = OMIT,
        about: typing.Optional[str] = OMIT,
        docs: typing.Optional[typing.List[CreateDoc]] = OMIT,
        metadata: typing.Optional[CreateUserRequestMetadata] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a new user

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

            - about: typing.Optional[str]. About the user

            - docs: typing.Optional[typing.List[CreateDoc]]. List of docs about user

            - metadata: typing.Optional[CreateUserRequestMetadata]. (Optional) metadata
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_user()
        """
        _request: typing.Dict[str, typing.Any] = {}
        if name is not OMIT:
            _request["name"] = name
        if about is not OMIT:
            _request["about"] = about
        if docs is not OMIT:
            _request["docs"] = docs
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "users"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_agents(
        self,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[ListAgentsRequestSortBy] = None,
        order: typing.Optional[ListAgentsRequestOrder] = None,
    ) -> ListAgentsResponse:
        """
        List agents created (use limit/offset pagination to get large number of sessions; sorted by descending order of `created_at` by default)

        Parameters:
            - limit: typing.Optional[int]. Number of items to return

            - offset: typing.Optional[int]. Number of items to skip (sorted created_at descending order)

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[ListAgentsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[ListAgentsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.list_agents()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "agents"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ListAgentsResponse, _response.json())  # type: ignore
        try:
            _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_agent(
        self,
        *,
        name: str,
        about: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.List[CreateToolRequest]] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        model: typing.Optional[str] = OMIT,
        docs: typing.Optional[typing.List[CreateDoc]] = OMIT,
        metadata: typing.Optional[CreateAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[CreateAgentRequestInstructions] = OMIT,
    ) -> ResourceCreatedResponse:
        """
        Create a new agent

        Parameters:
            - name: str. Name of the agent

            - about: typing.Optional[str]. About the agent

            - tools: typing.Optional[typing.List[CreateToolRequest]]. A list of tools the model may call. Currently, only `function`s are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for.

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - docs: typing.Optional[typing.List[CreateDoc]]. List of docs about agent

            - metadata: typing.Optional[CreateAgentRequestMetadata]. (Optional) metadata

            - instructions: typing.Optional[CreateAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_agent(
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"name": name}
        if about is not OMIT:
            _request["about"] = about
        if tools is not OMIT:
            _request["tools"] = tools
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if model is not OMIT:
            _request["model"] = model
        if docs is not OMIT:
            _request["docs"] = docs
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "agents"),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 get_session(self, session_id: str) -> Session:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_session(
            session_id="session_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Session, _response.json())  # type: ignore
        try:
            _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 update_session(
        self,
        session_id: str,
        *,
        situation: str,
        metadata: typing.Optional[UpdateSessionRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - session_id: str.

            - situation: str. Updated situation for this session

            - metadata: typing.Optional[UpdateSessionRequestMetadata]. Optional metadata
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.update_session(
            session_id="session_id",
            situation="situation",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"situation": situation}
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_session(self, session_id: str) -> None:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_session(
            session_id="session_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_session(
        self,
        session_id: str,
        *,
        situation: typing.Optional[str] = OMIT,
        metadata: typing.Optional[PatchSessionRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - session_id: str.

            - situation: typing.Optional[str]. Updated situation for this session

            - metadata: typing.Optional[PatchSessionRequestMetadata]. Optional metadata
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.patch_session(
            session_id="session_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if situation is not OMIT:
            _request["situation"] = situation
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_suggestions(
        self,
        session_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetSuggestionsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - session_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_suggestions(
            session_id="session_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/suggestions",
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetSuggestionsResponse, _response.json())  # type: ignore
        try:
            _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 get_history(
        self,
        session_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetHistoryResponse:
        """
        Sorted (created_at ascending)

        Parameters:
            - session_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_history(
            session_id="session_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/history",
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetHistoryResponse, _response.json())  # type: ignore
        try:
            _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_session_history(self, session_id: str) -> None:
        """


        Parameters:
            - session_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_session_history(
            session_id="session_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"sessions/{session_id}/history",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 chat(
        self,
        session_id: str,
        *,
        messages: typing.List[InputChatMlMessage],
        tools: typing.Optional[typing.List[Tool]] = OMIT,
        tool_choice: typing.Optional[ChatInputDataToolChoice] = OMIT,
        frequency_penalty: typing.Optional[float] = OMIT,
        length_penalty: typing.Optional[float] = OMIT,
        logit_bias: typing.Optional[typing.Dict[str, typing.Optional[int]]] = OMIT,
        max_tokens: typing.Optional[int] = OMIT,
        presence_penalty: typing.Optional[float] = OMIT,
        repetition_penalty: typing.Optional[float] = OMIT,
        response_format: typing.Optional[ChatSettingsResponseFormat] = OMIT,
        seed: typing.Optional[int] = OMIT,
        stop: typing.Optional[ChatSettingsStop] = OMIT,
        stream: typing.Optional[bool] = OMIT,
        temperature: typing.Optional[float] = OMIT,
        top_p: typing.Optional[float] = OMIT,
        min_p: typing.Optional[float] = OMIT,
        preset: typing.Optional[ChatSettingsPreset] = OMIT,
        recall: typing.Optional[bool] = OMIT,
        record: typing.Optional[bool] = OMIT,
        remember: typing.Optional[bool] = OMIT,
    ) -> ChatResponse:
        """


        Parameters:
            - session_id: str.

            - messages: typing.List[InputChatMlMessage]. A list of new input messages comprising the conversation so far.

            - tools: typing.Optional[typing.List[Tool]]. (Advanced) List of tools that are provided in addition to agent's default set of tools. Functions of same name in agent set are overriden

            - tool_choice: typing.Optional[ChatInputDataToolChoice]. Can be one of existing tools given to the agent earlier or the ones included in the request

            - frequency_penalty: typing.Optional[float]. (OpenAI-like) Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - length_penalty: typing.Optional[float]. (Huggingface-like) Number between 0 and 2.0. 1.0 is neutral and values larger than that penalize number of tokens generated.

            - logit_bias: typing.Optional[typing.Dict[str, typing.Optional[int]]]. Modify the likelihood of specified tokens appearing in the completion.

                                                                                   Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
            - max_tokens: typing.Optional[int]. The maximum number of tokens to generate in the chat completion.

                                                The total length of input tokens and generated tokens is limited by the model's context length.
            - presence_penalty: typing.Optional[float]. (OpenAI-like) Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - repetition_penalty: typing.Optional[float]. (Huggingface-like) Number between 0 and 2.0. 1.0 is neutral and values larger than that penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

            - response_format: typing.Optional[ChatSettingsResponseFormat]. An object specifying the format that the model must output.

                                                                            Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON.

                                                                            **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.
            - seed: typing.Optional[int]. This feature is in Beta.
                                          If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.
                                          Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.
            - stop: typing.Optional[ChatSettingsStop]. Up to 4 sequences where the API will stop generating further tokens.

            - stream: typing.Optional[bool]. If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).

            - temperature: typing.Optional[float]. What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.

            - top_p: typing.Optional[float]. Defaults to 1 An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both.

            - min_p: typing.Optional[float]. Minimum probability compared to leading token to be considered

            - preset: typing.Optional[ChatSettingsPreset]. Generation preset name (problem_solving|conversational|fun|prose|creative|business|deterministic|code|multilingual)

            - recall: typing.Optional[bool]. Whether previous memories should be recalled or not

            - record: typing.Optional[bool]. Whether this interaction should be recorded in history or not

            - remember: typing.Optional[bool]. Whether this interaction should form memories or not
        ---
        from julep import InputChatMlMessage, InputChatMlMessageRole
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.chat(
            session_id="session_id",
            min_p=0.01,
            messages=[
                InputChatMlMessage(
                    role=InputChatMlMessageRole.USER,
                    content="content",
                )
            ],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"messages": messages}
        if tools is not OMIT:
            _request["tools"] = tools
        if tool_choice is not OMIT:
            _request["tool_choice"] = tool_choice
        if frequency_penalty is not OMIT:
            _request["frequency_penalty"] = frequency_penalty
        if length_penalty is not OMIT:
            _request["length_penalty"] = length_penalty
        if logit_bias is not OMIT:
            _request["logit_bias"] = logit_bias
        if max_tokens is not OMIT:
            _request["max_tokens"] = max_tokens
        if presence_penalty is not OMIT:
            _request["presence_penalty"] = presence_penalty
        if repetition_penalty is not OMIT:
            _request["repetition_penalty"] = repetition_penalty
        if response_format is not OMIT:
            _request["response_format"] = response_format
        if seed is not OMIT:
            _request["seed"] = seed
        if stop is not OMIT:
            _request["stop"] = stop
        if stream is not OMIT:
            _request["stream"] = stream
        if temperature is not OMIT:
            _request["temperature"] = temperature
        if top_p is not OMIT:
            _request["top_p"] = top_p
        if min_p is not OMIT:
            _request["min_p"] = min_p
        if preset is not OMIT:
            _request["preset"] = preset.value  # type: ignore
        if recall is not OMIT:
            _request["recall"] = recall
        if record is not OMIT:
            _request["record"] = record
        if remember is not OMIT:
            _request["remember"] = remember
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"sessions/{session_id}/chat"
            ),
            json=jsonable_encoder(_request),
            headers=remove_none_from_dict(
                {**self._client_wrapper.get_headers(), "Accept": "application/json"}
            ),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ChatResponse, _response.json())  # type: ignore
        try:
            _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 get_agent_memories(
        self,
        agent_id: str,
        *,
        query: str,
        user_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetAgentMemoriesResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - query: str.

            - user_id: typing.Optional[str].

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_agent_memories(
            agent_id="agent_id",
            query="query",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/memories"
            ),
            params=remove_none_from_dict(
                {"query": query, "user_id": user_id, "limit": limit, "offset": offset}
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentMemoriesResponse, _response.json())  # type: ignore
        try:
            _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 get_user(self, user_id: str) -> User:
        """


        Parameters:
            - user_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_user(
            user_id="user_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(User, _response.json())  # type: ignore
        try:
            _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 update_user(
        self,
        user_id: str,
        *,
        about: str,
        name: str,
        metadata: typing.Optional[UpdateUserRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - user_id: str.

            - about: str. About the user

            - name: str. Name of the user

            - metadata: typing.Optional[UpdateUserRequestMetadata]. Optional metadata
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.update_user(
            user_id="user_id",
            about="about",
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"about": about, "name": name}
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_user(self, user_id: str) -> None:
        """


        Parameters:
            - user_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_user(
            user_id="user_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_user(
        self,
        user_id: str,
        *,
        about: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        metadata: typing.Optional[PatchUserRequestMetadata] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - user_id: str.

            - about: typing.Optional[str]. About the user

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

            - metadata: typing.Optional[PatchUserRequestMetadata]. Optional metadata
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.patch_user(
            user_id="user_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if about is not OMIT:
            _request["about"] = about
        if name is not OMIT:
            _request["name"] = name
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_agent(self, agent_id: str) -> Agent:
        """


        Parameters:
            - agent_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_agent(
            agent_id="agent_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Agent, _response.json())  # type: ignore
        try:
            _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 update_agent(
        self,
        agent_id: str,
        *,
        about: str,
        name: str,
        model: typing.Optional[str] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        metadata: typing.Optional[UpdateAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[UpdateAgentRequestInstructions] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - about: str. About the agent

            - name: str. Name of the agent

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - metadata: typing.Optional[UpdateAgentRequestMetadata]. Optional metadata

            - instructions: typing.Optional[UpdateAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.update_agent(
            agent_id="agent_id",
            about="about",
            name="name",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"about": about, "name": name}
        if model is not OMIT:
            _request["model"] = model
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = await self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_agent(self, agent_id: str) -> None:
        """


        Parameters:
            - agent_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_agent(
            agent_id="agent_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_agent(
        self,
        agent_id: str,
        *,
        about: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        model: typing.Optional[str] = OMIT,
        default_settings: typing.Optional[AgentDefaultSettings] = OMIT,
        metadata: typing.Optional[PatchAgentRequestMetadata] = OMIT,
        instructions: typing.Optional[PatchAgentRequestInstructions] = OMIT,
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - about: typing.Optional[str]. About the agent

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

            - model: typing.Optional[str]. Name of the model that the agent is supposed to use

            - default_settings: typing.Optional[AgentDefaultSettings]. Default model settings to start every session with

            - metadata: typing.Optional[PatchAgentRequestMetadata]. Optional metadata

            - instructions: typing.Optional[PatchAgentRequestInstructions]. Instructions for the agent
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.patch_agent(
            agent_id="agent_id",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if about is not OMIT:
            _request["about"] = about
        if name is not OMIT:
            _request["name"] = name
        if model is not OMIT:
            _request["model"] = model
        if default_settings is not OMIT:
            _request["default_settings"] = default_settings
        if metadata is not OMIT:
            _request["metadata"] = metadata
        if instructions is not OMIT:
            _request["instructions"] = instructions
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}"
            ),
            json=jsonable_encoder(_request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_agent_docs(
        self,
        agent_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[GetAgentDocsRequestSortBy] = None,
        order: typing.Optional[GetAgentDocsRequestOrder] = None,
    ) -> GetAgentDocsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[GetAgentDocsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[GetAgentDocsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_agent_docs(
            agent_id="agent_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/docs"
            ),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentDocsResponse, _response.json())  # type: ignore
        try:
            _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_agent_doc(
        self, agent_id: str, *, request: CreateDoc
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - agent_id: str.

            - request: CreateDoc.
        ---
        from julep import CreateDoc
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_agent_doc(
            agent_id="agent_id",
            request=CreateDoc(
                title="title",
                content="content",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/docs"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 get_user_docs(
        self,
        user_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        sort_by: typing.Optional[GetUserDocsRequestSortBy] = None,
        order: typing.Optional[GetUserDocsRequestOrder] = None,
    ) -> GetUserDocsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - user_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].

            - metadata_filter: typing.Optional[str]. JSON object that should be used to filter objects by metadata

            - sort_by: typing.Optional[GetUserDocsRequestSortBy]. Which field to sort by: `created_at` or `updated_at`

            - order: typing.Optional[GetUserDocsRequestOrder]. Which order should the sort be: `asc` (ascending) or `desc` (descending)
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_user_docs(
            user_id="user_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}/docs"
            ),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "offset": offset,
                    "metadata_filter": metadata_filter,
                    "sort_by": sort_by,
                    "order": order,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetUserDocsResponse, _response.json())  # type: ignore
        try:
            _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_user_doc(
        self, user_id: str, *, request: CreateDoc
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - user_id: str.

            - request: CreateDoc.
        ---
        from julep import CreateDoc
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_user_doc(
            user_id="user_id",
            request=CreateDoc(
                title="title",
                content="content",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"users/{user_id}/docs"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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_user_doc(self, user_id: str, doc_id: str) -> None:
        """


        Parameters:
            - user_id: str.

            - doc_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_user_doc(
            user_id="user_id",
            doc_id="doc_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"users/{user_id}/docs/{doc_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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_agent_doc(self, agent_id: str, doc_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - doc_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_agent_doc(
            agent_id="agent_id",
            doc_id="doc_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/docs/{doc_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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_agent_memory(self, agent_id: str, memory_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - memory_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_agent_memory(
            agent_id="agent_id",
            memory_id="memory_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/memories/{memory_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 get_agent_tools(
        self,
        agent_id: str,
        *,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
    ) -> GetAgentToolsResponse:
        """
        Sorted (created_at descending)

        Parameters:
            - agent_id: str.

            - limit: typing.Optional[int].

            - offset: typing.Optional[int].
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_agent_tools(
            agent_id="agent_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/tools"
            ),
            params=remove_none_from_dict({"limit": limit, "offset": offset}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(GetAgentToolsResponse, _response.json())  # type: ignore
        try:
            _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_agent_tool(
        self, agent_id: str, *, request: CreateToolRequest
    ) -> ResourceCreatedResponse:
        """


        Parameters:
            - agent_id: str.

            - request: CreateToolRequest.
        ---
        from julep import CreateToolRequest, CreateToolRequestType, FunctionDef
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.create_agent_tool(
            agent_id="agent_id",
            request=CreateToolRequest(
                type=CreateToolRequestType.FUNCTION,
                function=FunctionDef(
                    name="name",
                    parameters={},
                ),
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"agents/{agent_id}/tools"
            ),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceCreatedResponse, _response.json())  # type: ignore
        try:
            _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 update_agent_tool(
        self, agent_id: str, tool_id: str, *, function: FunctionDef
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.

            - function: FunctionDef. Function definition and parameters
        ---
        from julep import FunctionDef
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.update_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
            function=FunctionDef(
                name="name",
                parameters={},
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            json=jsonable_encoder({"function": function}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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_agent_tool(self, agent_id: str, tool_id: str) -> None:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.delete_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _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 patch_agent_tool(
        self, agent_id: str, tool_id: str, *, function: PartialFunctionDef
    ) -> ResourceUpdatedResponse:
        """


        Parameters:
            - agent_id: str.

            - tool_id: str.

            - function: PartialFunctionDef. Function definition and parameters
        ---
        from julep import PartialFunctionDef
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.patch_agent_tool(
            agent_id="agent_id",
            tool_id="tool_id",
            function=PartialFunctionDef(),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/",
                f"agents/{agent_id}/tools/{tool_id}",
            ),
            json=jsonable_encoder({"function": function}),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ResourceUpdatedResponse, _response.json())  # type: ignore
        try:
            _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 get_job_status(self, job_id: str) -> JobStatus:
        """


        Parameters:
            - job_id: str.
        ---
        from julep.client import AsyncJulepApi

        client = AsyncJulepApi(
            api_key="YOUR_API_KEY",
        )
        await client.get_job_status(
            job_id="job_id",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"jobs/{job_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=300,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(JobStatus, _response.json())  # type: ignore
        try:
            _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 _get_base_url(
    *, base_url: typing.Optional[str] = None, environment: JulepApiEnvironment
) -> str:
    if base_url is not None:
        return base_url
    elif environment is not None:
        return environment.value
    else:
        raise Exception(
            "Please pass in either base_url or environment to construct the client"
        )
