[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Serverless technologies](index.md) > AI > Creating an AI agent with Yandex Cloud Functions

# Creating an AI agent using Yandex Cloud Functions

Learn how to use a [function](../../functions/concepts/function.md) from Cloud Functions with the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/) to create an [AI agent](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf), i.e., a personalized assistant integrated with Yandex Cloud AI Studio [text generation models](https://aistudio.yandex.ru/docs/en/ai-studio/concepts/generation/models) to provide generative responses.

In this tutorial, you will create a simple AI agent that uses a function from Cloud Functions to get weather information, interact with the Yandex Cloud AI Studio [language model](https://aistudio.yandex.ru/docs/en/ai-studio/concepts/generation/models), and, to add a touch of fun, respond to the user in [haiku](https://en.wikipedia.org/wiki/Haiku) form.

![create-ai-agent-function](../../_assets/tutorials/create-ai-agent-function.svg)

On the diagram:

1. The user sends a request to the AI agent. The Cloud Functions handler receives the request.
1. The Cloud Functions handler creates and runs the AI agent.
1. The AI agent requests additional weather data for a given city using the custom `get_weather()` function.
1. The AI agent sends the user request together with the extra context to the AI Studio text generation model.
1. A [service account](../../iam/concepts/users/service-accounts.md) authorizes the AI agent to access the AI Studio [Text Generation API](https://aistudio.yandex.ru/docs/en/ai-studio/text-generation/api-ref/index) using an [API key](../../iam/concepts/authorization/api-key.md).
1. The service account grants access to the [Yandex Lockbox](../../lockbox/index.md) secret with the service account API key to the function in Cloud Functions.
1. The function in Cloud Functions retrieves the service account API key from the Yandex Lockbox secret.
1. The AI Studio model sends the generated response to the AI agent.
1. The AI agent returns the response to the user.

The AI agent you create in this tutorial will be deployed in Yandex Cloud using Yandex Cloud Functions. You will also create resources to arrange access to the AI Studio model: a [service account](../../iam/concepts/users/service-accounts.md), a service account [API key](../../iam/concepts/authorization/api-key.md), a Yandex Lockbox [secret](../../lockbox/concepts/secret.md), and a [function](../../functions/concepts/function.md) in Cloud Functions.

You can create these resources [automatically](#automatic-setup) or [manually](#manual-setup).

## What an AI agent is and how to use it {#ai-agent-definition}

An AI agent is an AI-powered software assistant which can follow instructions, give answers to questions, and interact with users or other systems within a given context. Unlike standard generative models, AI agents can:

* Support personalized instructions and have a personality.
* Use external sources and third-party tools to gather information.
* Maintain conversation context.
* Perform multi-step actions to solve complex tasks.

### Why use serverless functions to work with AI agents {#why-serverless}

Functions offered by Cloud Functions provide multiple benefits when deploying AI agents:

* Scalability: Automatic scaling to accommodate the load.
* Cost-effectiveness: You only pay for the actual execution time.
* No infrastructure management required: You do not need to configure or maintain servers.
* Fast deployment: AI agents are easy to create and update.
* Multiple integration options: Simple connection to APIs and other Yandex Cloud services.


## Get your cloud ready {#before-begin}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).

### Required paid resources {#paid-resources}

The infrastructure support cost for this tutorial includes:
* Fee for using the function (see [Yandex Cloud Functions pricing](../../functions/pricing.md)).
* Fee for text generation (see [Yandex Cloud AI Studio pricing](https://aistudio.yandex.ru/docs/en/ai-studio/pricing)).
* Fee for storing the secret and operations with it (see [Yandex Lockbox pricing](../../lockbox/pricing.md)).
* Fee for logging operations and data storage in a [log group](../../logging/concepts/log-group.md) (see [Yandex Cloud Logging pricing](../../logging/pricing.md)) when using [Cloud Logging](../../logging/index.md).

## Automated AI agent deployment using SourceCraft CI/CD {#automatic-sourcecraft-setup}

Run a CI/CD workflow in [SourceCraft](https://sourcecraft.dev/portal/docs/en/) to automatically create all the required resources in your selected folder and deploy a ready-to-use AI agent for you to experiment with.

### Why SourceCraft CI/CD is the fastest and most secure way to deploy an AI agent {#why-sourcecraft}

SourceCraft provides multiple benefits when deploying AI agents:

* You do not need to set up a local development environment. All the required settings are configured remotely when running CI/CD workflows in SourceCraft.
* Deployment is secure as you do not need to store service account secrets locally. In SourceCraft, you can use a [service connection](https://sourcecraft.dev/portal/docs/en/sourcecraft/concepts/service-connections) to request short-living IAM tokens for accessing Yandex Cloud services.

To create an AI agent automatically using SourceCraft CI/CD:

1. [Fork](https://sourcecraft.dev/portal/docs/en/sourcecraft/operations/fork-work#create-fork) the [repository](https://sourcecraft.dev/yandex-cloud-examples/yc-serverless-ai-agent) with scripts for AI agent creation.

    The repository contains scripts for creating the following AI agent types:

    {% list tabs group=difficulty %}

    - Simple AI agent {#simple}

      The `create-simple-ai-agent-workflow` will create a simple AI agent which, when launched, returns information about the weather in Tokyo in haiku form.

    - Advanced AI agent {#advanced}

      The `create-advanced-ai-agent-workflow` will create an advanced AI agent which responds to user queries in haiku form. When there is no user query, the agent returns a response to the default query.

    - Translator agent {#complex}

      The `create-complex-ai-agent-workflow` will create a translator agent which can handle user queries for text translation to the specified language while maintaining the style and tone.

    {% endlist %}

1. [Configure a service connection](https://sourcecraft.dev/portal/docs/en/sourcecraft/operations/service-connections) in SourceCraft for access to your Yandex Cloud.

1. [Run a workflow](https://sourcecraft.dev/portal/docs/en/sourcecraft/operations/run-workflow-manually), e.g., `create-simple-ai-agent-workflow`.

1. Test the AI agent.

   You can view the function result in the [logs](https://sourcecraft.dev/portal/docs/en/sourcecraft/operations/ci-cd#check-ci-cd) of the SourceCraft CI/CD cube, e.g., for `create-simple-ai-agent-workflow`, this cube is named `deploy-simple-ai-agent`. In addition, you can [test the function](#test-function) in the Yandex Cloud management console.

1. If you no longer need the resources you created, [delete them](#clear-out).

## Creating an AI agent automatically {#automatic-setup}

Run a script to automatically create all the required resources in your selected folder and deploy a ready-to-use AI agent for you to experiment with.

To create an AI agent automatically:

1. [Install](../../cli/operations/install-cli.md) the Yandex Cloud CLI and [get authenticated](../../cli/operations/index.md#auth).
1. [Download and install Python](https://www.python.org/downloads/).
1. Clone the [repository](https://sourcecraft.dev/yandex-cloud-examples/yc-serverless-ai-agent) with scripts for creating the AI agent:

    ```bash
    git clone https://git@git.sourcecraft.dev/yandex-cloud-examples/yc-serverless-ai-agent.git
    ```

    The repository contains scripts for creating three types of AI agents:

    {% list tabs group=difficulty %}

    - Simple AI agent {#simple}

      The `create-simple-ai-agent.py` script will create a simple AI agent which returns information about the weather in Tokyo in haiku form when you run it.

    - Advanced AI agent {#advanced}

      The `create-advanced-ai-agent.py` script will create an advanced AI agent which responds to user queries in haiku form. When there is no user request, the agent returns a response to the default request.

    - Translator agent {#complex}

      The `create-complex-ai-agent.py` script will create a translator agent which can handle user queries for text translation to the specified language while maintaining the style and tone.

    {% endlist %}

1. Make the script file executable. Here is an example:

    ```bash
    chmod +x create-simple-ai-agent.py
    ```
1. Run the script:

    ```bash
    ./create-simple-ai-agent.py
    ```

    While the script is running, specify your cloud and folder details, then wait until the resources are created.
1. Test the AI agent.

    {% list tabs group=difficulty %}

    - Simple AI agent {#simple}

      [Test](#test-function) the function in the management console.

    - Advanced AI agent {#advanced}

      [Test](#test-function) the function in the management console.

      You can also test the function by sending a user query to the AI agent via the Yandex Cloud CLI. To do this, run this command and specify the function ID you obtained when creating the AI agent:

      ```bash
      echo '{"query": "What's the weather in Paris?"}' > request.json \
        yc serverless function invoke <function_ID> --data-file request.json
      ```

    - Translator agent {#complex}

      [Test](#test-function) the function in the management console.

      You can also test the function by sending a user query to the AI agent via the Yandex Cloud CLI. To do this, run this command and specify the function ID you obtained when creating the AI agent:

      ```bash
      echo '{"text": "Hello, world!", "target_language": "Russian", "tone": "friendly"}' > translate.json \
        yc serverless function invoke <function_ID> --data-file translate.json
      ```

    {% endlist %}

1. If you no longer need the resources you created, [delete them](#clear-out).


## Creating an AI agent manually {#manual-setup}

To create an AI agent manually using a function from Cloud Functions:

1. [Create a service account](#create-sa).
1. [Create an API key for your service account](#create-api-key).
1. [Create a Yandex Lockbox secret](#create-secret).
1. [Create a ZIP archive with the function code](#zip-archive).
1. [Create a function](#create-function).
1. [Test the function](#test-function).

If you no longer need the resources you created, [delete them](#clear-out).

## Create a service account {#create-sa}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you are going to create your infrastructure.
  1. Navigate to **Identity and Access Management**.
  1. Click **Create service account**.
  1. Name the service account: `function-sa`.
  1. Click ![plus](../../_assets/console-icons/plus.svg) **Add role** and select [`ai.languageModels.user`](https://aistudio.yandex.ru/docs/en/ai-studio/security/index#languageModels-user).
  1. Click **Create**.

- CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

  The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

  1. Create a service account named `function-sa` in the default folder:

      ```bash
      yc iam service-account create \
        --name function-sa
      ```

      Result:

      ```text
      done (1s)
      id: aje23dgspcpi********
      folder_id: b1gt6g8ht345********
      created_at: "2025-06-04T19:34:58.145514099Z"
      name: function-sa
      ```

      Save the service account ID (the `id` field value) and the folder ID (the `folder_id` field value), as you will need them later.

      For more information about the `yc iam service-account create` command, see the [CLI reference](../../cli/cli-ref/iam/cli-ref/service-account/create.md).

  1. Assign the `ai.languageModels.user` [role](https://aistudio.yandex.ru/docs/en/ai-studio/security/index#languageModels-user) for the folder to the created service account by specifying the folder and service account IDs you previously saved:

      ```bash
      yc resource-manager folder add-access-binding <folder_ID> \
        --role ai.languageModels.user \
        --subject serviceAccount:<service_account_ID>
      ```

      Result:

      ```text
      done (2s)
      effective_deltas:
        - action: ADD
          access_binding:
            role_id: ai.languageModels.user
            subject:
              id: aje23dgspcpi********
              type: serviceAccount
      ```

      For more information about the `yc resource-manager folder add-access-binding` command, see the [CLI reference](../../cli/cli-ref/resource-manager/cli-ref/folder/add-access-binding.md).

- API {#api}

  To create a service account, use the [create](../../iam/api-ref/ServiceAccount/create.md) REST API method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/Create](../../iam/api-ref/grpc/ServiceAccount/create.md) gRPC API call.

  To assign the service account the `ai.languageModels.user` role for the folder, use the [updateAccessBindings](../../resource-manager/api-ref/Folder/updateAccessBindings.md) REST API method for the [Folder](../../resource-manager/api-ref/Folder/index.md) resource or the [FolderService/UpdateAccessBindings](../../resource-manager/api-ref/grpc/Folder/updateAccessBindings.md) gRPC API call.

{% endlist %}


## Create an API key for your service account {#create-api-key}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Identity and Access Management** and select the `function-sa` service account you created earlier.
  1. In the top panel, click ![image](../../_assets/console-icons/plus.svg) **Create new key** and select **Create API key**.
  1. In the **Scope** field, select [`yc.ai.languageModels.execute`](../../iam/concepts/authorization/api-key.md#scoped-api-keys).
  1. Optionally, set **Expires at** for the API key.
  1. Click **Create**.
  1. Save the secret key, as you will need it to create a function.

      {% note alert %}

      After you close this dialog, the key value will no longer be available.

      {% endnote %}

- CLI {#cli}

  1. Create an API key for the `function-sa` service account:

      ```bash
      yc iam api-key create \
        --service-account-name function-sa \
        --scopes yc.ai.languageModels.execute
      ```

      Result:

      ```yaml
      api_key:
        id: ajemcpt92i9j********
        service_account_id: aje23dgspcpi********
        created_at: "2025-06-04T19:41:28.960624728Z"
        scope: yc.ai.languageModels.execute
        scopes:
          - yc.ai.languageModels.execute
      secret: AQVN1mZ6kUkzDCjhNJxmjDX6WeJdOlJv********
      ```

      The key value is shown only once. Save it now, as you will not be able to retrieve it again.

      For more information about the `yc iam api-key create` command, see the [CLI reference](../../cli/cli-ref/iam/cli-ref/api-key/create.md).

- API {#api}

  To create an API key, use the [create](../../iam/api-ref/ApiKey/create.md) REST API method for the [ApiKey](../../iam/api-ref/ApiKey/index.md) resource or the [ApiKeyService/Create](../../iam/api-ref/grpc/ApiKey/create.md) gRPC API call.

{% endlist %}


## Create a Yandex Lockbox secret {#create-secret}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Lockbox** and click **Create secret**.
  1. In the **Name** field, specify the secret name: `api-key-secret`.
  1. In the **Secret type** field, select `Custom`.
  1. In the **Key** field, enter the secret key: `api-key`.
  1. In the **Value** field, paste the secret key you obtained in the previous step.
  1. Click **Create**.

- CLI {#cli}

  1. Create a Yandex Lockbox secret named `api-key-secret` in the default folder by specifying the secret key obtained in the previous step:

      ```bash
      yc lockbox secret create \
        --name api-key-secret \
        --payload "[{'key': 'api-key', 'text_value': '<secret_key>'}]"
      ```

      Result:

      ```bash
      done (1s)
      id: e6q7c0n0n7ji********
      folder_id: b1gt6g8ht345********
      created_at: "2025-06-04T19:50:38.690Z"
      name: api-key-secret
      status: ACTIVE
      current_version:
        id: e6qhmal099ki********
        secret_id: e6q7c0n0n7ji********
        created_at: "2025-06-04T19:50:38.690Z"
        status: ACTIVE
        payload_entry_keys:
          - api-key
      ```

      For more information about the `yc lockbox secret create` command, see the [CLI reference](../../cli/cli-ref/lockbox/cli-ref/secret/create.md).

- API {#api}

  To create a secret, use the [create](../../lockbox/api-ref/Secret/create.md) REST API method for the [Secret](../../lockbox/api-ref/Secret/index.md) resource or the [SecretService/Create](../../lockbox/api-ref/grpc/Secret/create.md) gRPC API call.

{% endlist %}

### Grant read permissions for the secret contents to the service account {#grant-secret-access}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Lockbox** and select `api-key-secret` you created earlier.
  1. On the left-hand panel, select ![persons](../../_assets/console-icons/persons.svg) **Access bindings** and click **Assign roles**. In the window that opens:

      1. In the search bar, enter the name of the service account created earlier, `function-sa`, and select it from the search results.
      1. Click ![plus](../../_assets/console-icons/plus.svg) **Add role** and select [`lockbox.payloadViewer`](../../lockbox/security/index.md#lockbox-payloadViewer).
      1. Click **Save**.

- CLI {#cli}

  1. Assign the `lockbox.payloadViewer` [role](../../lockbox/security/index.md#lockbox-payloadViewer) for `api-key-secret` to the `function-sa` service account:

      ```bash
      yc lockbox secret add-access-binding \
          --name api-key-secret \
          --service-account-name function-sa \
          --role lockbox.payloadViewer
      ```

      For more information about the `yc lockbox secret add-access-binding` command, see the [CLI reference](../../cli/cli-ref/lockbox/cli-ref/secret/add-access-binding.md).

- API {#api}

  To assign a role for a secret to the service account, use the [setAccessBindings](../../lockbox/api-ref/Secret/setAccessBindings.md) REST API method for the [Secret](../../lockbox/api-ref/Secret/index.md) resource or the [SecretService/SetAccessBindings](../../lockbox/api-ref/grpc/Secret/setAccessBindings.md) gRPC API call.

{% endlist %}

## Create a ZIP archive with the function code {#zip-archive}

1. Save the following code to a file named `index.py`:

    {% list tabs group=difficulty %}

    - Simple AI agent {#simple}

      ```python
      import os

      from openai import AsyncOpenAI

      from agents import (
          Agent,
          OpenAIChatCompletionsModel,
          Runner,
          function_tool,
          set_tracing_disabled,
      )

      BASE_URL = os.getenv("BASE_URL")
      API_KEY = os.getenv("API_KEY")
      MODEL_NAME = os.getenv("MODEL_NAME")

      client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)
      set_tracing_disabled(disabled=True)


      @function_tool
      def get_weather(city: str):
          print(f"[debug] getting weather for {city}")
          return f"The weather in {city} is sunny."


      async def handler(event, context):
          agent = Agent(
              name="Assistant",
              instructions="You only respond in haikus.",
              model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client),
              tools=[get_weather],
          )

          result = await Runner.run(agent, "What's the weather in Tokyo?")

          return {
              "statusCode": 200,
              "body": result.final_output,
          }
      ```

    - Advanced AI agent {#advanced}

      ```python
      import os
      import json

      from openai import AsyncOpenAI

      from agents import (
          Agent,
          OpenAIChatCompletionsModel,
          Runner,
          function_tool,
          set_tracing_disabled,
      )

      BASE_URL = os.getenv("BASE_URL")
      API_KEY = os.getenv("API_KEY")
      MODEL_NAME = os.getenv("MODEL_NAME")

      client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)
      set_tracing_disabled(disabled=True)


      @function_tool
      def get_weather(city: str):
          print(f"[debug] getting weather for {city}")
          return f"The weather in {city} is sunny."


      async def handler(event, context):
          # Extracting the user request from the event
          user_query = "What's the weather today?"  # Default request
          
          try:
              # Attempting to get the request from the event body
              if event and isinstance(event, dict):
                  body = event.get('body')
                  if body:
                      # If `body ` is provided as a string (which is often the case during API Gateway calls)
                      if isinstance(body, str):
                          try:
                              body_json = json.loads(body)
                              if 'query' in body_json:
                                  user_query = body_json['query']
                          except json.JSONDecodeError:
                              pass  # Using the default request if `body` is not JSON
                      elif isinstance(body, dict) and 'query' in body:
                          user_query = body['query']
                  # If the request was provided directly to `event`:
                  elif 'query' in event:
                      user_query = event['query']
          except Exception as e:
              print(f"Request processing error: {e}")
              # Running the default request in case of an error
          
          print(f"Processed request: {user_query}")
          
          agent = Agent(
              name="Assistant",
              instructions="You only respond in haikus. Be creative and poetic.",
              model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client),
              tools=[get_weather],
          )

          result = await Runner.run(agent, user_query)

          return {
              "statusCode": 200,
              "body": result.final_output,
              "headers": {
                  "Content-Type": "application/json"
              }
          }
      ```

    - Translator agent {#complex}

      ```python
      import os
      import json
      import re
      from typing import Dict, List, Optional, Any

      from openai import AsyncOpenAI

      from agents import (
          Agent,
          OpenAIChatCompletionsModel,
          Runner,
          function_tool,
          set_tracing_disabled,
      )

      BASE_URL = os.getenv("BASE_URL")
      API_KEY = os.getenv("API_KEY")
      MODEL_NAME = os.getenv("MODEL_NAME")

      client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)
      set_tracing_disabled(disabled=True)

      # Dictionary with language codes to simplify input
      LANGUAGE_CODES = {
          "русский": "ru",
          "russian": "ru",
          "английский": "en",
          "english": "en",
          "французский": "fr",
          "french": "fr",
          "немецкий": "de",
          "german": "de",
          "испанский": "es",
          "spanish": "es",
          "итальянский": "it",
          "italian": "it",
          "китайский": "zh",
          "chinese": "zh",
          "японский": "ja",
          "japanese": "ja",
          "корейский": "ko",
          "korean": "ko",
          "арабский": "ar",
          "arabic": "ar",
          "португальский": "pt",
          "portuguese": "pt",
      }

      # Dictionary with tone codes
      TONE_TYPES = {
          "формальный": "formal",
          "formal": "formal",
          "неформальный": "informal",
          "informal": "informal",
          "дружеский": "friendly",
          "friendly": "friendly",
          "деловой": "business",
          "business": "business",
          "технический": "technical",
          "technical": "technical",
          "простой": "simple",
          "simple": "simple",
          "академический": "academic",
          "academic": "academic",
          "поэтический": "poetic",
          "poetic": "poetic",
          "разговорный": "conversational",
          "conversational": "conversational",
      }

      @function_tool
      def detect_language(text: str) -> dict:
          """Detects the language of the input text.
          
          Args:
              text: Text to analyze
              
          Returns:
              Dictionary with detected language and its code
          """
          # This function uses model capabilities to determine the language
          # In a real application, you could use specialized libraries for more accurate detection
          
          common_words = {
              "en": ["the", "and", "of", "to", "in", "a", "is", "that", "for", "it", "with", "as", "was", "on"],
              "ru": ["и", "в", "не", "на", "что", "с", "по", "это", "я", "он", "как", "из", "то", "а", "все", "так"],
              "fr": ["le", "la", "les", "un", "une", "et", "de", "des", "du", "dans", "en", "est", "que", "pour", "qui"],
              "de": ["der", "die", "das", "und", "in", "von", "mit", "den", "zu", "ist", "für", "auf", "dem", "nicht"],
              "es": ["el", "la", "los", "las", "un", "una", "y", "de", "en", "que", "a", "por", "con", "no", "es"],
              "it": ["il", "la", "i", "le", "e", "di", "un", "una", "in", "che", "per", "con", "è", "non", "sono"],
          }
          
          # Simple detection by characteristic symbols and words
          text_lower = text.lower()
          
          # Check for Cyrillic characters (for Russian)
          if re.search('[а-яА-Я]', text):
              return {"language": "Russian", "code": "ru"}
          
          # Check for characters (for Chinese and Japanese)
          if re.search('[\u4e00-\u9fff]', text):
              return {"language": "Chinese", "code": "zh"}
          
          if re.search('[\u3040-\u309F\u30A0-\u30FF]', text):
              return {"language": "Japanese", "code": "ja"}
          
          # Check by common words
          word_counts = {}
          for lang, words in common_words.items():
              count = 0
              for word in words:
                  pattern = r'\b' + re.escape(word) + r'\b'
                  count += len(re.findall(pattern, text_lower))
              word_counts[lang] = count
          
          # Determine the language with the most matches
          if word_counts:
              detected_code = max(word_counts.items(), key=lambda x: x[1])[0]
              language_names = {
                  "en": "English",
                  "ru": "Russian",
                  "fr": "French",
                  "de": "German",
                  "es": "Spanish",
                  "it": "Italian",
              }
              return {"language": language_names.get(detected_code, "Unknown"), "code": detected_code}
          
          # Default to English
          return {"language": "Unknown (assuming English)", "code": "en"}

      @function_tool
      def translate_text(text: str, target_language: str, source_language: Optional[str] = None, tone: Optional[str] = None) -> str:
          """Translates text to the specified language while preserving tone and style.
          
          Args:
              text: Text to translate
              target_language: Target language for translation (code or name)
              source_language: Source language of the text (code or name, optional)
              tone: Desired tone of translation (formal, informal, business, etc., optional)
              
          Returns:
              Translated text
          """
          # This function would use LLM for translation in reality
          # Here we just return information about the request for demonstration
          
          # Normalize language codes
          target_code = LANGUAGE_CODES.get(target_language.lower(), target_language.lower())
          source_code = None
          if source_language:
              source_code = LANGUAGE_CODES.get(source_language.lower(), source_language.lower())
          
          # Normalize tone
          tone_type = None
          if tone:
              tone_type = TONE_TYPES.get(tone.lower(), tone.lower())
          
          # Return information for LLM to perform translation
          # In a real application, you could call a specialized translation API here
          return {
              "text": text,
              "target_language_code": target_code,
              "source_language_code": source_code,
              "tone": tone_type,
              "length": len(text)
          }

      async def handler(event, context):
          """Function handler"""
          try:
              # Get text for translation and parameters from the request
              text = None
              target_language = None
              source_language = None
              tone = None
              
              # Process different formats of incoming data
              if event and isinstance(event, dict):
                  body = event.get('body')
                  
                  if body:
                      # If body is passed as a string (common when called via API Gateway)
                      if isinstance(body, str):
                          try:
                              body_json = json.loads(body)
                              text = body_json.get('text')
                              target_language = body_json.get('target_language')
                              source_language = body_json.get('source_language')
                              tone = body_json.get('tone')
                          except json.JSONDecodeError:
                              # Maybe it's just text for translation
                              text = body
                      elif isinstance(body, dict):
                          text = body.get('text')
                          target_language = body.get('target_language')
                          source_language = body.get('source_language')
                          tone = body.get('tone')
                  else:
                      # If parameters are passed directly in the event
                      text = event.get('text')
                      target_language = event.get('target_language')
                      source_language = event.get('source_language')
                      tone = event.get('tone')
              
              # Check required parameters
              if not text:
                  return {
                      "statusCode": 400,
                      "body": json.dumps({"error": "Missing 'text' parameter (text to translate)"}),
                      "headers": {"Content-Type": "application/json"}
                  }
              
              if not target_language:
                  return {
                      "statusCode": 400,
                      "body": json.dumps({"error": "Missing 'target_language' parameter (target language)"}),
                      "headers": {"Content-Type": "application/json"}
                  }
                  
              # Create request for AI agent
              user_query = f"Translate the following text to {target_language}:"
              if source_language:
                  user_query += f" from {source_language}"
              if tone:
                  user_query += f". Preserve the {tone} tone and style of the original"
              user_query += f"\\n\\n{text}"
              
              # Set up AI agent
              agent = Agent(
                  name="TranslatorAssistant",
                  instructions="""You are a professional translator assistant who can translate text between different languages 
      while preserving the original tone, style, and context. 

      Your tools:
      1. detect_language - to identify the language of the input text
      2. translate_text - to translate text to the target language

      You should:
      - Understand the tone and style of the original text
      - Preserve formatting, including paragraphs, bullet points, and special symbols
      - Keep names, terms, and brand names unchanged unless translation is specifically required
      - When translating technical or specialized content, use appropriate terminology
      - Be sensitive to cultural context and adapt idioms appropriately
      - For formal documents, maintain formal language in the translation
      - For creative content, preserve the creative elements in the translation

      When responding:
      1. Provide the translation
      2. If requested or if there are important notes about the translation, briefly mention them
      3. Be concise and focus on accurate translation""",
                  model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client),
                  tools=[detect_language, translate_text],
              )

              # Run the agent
              result = await Runner.run(agent, user_query)
              
              # Format the response
              return {
                  "statusCode": 200,
                  "body": json.dumps({
                      "translation": result.final_output,
                      "original_text": text,
                      "target_language": target_language,
                      "source_language": source_language,
                      "tone": tone
                  }, ensure_ascii=False),
                  "headers": {"Content-Type": "application/json; charset=utf-8"}
              }
              
          except Exception as e:
              print(f"Request processing error: {str(e)}")
              return {
                  "statusCode": 500,
                  "body": json.dumps({"error": f"Internal server error: {str(e)}"}),
                  "headers": {"Content-Type": "application/json"}
              }
      ```

    {% endlist %}

1. Save the following code to a file named `requirements.txt`:

    ```text
    openai-agents
    ```
1. Add the `index.py` and `requirements.txt` files to a ZIP archive named `openai-function.zip`.


## Create a function {#create-function}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Cloud Functions**.
  1. Create a function:
     1. Click **Create function**.
     1. In the window that opens, enter `ai-agent-function` as the function name.
     1. Click **Create**.
  1. Create a [function version](../../functions/concepts/function.md#version):
     1. Select `Python 3.12` as the runtime, disable **Add files with code examples**, and click **Continue**.
     1. In the **Code source** field, select `ZIP archive` and attach the `openai-function.zip` file you created earlier.
     1. Specify the entry point: `index.handler`.
     1. Under **Parameters**, specify:
         * **Timeout**: `5 minutes`.
         * **Memory**: `128 MB`.
         * **Service account**: Select the `function-sa` service account.
         * **Environment variables**:
             * `FOLDER_ID`: [ID of the folder](../../resource-manager/operations/folder/get-id.md) where you are creating the infrastructure.
             * `MODEL_NAME`: URI of the Yandex Cloud AI Studio text generation [model](https://aistudio.yandex.ru/docs/en/ai-studio/concepts/generation/models#generation).

                 Here is an example: `gpt://<folder_ID>/yandexgpt/latest`.
                
                 Specify the ID of the folder you are creating the infrastructure in.
             * `BASE_URL`: Yandex Cloud AI Studio URL, `https://ai.api.cloud.yandex.net/v1`.

         * **Lockbox secrets**:
             * In the **Environment variable** field, specify `API_KEY` and select the previously created `api-key-secret`, its version, and `api-key`.
        * If you prefer to opt out of logging so as not to pay for Cloud Logging, disable **Write logs**.
     1. Click **Save changes**.

- CLI {#cli}

  1. Create a function named `ai-agent-function` in the default folder:

      ```bash
      yc serverless function create \
       --name ai-agent-function
      ```

      Result:

      ```text
      id: d4edhic2qf3i********
      folder_id: b1gt6g8ht345********
      created_at: "2025-06-04T20:02:14.741Z"
      name: ai-agent-function
      http_invoke_url: https://functions.yandexcloud.net/d4edhic2qf3i********
      status: ACTIVE
      ```

      For more information about the `yc serverless function create` command, see the [CLI reference](../../cli/cli-ref/serverless/cli-ref/function/create.md).

  1. Create a [version](../../functions/concepts/function.md#version) of `ai-agent-function`:

      ```bash
      yc serverless function version create \
        --function-name ai-agent-function \
        --memory=128m \
        --execution-timeout=5m \
        --runtime=python312 \
        --entrypoint=index.handler \
        --service-account-id=<service_account_ID> \
        --environment FOLDER_ID="<folder_ID>",MODEL_NAME="gpt://<folder_ID>/yandexgpt/latest",BASE_URL="https://ai.api.cloud.yandex.net/v1" \
        --secret name=api-key-secret,key=api-key,environment-variable=API_KEY \
        --source-path=./openai-function.zip \
        --no-logging
      ```

      Where:

      * `--service-account-id`: `function-sa` service account [ID](../../iam/operations/sa/get-id.md) you saved earlier.
      * `--environment`: Environment variables:

          * `FOLDER_ID`: [ID](../../resource-manager/operations/folder/get-id.md) of the folder you saved earlier when creating the service account.
          * `MODEL_NAME`: URI of the Yandex Cloud AI Studio text generation [model](https://aistudio.yandex.ru/docs/en/ai-studio/concepts/generation/models#generation).

                 Here is an example: `gpt://<folder_ID>/yandexgpt/latest`.
                
                 Specify the ID of the folder you are creating the infrastructure in.

          * `BASE_URL`: Yandex Cloud AI Studio URL, `https://ai.api.cloud.yandex.net/v1`.

      Result:

      ```text
      done (16s)
      id: d4e1vnnvhk5p********
      function_id: d4edhic2qf3i********
      created_at: "2025-06-04T20:09:59.675Z"
      runtime: python312
      entrypoint: index.handler
      resources:
        memory: "134217728"
      execution_timeout: 300s
      service_account_id: aje23dgspcpi********
      image_size: "14958592"
      status: ACTIVE
      tags:
        - $latest
      environment:
        FOLDER_ID: b1gt6g8ht345********
        BASE_URL: https://ai.api.cloud.yandex.net/v1
        MODEL_NAME: gpt://b1gt6g8ht345********/yandexgpt/latest
      secrets:
        - id: e6q7c0n0n7ji********
          version_id: e6qhmal099ki********
          key: api-key
          environment_variable: API_KEY
      log_options:
        disabled: true
        folder_id: b1gt6g8ht345********
      concurrency: "1"
      ```

      For more information about the `yc serverless function version create` command, see the [CLI reference](../../cli/cli-ref/serverless/cli-ref/function/version/create.md).

- API {#api}

  To create a function, use the [create](../../functions/functions/api-ref/Function/create.md) REST API method for the [Function](../../functions/functions/api-ref/Function/index.md) resource or the [FunctionService/Create](../../functions/functions/api-ref/grpc/Function/create.md) gRPC API call.

  To create a function version, use the [createVersion](../../functions/functions/api-ref/Function/createVersion.md) REST API method for the [Function](../../functions/functions/api-ref/Function/index.md) resource or the [FunctionService/CreateVersion](../../functions/functions/api-ref/grpc/Function/createVersion.md) gRPC API call.

{% endlist %}


## Test the function {#test-function}

{% list tabs group=difficulty %}

- Simple AI agent {#simple}

  1. In the [management console](https://console.yandex.cloud), select the folder where you created the infrastructure.
  1. Navigate to **Cloud Functions** and select the function you created.
  1. Navigate to the ![circle-play](../../_assets/console-icons/circle-play.svg) **Testing** tab.
  1. Click ![play-fill](../../_assets/console-icons/play-fill.svg) **Run test** and look up the test result.

      If the request is successful, the function status will change to `Done` and the output will contain the `200` status code and model response. Here is an example:

      ```json
      {
          "statusCode": 200,
          "body": "In Tokyo's sky,\nSunshine beams so bright and clear,\nWarmth fills the air."
      }
      ```

- Advanced AI agent {#advanced}

  1. Navigate to **Cloud Functions** and select the function you created.
  1. Navigate to the ![circle-play](../../_assets/console-icons/circle-play.svg) **Testing** tab.
  1. In the **Payload** field, specify:

      ```json
      {
        "query": "What's the weather in Paris?"
      }
      ```

  1. Click ![play-fill](../../_assets/console-icons/play-fill.svg) **Run test** and look up the test result.

      If the request is successful, the function status will change to `Done` and the output will contain the `200` status code and model response. Here is an example:

      ```json
      {
          "statusCode": 200,
          "body": "Paris skies so blue,\nSunshine warms the city's heart,\nBreathe in, feel the joy.",
          "headers": {
              "Content-Type": "application/json"
          }
      }
      ```

- Translator agent {#complex}

  1. Navigate to **Cloud Functions** and select the function you created.
  1. Navigate to the ![circle-play](../../_assets/console-icons/circle-play.svg) **Testing** tab.
  1. In the **Payload** field, specify:

      ```json
      {
        "text": "Hello, world!",
        "target_language": "Russian",
        "tone": "friendly"
      }
      ```

  1. Click ![play-fill](../../_assets/console-icons/play-fill.svg) **Run test** and look up the test result.

      If the request is successful, the function status will change to `Done` and the output will contain the `200` status code and model response. Here is an example:

      ```json
      {
          "statusCode": 200,
          "body": "{\"translation\": \"Привет, мир!\", \"original_text\": \"Hello, world!\", \"target_language\": \"Russian\", \"source_language\": null, \"tone\": \"friendly\"}",
          "headers": {
              "Content-Type": "application/json; charset=utf-8"
          }
      }
      ```

{% endlist %}


## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:
1. [Delete the function](../../functions/operations/function/function-delete.md).
1. [Delete the secret](../../lockbox/operations/secret-delete.md).
1. If you logged data to a log group, [delete the group](../../logging/operations/delete-group.md).