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

from __future__ import annotations

import typing

from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.request_options import RequestOptions
from ...types.adhoc_agent_config_override_for_test_request_model import AdhocAgentConfigOverrideForTestRequestModel
from ...types.agent_platform_settings_request_model import AgentPlatformSettingsRequestModel
from ...types.agent_simulated_chat_test_response_model import AgentSimulatedChatTestResponseModel
from ...types.agent_sort_by import AgentSortBy
from ...types.agent_workflow_request_model import AgentWorkflowRequestModel
from ...types.conversation_simulation_specification import ConversationSimulationSpecification
from ...types.conversational_config import ConversationalConfig
from ...types.create_agent_response_model import CreateAgentResponseModel
from ...types.get_agent_response_model import GetAgentResponseModel
from ...types.get_agents_page_response_model import GetAgentsPageResponseModel
from ...types.get_test_suite_invocation_response_model import GetTestSuiteInvocationResponseModel
from ...types.prompt_evaluation_criteria import PromptEvaluationCriteria
from ...types.single_test_run_request_model import SingleTestRunRequestModel
from ...types.sort_direction import SortDirection
from .raw_client import AsyncRawAgentsClient, RawAgentsClient

if typing.TYPE_CHECKING:
    from .knowledge_base.client import AsyncKnowledgeBaseClient, KnowledgeBaseClient
    from .link.client import AsyncLinkClient, LinkClient
    from .llm_usage.client import AsyncLlmUsageClient, LlmUsageClient
    from .widget.client import AsyncWidgetClient, WidgetClient
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class AgentsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawAgentsClient(client_wrapper=client_wrapper)
        self._client_wrapper = client_wrapper
        self._widget: typing.Optional[WidgetClient] = None
        self._link: typing.Optional[LinkClient] = None
        self._knowledge_base: typing.Optional[KnowledgeBaseClient] = None
        self._llm_usage: typing.Optional[LlmUsageClient] = None

    @property
    def with_raw_response(self) -> RawAgentsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawAgentsClient
        """
        return self._raw_client

    def create(
        self,
        *,
        conversation_config: ConversationalConfig,
        platform_settings: typing.Optional[AgentPlatformSettingsRequestModel] = OMIT,
        workflow: typing.Optional[AgentWorkflowRequestModel] = OMIT,
        name: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateAgentResponseModel:
        """
        Create an agent from a config object

        Parameters
        ----------
        conversation_config : ConversationalConfig
            Conversation configuration for an agent

        platform_settings : typing.Optional[AgentPlatformSettingsRequestModel]
            Platform settings for the agent are all settings that aren't related to the conversation orchestration and content.

        workflow : typing.Optional[AgentWorkflowRequestModel]
            Workflow for the agent. This is used to define the flow of the conversation and how the agent interacts with tools.

        name : typing.Optional[str]
            A name to make the agent easier to find

        tags : typing.Optional[typing.Sequence[str]]
            Tags to help classify and filter the agent

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

        Returns
        -------
        CreateAgentResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ConversationalConfig, ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.create(
            conversation_config=ConversationalConfig(),
        )
        """
        _response = self._raw_client.create(
            conversation_config=conversation_config,
            platform_settings=platform_settings,
            workflow=workflow,
            name=name,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    def get(self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetAgentResponseModel:
        """
        Retrieve config for an agent

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

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

        Returns
        -------
        GetAgentResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.get(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
        )
        """
        _response = self._raw_client.get(agent_id, request_options=request_options)
        return _response.data

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

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

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

        Returns
        -------
        None

        Examples
        --------
        from elevenlabs import ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.delete(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
        )
        """
        _response = self._raw_client.delete(agent_id, request_options=request_options)
        return _response.data

    def update(
        self,
        agent_id: str,
        *,
        conversation_config: typing.Optional[ConversationalConfig] = OMIT,
        platform_settings: typing.Optional[AgentPlatformSettingsRequestModel] = OMIT,
        workflow: typing.Optional[AgentWorkflowRequestModel] = OMIT,
        name: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetAgentResponseModel:
        """
        Patches an Agent settings

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        conversation_config : typing.Optional[ConversationalConfig]
            Conversation configuration for an agent

        platform_settings : typing.Optional[AgentPlatformSettingsRequestModel]
            Platform settings for the agent are all settings that aren't related to the conversation orchestration and content.

        workflow : typing.Optional[AgentWorkflowRequestModel]
            Workflow for the agent. This is used to define the flow of the conversation and how the agent interacts with tools.

        name : typing.Optional[str]
            A name to make the agent easier to find

        tags : typing.Optional[typing.Sequence[str]]
            Tags to help classify and filter the agent

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

        Returns
        -------
        GetAgentResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.update(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
        )
        """
        _response = self._raw_client.update(
            agent_id,
            conversation_config=conversation_config,
            platform_settings=platform_settings,
            workflow=workflow,
            name=name,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    def list(
        self,
        *,
        page_size: typing.Optional[int] = None,
        search: typing.Optional[str] = None,
        archived: typing.Optional[bool] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        sort_by: typing.Optional[AgentSortBy] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetAgentsPageResponseModel:
        """
        Returns a list of your agents and their metadata.

        Parameters
        ----------
        page_size : typing.Optional[int]
            How many Agents to return at maximum. Can not exceed 100, defaults to 30.

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

        archived : typing.Optional[bool]
            Filter agents by archived status

        sort_direction : typing.Optional[SortDirection]
            The direction to sort the results

        sort_by : typing.Optional[AgentSortBy]
            The field to sort the results by

        cursor : typing.Optional[str]
            Used for fetching next page. Cursor is returned in the response.

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

        Returns
        -------
        GetAgentsPageResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.list(
            page_size=1,
            search="search",
            archived=True,
            sort_direction="asc",
            sort_by="name",
            cursor="cursor",
        )
        """
        _response = self._raw_client.list(
            page_size=page_size,
            search=search,
            archived=archived,
            sort_direction=sort_direction,
            sort_by=sort_by,
            cursor=cursor,
            request_options=request_options,
        )
        return _response.data

    def duplicate(
        self,
        agent_id: str,
        *,
        name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateAgentResponseModel:
        """
        Create a new agent by duplicating an existing one

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        name : typing.Optional[str]
            A name to make the agent easier to find

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

        Returns
        -------
        CreateAgentResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ElevenLabs

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.duplicate(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
        )
        """
        _response = self._raw_client.duplicate(agent_id, name=name, request_options=request_options)
        return _response.data

    def simulate_conversation(
        self,
        agent_id: str,
        *,
        simulation_specification: ConversationSimulationSpecification,
        extra_evaluation_criteria: typing.Optional[typing.Sequence[PromptEvaluationCriteria]] = OMIT,
        new_turns_limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentSimulatedChatTestResponseModel:
        """
        Run a conversation between the agent and a simulated user.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        simulation_specification : ConversationSimulationSpecification
            A specification detailing how the conversation should be simulated

        extra_evaluation_criteria : typing.Optional[typing.Sequence[PromptEvaluationCriteria]]
            A list of evaluation criteria to test

        new_turns_limit : typing.Optional[int]
            Maximum number of new turns to generate in the conversation simulation

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

        Returns
        -------
        AgentSimulatedChatTestResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import (
            AgentConfig,
            ConversationSimulationSpecification,
            ElevenLabs,
        )

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.simulate_conversation(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
            simulation_specification=ConversationSimulationSpecification(
                simulated_user_config=AgentConfig(
                    first_message="Hello, how can I help you today?",
                    language="en",
                    disable_first_message_interruptions=False,
                ),
            ),
        )
        """
        _response = self._raw_client.simulate_conversation(
            agent_id,
            simulation_specification=simulation_specification,
            extra_evaluation_criteria=extra_evaluation_criteria,
            new_turns_limit=new_turns_limit,
            request_options=request_options,
        )
        return _response.data

    def simulate_conversation_stream(
        self,
        agent_id: str,
        *,
        simulation_specification: ConversationSimulationSpecification,
        extra_evaluation_criteria: typing.Optional[typing.Sequence[PromptEvaluationCriteria]] = OMIT,
        new_turns_limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Run a conversation between the agent and a simulated user and stream back the response. Response is streamed back as partial lists of messages that should be concatenated and once the conversation has complete a single final message with the conversation analysis will be sent.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        simulation_specification : ConversationSimulationSpecification
            A specification detailing how the conversation should be simulated

        extra_evaluation_criteria : typing.Optional[typing.Sequence[PromptEvaluationCriteria]]
            A list of evaluation criteria to test

        new_turns_limit : typing.Optional[int]
            Maximum number of new turns to generate in the conversation simulation

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

        Returns
        -------
        None

        Examples
        --------
        from elevenlabs import (
            AgentConfig,
            ConversationSimulationSpecification,
            ElevenLabs,
        )

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.simulate_conversation_stream(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
            simulation_specification=ConversationSimulationSpecification(
                simulated_user_config=AgentConfig(
                    first_message="Hello, how can I help you today?",
                    language="en",
                    disable_first_message_interruptions=False,
                ),
            ),
        )
        """
        _response = self._raw_client.simulate_conversation_stream(
            agent_id,
            simulation_specification=simulation_specification,
            extra_evaluation_criteria=extra_evaluation_criteria,
            new_turns_limit=new_turns_limit,
            request_options=request_options,
        )
        return _response.data

    def run_tests(
        self,
        agent_id: str,
        *,
        tests: typing.Sequence[SingleTestRunRequestModel],
        agent_config_override: typing.Optional[AdhocAgentConfigOverrideForTestRequestModel] = OMIT,
        branch_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetTestSuiteInvocationResponseModel:
        """
        Run selected tests on the agent with provided configuration. If the agent configuration is provided, it will be used to override default agent configuration.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        tests : typing.Sequence[SingleTestRunRequestModel]
            List of tests to run on the agent

        agent_config_override : typing.Optional[AdhocAgentConfigOverrideForTestRequestModel]
            Configuration overrides to use for testing. If not provided, the agent's default configuration will be used.

        branch_id : typing.Optional[str]
            ID of the branch to run the tests on. If not provided, the tests will be run on the agent default configuration.

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

        Returns
        -------
        GetTestSuiteInvocationResponseModel
            Successful Response

        Examples
        --------
        from elevenlabs import ElevenLabs, SingleTestRunRequestModel

        client = ElevenLabs(
            api_key="YOUR_API_KEY",
        )
        client.conversational_ai.agents.run_tests(
            agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
            tests=[
                SingleTestRunRequestModel(
                    test_id="test_id",
                )
            ],
        )
        """
        _response = self._raw_client.run_tests(
            agent_id,
            tests=tests,
            agent_config_override=agent_config_override,
            branch_id=branch_id,
            request_options=request_options,
        )
        return _response.data

    @property
    def widget(self):
        if self._widget is None:
            from .widget.client import WidgetClient  # noqa: E402

            self._widget = WidgetClient(client_wrapper=self._client_wrapper)
        return self._widget

    @property
    def link(self):
        if self._link is None:
            from .link.client import LinkClient  # noqa: E402

            self._link = LinkClient(client_wrapper=self._client_wrapper)
        return self._link

    @property
    def knowledge_base(self):
        if self._knowledge_base is None:
            from .knowledge_base.client import KnowledgeBaseClient  # noqa: E402

            self._knowledge_base = KnowledgeBaseClient(client_wrapper=self._client_wrapper)
        return self._knowledge_base

    @property
    def llm_usage(self):
        if self._llm_usage is None:
            from .llm_usage.client import LlmUsageClient  # noqa: E402

            self._llm_usage = LlmUsageClient(client_wrapper=self._client_wrapper)
        return self._llm_usage


class AsyncAgentsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawAgentsClient(client_wrapper=client_wrapper)
        self._client_wrapper = client_wrapper
        self._widget: typing.Optional[AsyncWidgetClient] = None
        self._link: typing.Optional[AsyncLinkClient] = None
        self._knowledge_base: typing.Optional[AsyncKnowledgeBaseClient] = None
        self._llm_usage: typing.Optional[AsyncLlmUsageClient] = None

    @property
    def with_raw_response(self) -> AsyncRawAgentsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawAgentsClient
        """
        return self._raw_client

    async def create(
        self,
        *,
        conversation_config: ConversationalConfig,
        platform_settings: typing.Optional[AgentPlatformSettingsRequestModel] = OMIT,
        workflow: typing.Optional[AgentWorkflowRequestModel] = OMIT,
        name: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateAgentResponseModel:
        """
        Create an agent from a config object

        Parameters
        ----------
        conversation_config : ConversationalConfig
            Conversation configuration for an agent

        platform_settings : typing.Optional[AgentPlatformSettingsRequestModel]
            Platform settings for the agent are all settings that aren't related to the conversation orchestration and content.

        workflow : typing.Optional[AgentWorkflowRequestModel]
            Workflow for the agent. This is used to define the flow of the conversation and how the agent interacts with tools.

        name : typing.Optional[str]
            A name to make the agent easier to find

        tags : typing.Optional[typing.Sequence[str]]
            Tags to help classify and filter the agent

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

        Returns
        -------
        CreateAgentResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs, ConversationalConfig

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.conversational_ai.agents.create(
                conversation_config=ConversationalConfig(),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.create(
            conversation_config=conversation_config,
            platform_settings=platform_settings,
            workflow=workflow,
            name=name,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    async def get(
        self, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> GetAgentResponseModel:
        """
        Retrieve config for an agent

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

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

        Returns
        -------
        GetAgentResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


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


        asyncio.run(main())
        """
        _response = await self._raw_client.get(agent_id, request_options=request_options)
        return _response.data

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

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


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


        asyncio.run(main())
        """
        _response = await self._raw_client.delete(agent_id, request_options=request_options)
        return _response.data

    async def update(
        self,
        agent_id: str,
        *,
        conversation_config: typing.Optional[ConversationalConfig] = OMIT,
        platform_settings: typing.Optional[AgentPlatformSettingsRequestModel] = OMIT,
        workflow: typing.Optional[AgentWorkflowRequestModel] = OMIT,
        name: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetAgentResponseModel:
        """
        Patches an Agent settings

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        conversation_config : typing.Optional[ConversationalConfig]
            Conversation configuration for an agent

        platform_settings : typing.Optional[AgentPlatformSettingsRequestModel]
            Platform settings for the agent are all settings that aren't related to the conversation orchestration and content.

        workflow : typing.Optional[AgentWorkflowRequestModel]
            Workflow for the agent. This is used to define the flow of the conversation and how the agent interacts with tools.

        name : typing.Optional[str]
            A name to make the agent easier to find

        tags : typing.Optional[typing.Sequence[str]]
            Tags to help classify and filter the agent

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

        Returns
        -------
        GetAgentResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


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


        asyncio.run(main())
        """
        _response = await self._raw_client.update(
            agent_id,
            conversation_config=conversation_config,
            platform_settings=platform_settings,
            workflow=workflow,
            name=name,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    async def list(
        self,
        *,
        page_size: typing.Optional[int] = None,
        search: typing.Optional[str] = None,
        archived: typing.Optional[bool] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        sort_by: typing.Optional[AgentSortBy] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetAgentsPageResponseModel:
        """
        Returns a list of your agents and their metadata.

        Parameters
        ----------
        page_size : typing.Optional[int]
            How many Agents to return at maximum. Can not exceed 100, defaults to 30.

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

        archived : typing.Optional[bool]
            Filter agents by archived status

        sort_direction : typing.Optional[SortDirection]
            The direction to sort the results

        sort_by : typing.Optional[AgentSortBy]
            The field to sort the results by

        cursor : typing.Optional[str]
            Used for fetching next page. Cursor is returned in the response.

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

        Returns
        -------
        GetAgentsPageResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.conversational_ai.agents.list(
                page_size=1,
                search="search",
                archived=True,
                sort_direction="asc",
                sort_by="name",
                cursor="cursor",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list(
            page_size=page_size,
            search=search,
            archived=archived,
            sort_direction=sort_direction,
            sort_by=sort_by,
            cursor=cursor,
            request_options=request_options,
        )
        return _response.data

    async def duplicate(
        self,
        agent_id: str,
        *,
        name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateAgentResponseModel:
        """
        Create a new agent by duplicating an existing one

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        name : typing.Optional[str]
            A name to make the agent easier to find

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

        Returns
        -------
        CreateAgentResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


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


        asyncio.run(main())
        """
        _response = await self._raw_client.duplicate(agent_id, name=name, request_options=request_options)
        return _response.data

    async def simulate_conversation(
        self,
        agent_id: str,
        *,
        simulation_specification: ConversationSimulationSpecification,
        extra_evaluation_criteria: typing.Optional[typing.Sequence[PromptEvaluationCriteria]] = OMIT,
        new_turns_limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentSimulatedChatTestResponseModel:
        """
        Run a conversation between the agent and a simulated user.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        simulation_specification : ConversationSimulationSpecification
            A specification detailing how the conversation should be simulated

        extra_evaluation_criteria : typing.Optional[typing.Sequence[PromptEvaluationCriteria]]
            A list of evaluation criteria to test

        new_turns_limit : typing.Optional[int]
            Maximum number of new turns to generate in the conversation simulation

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

        Returns
        -------
        AgentSimulatedChatTestResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import (
            AgentConfig,
            AsyncElevenLabs,
            ConversationSimulationSpecification,
        )

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.conversational_ai.agents.simulate_conversation(
                agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
                simulation_specification=ConversationSimulationSpecification(
                    simulated_user_config=AgentConfig(
                        first_message="Hello, how can I help you today?",
                        language="en",
                        disable_first_message_interruptions=False,
                    ),
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.simulate_conversation(
            agent_id,
            simulation_specification=simulation_specification,
            extra_evaluation_criteria=extra_evaluation_criteria,
            new_turns_limit=new_turns_limit,
            request_options=request_options,
        )
        return _response.data

    async def simulate_conversation_stream(
        self,
        agent_id: str,
        *,
        simulation_specification: ConversationSimulationSpecification,
        extra_evaluation_criteria: typing.Optional[typing.Sequence[PromptEvaluationCriteria]] = OMIT,
        new_turns_limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Run a conversation between the agent and a simulated user and stream back the response. Response is streamed back as partial lists of messages that should be concatenated and once the conversation has complete a single final message with the conversation analysis will be sent.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        simulation_specification : ConversationSimulationSpecification
            A specification detailing how the conversation should be simulated

        extra_evaluation_criteria : typing.Optional[typing.Sequence[PromptEvaluationCriteria]]
            A list of evaluation criteria to test

        new_turns_limit : typing.Optional[int]
            Maximum number of new turns to generate in the conversation simulation

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from elevenlabs import (
            AgentConfig,
            AsyncElevenLabs,
            ConversationSimulationSpecification,
        )

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.conversational_ai.agents.simulate_conversation_stream(
                agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
                simulation_specification=ConversationSimulationSpecification(
                    simulated_user_config=AgentConfig(
                        first_message="Hello, how can I help you today?",
                        language="en",
                        disable_first_message_interruptions=False,
                    ),
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.simulate_conversation_stream(
            agent_id,
            simulation_specification=simulation_specification,
            extra_evaluation_criteria=extra_evaluation_criteria,
            new_turns_limit=new_turns_limit,
            request_options=request_options,
        )
        return _response.data

    async def run_tests(
        self,
        agent_id: str,
        *,
        tests: typing.Sequence[SingleTestRunRequestModel],
        agent_config_override: typing.Optional[AdhocAgentConfigOverrideForTestRequestModel] = OMIT,
        branch_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetTestSuiteInvocationResponseModel:
        """
        Run selected tests on the agent with provided configuration. If the agent configuration is provided, it will be used to override default agent configuration.

        Parameters
        ----------
        agent_id : str
            The id of an agent. This is returned on agent creation.

        tests : typing.Sequence[SingleTestRunRequestModel]
            List of tests to run on the agent

        agent_config_override : typing.Optional[AdhocAgentConfigOverrideForTestRequestModel]
            Configuration overrides to use for testing. If not provided, the agent's default configuration will be used.

        branch_id : typing.Optional[str]
            ID of the branch to run the tests on. If not provided, the tests will be run on the agent default configuration.

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

        Returns
        -------
        GetTestSuiteInvocationResponseModel
            Successful Response

        Examples
        --------
        import asyncio

        from elevenlabs import AsyncElevenLabs, SingleTestRunRequestModel

        client = AsyncElevenLabs(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.conversational_ai.agents.run_tests(
                agent_id="agent_3701k3ttaq12ewp8b7qv5rfyszkz",
                tests=[
                    SingleTestRunRequestModel(
                        test_id="test_id",
                    )
                ],
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.run_tests(
            agent_id,
            tests=tests,
            agent_config_override=agent_config_override,
            branch_id=branch_id,
            request_options=request_options,
        )
        return _response.data

    @property
    def widget(self):
        if self._widget is None:
            from .widget.client import AsyncWidgetClient  # noqa: E402

            self._widget = AsyncWidgetClient(client_wrapper=self._client_wrapper)
        return self._widget

    @property
    def link(self):
        if self._link is None:
            from .link.client import AsyncLinkClient  # noqa: E402

            self._link = AsyncLinkClient(client_wrapper=self._client_wrapper)
        return self._link

    @property
    def knowledge_base(self):
        if self._knowledge_base is None:
            from .knowledge_base.client import AsyncKnowledgeBaseClient  # noqa: E402

            self._knowledge_base = AsyncKnowledgeBaseClient(client_wrapper=self._client_wrapper)
        return self._knowledge_base

    @property
    def llm_usage(self):
        if self._llm_usage is None:
            from .llm_usage.client import AsyncLlmUsageClient  # noqa: E402

            self._llm_usage = AsyncLlmUsageClient(client_wrapper=self._client_wrapper)
        return self._llm_usage
