Создание инструментов Opal для обработчика Stott Robots

Этим летом команда разработки Netcel и я приняли участие в Opal Hackathon Optimizely. Задача оптимизации состояла в том, чтобы расширить способности Opal, создавая инструменты, которые обертывают реальные бизнес -потоки, позволяя Opal сосредоточиться на входах и выходах в разговорном контексте. Наше первоначальное представление состояло в том, чтобы разработать инструменты для управления событиями, которые будут интегрироваться с оптимизированной системой управления контентом SaaS, оптимизированной платформой управления контентом и Eventbrite.

Optimizely создал SDK в C#, JavaScript и Python для ускорения процесса разработки инструментов OPAL, мы решили использовать C# SDK из -за знакомства с языком. Этот SDK требовал, чтобы мы создавали статические классы и методы, которые выполняли действия инструмента, в то время как сам SDK управлял маршрутизацией для инструментов и полностью предоставил конечную точку Discovery. После предоставления нескольких инструментов для хакатона я размышлял о SDK и о том, как он достиг наших целей. Поскольку маршрутизация управлялась SDK, она действительно ограничивала нашу способность создавать наши собственные контроллеры или рассмотреть другие варианты хостинга, такие как функции Azure. Как владелец и сопровождающий двух оптимизированных дополнений, я начал думать о том, как это может работать с надстройками Paas CMS.

Я пришел к выводу, что если бы я хотел добавить инструменты опала в свои дополнения, я бы подумал о том, чтобы не использовать SDK вообще по следующим причинам:

  • Чтобы избежать конфликта с реализациями CMS, которые имеют инструменты как часть их доставки.
  • Чтобы избежать конфликта с другими надстройками CMS, которые также пытались использовать SDK.
  • Чтобы сохранить обнаружение и конечные точки инструмента в той же структуре маршрутизации, что и остальная часть моего дополнения.
  • Чтобы применить пользовательскую проверку токена и контроллера.

Требования к инструменту опала

Когда мы рассматриваем, что инструменты Opal являются просто REST API с конкретным требованием JSON, мы понимаем, что это то, что мы доставляем в течение многих лет. По сути, есть два вкуса конечной точки; Конечная точка Discovery, которая описывает ваши инструменты для Opal, а затем сами ваши конечные точки инструмента.

Discovery Endpoint

Конечная точка Discovery должна вернуть объект JSON, содержащий множество функций. Каждая функция в этом массиве описывает инструмент, как показано ниже. Каждая запись должна указать имя, описание, конечную точку, массив параметров и желаемый метод HTTP. Описание особенно важно здесь, так как оно поможет Опалу понять объем и намерения вашего инструмента, принесение этого права очень важно.

  • имя: Это название вашего инструмента, и должно быть все одно слово и уникальное.
  • описание: Это описание поможет Opal понять намерение для вашего инструмента, важно, чтобы это имело значение.
  • параметры: Это список параметров, которые Опал должен отправить в вашу конечную точку.
    • имя: Это имя параметра, это должно соответствовать делу, в котором вы ожидаете получить данные.
    • описание: Это описание поможет Опалу понять, как и что он должен передать в этот параметр.
    • тип: Это говорит о Опале, какой тип данных он должен отправить вам.
    • необходимый: Это говорит Опал, если он должен или может предоставить этот параметр.
  • конечная точка: Это должна быть конечная точка для вашего API и должен относиться к Открытие конечная точка.
  • http_method: Это говорит о Opal, какой метод HTTP использовать.
  • auth_requirements: Это необязательный поле и может быть полностью опущено. Заполните это только в том случае, если вам нужна аутентификация для запуска вашего инструмента либо от Opal, либо с другим поставщиком идентификаторов.
    • поставщик: Имя поставщика идентификации.
    • scope_bundle: Запрашивается сфера разрешения.
    • необходимый: Индикатор относительно того, требуется ли этот метод аутентификации или нет.
Read more:  «Это приближает вас к миру природы»: популярность приложения для определения пения птиц Мерлина | Птицы

Get: /Discovery

{
    "functions": [
        {
            "name": "myuniquetoolname",
            "description": "This is a description of what this tool will do.",
            "parameters": [
                {
                    "name": "parameterOne",
                    "type": "string",
                    "description": "A description of what data should be passed into this parameter.",
                    "required": false
                }
            ],
            "endpoint": "/tools/tool-api-endpoint",
            "http_method": "POST",
            "auth_requirements": [
                {
                    "provider": "OptiID",
                    "scope_bundle": "tasks",
                    "required": true
                }
            ]
        }
    ]
}

💡 Совет: Opal не будет включать заголовок авторизации при выполнении запроса в конечную точку Discovery, поэтому убедитесь, что ваша реализация доступна анонимно.

Конечный пункт инструмента

Конечная точка для инструмента должна быть относительно конечной точки обнаружения, то есть она должна существовать под конечной точкой обнаружения. Если мы предположим, что конечная точка Discovery реагирует на https://www.example.com/path-one/discoveryи инструмент имеет конечную точку /инструменты/инструмент-один Затем Опал отправит запрос на https://www.example.com/path-one/tools/tool-oneПолем Следует отметить, что если вы зарегистрирует https://www.example.com/path-one/discovery/тогда Opal отправит запрос на https://www.example.com/path-ony/discovery/tools/tool-one вместо. Из -за этого вы можете проверить любые правила перенаправления в вашем решении, которые заставляют следы задержки и т. Д.

  • параметры: Это будет объект JSON, который обладает свойствами, соответствующими определенным параметрам инструмента.
    • Параметр: Это просто пример параметров; Ваши собственные параметры, определенные в конечной точке Discovery, появятся здесь.
  • аут: Это дополнительный объект и будет предоставлен только в том случае, если инструмент был указан как требующий конкретной аутентификации.
    • поставщик: Это будет название поставщика аутентификации.
    • реквизиты для входа: Это конкретные детали аутентификации.

Дополнительные элементы данных также включены как среда и CHAT_METADATAно они не важны для работы вашего инструмента и могут быть полезны для отслеживания операций. В следующем примере был объявлен инструмент, который имел Optiid в качестве требования аутентификации.

Сообщение: /Инструменты /Имя инструмента

{
	"parameters": {
		"parameterOne": "Some value"
	},
	"auth": {
		"provider": "OptiID",
		"credentials": {
			"token_type": "Bearer",
			"access_token": "...",
			"org_sso_id": null,
			"user_id": "...",
			"instance_id": "...",
			"customer_id": "...",
			"product_sku": "OPAL"
		}
	},
	"environment": {
		"execution_mode": "interactive"
	},
	"chat_metadata": {
		"thread_id": "e597710c-2d10-4f07-9817-6fad9f2b748d"
	}
}

Внедрение инструментов Opal

Реализация самой конечной точки Discovery – простая. Например, C# SDK использует отражение и понимает атрибуты, которые вы украшаете на своих инструментах. Поскольку в этом сценарии я не использую SDK, я мог бы либо отправить объект JSON с моим кодом, либо в этом случае создать классы, которые достигают того же результата. Я решил создать объекты DTO, которые будут сериализованы в нужную структуру JSON. Я украсил действие контроллера с помощью Httpget и AllingAnonymous Атрибуты, чтобы гарантировать, что конечная точка была общедоступна только для запросов на получение.

[HttpGet]
[AllowAnonymous]
[Route("/stott.robotshandler/opal/discovery/")]
public IActionResult Discovery()
{
    var model = new FunctionsRoot { Functions = new List() };

    model.Functions.Add(new Function
    {
        Name = "getrobottxtconfigurations",
        Description = "Get a collection of robot.txt configurations optionally filtered by host name.",
        Parameters = new List
        {
            new FunctionParameter
            {
                Name = "hostName",
                Type = "string",
                Description = "The host name to filter the robot.txt configurations by.",
                Required = false
            }
        },
        Endpoint = "/tools/get-robot-txt-configurations/",
        HttpMethod = "POST"
    });

    // More tools defined here...

    return CreateSafeJsonResult(model);
}

Поскольку я стремился поддерживать несколько конечных точек с той же структурой модели, я использовал дженерики для создания объекта с обертыванием, используя конкретную модель контента, требуемую моей конечной точкой. Затем это добавляется в качестве параметра для действий моего контроллера с Fombers Атрибут, чтобы убедиться, что модель была получена из корпуса запроса. Обратите внимание, что стоит указать Jsonpropertyname Атрибуты, так как вы не можете гарантировать параметры сериализации решения для хостинга.

public class ToolRequest where TModel : class
{
    [JsonPropertyName("parameters")]
    public TModel Parameters { get; set; }
}

public class GetRobotTextConfigurationsQuery
{
    [JsonPropertyName("hostName")]
    public string HostName { get; set; }
}

Если ваш инструмент должен быть передана в него аутентификацию, то вы можете расширить этот объект обертывания, чтобы содержать данные аутентификации, как SO:

public class AuthenticatedToolRequest where TModel : class
{
    [JsonPropertyName("parameters")]
    public TModel Parameters { get; set; }

    [JsonPropertyName("auth")]
    public AuthData Auth { get; set; }
}

public class AuthData
{
    [JsonPropertyName("provider")]
    public string Provider { get; set; } = string.Empty;

    [JsonPropertyName("credentials")]
    public Dictionary Credentials { get; set; } = new Dictionary();
}

В следующем примере я украсил свой контроллер атрибутом httppost, а затем двумя отдельными атрибутами маршрута. Это помогает моему контроллеру реагировать на обоих возможных пути запроса, в зависимости от того, была ли конечная точка Discovery зарегистрирована с помощью следа или нет. Я тогда использовал общий ToolRequest класс, чтобы обернуть мою конкретную модель GetRoBotTextConfigurationsQuery как параметр для метода.

[HttpPost]
[Route("/stott.robotshandler/opal/tools/get-robot-txt-configurations/")]
[Route("/stott.robotshandler/opal/discovery/tools/get-robot-txt-configurations/")]
[OpalAuthorization(OpalScopeType.Robots, OpalAuthorizationLevel.Read)]
public IActionResult GetRobotTxtConfigurations([FromBody] ToolRequest model)
{
    try
    {
        var configurations = _service.GetAll();
        if (!string.IsNullOrWhiteSpace(model?.Parameters?.HostName))
        {
            var hostName = model.Parameters.HostName.Trim();
            var specificConfiguration =
                configurations.FirstOrDefault(x => string.Equals(x.SpecificHost, hostName, StringComparison.OrdinalIgnoreCase)) ??
                configurations.FirstOrDefault(x => x.AvailableHosts.Any(h => string.Equals(h.HostName, hostName, StringComparison.OrdinalIgnoreCase)));

            if (specificConfiguration is null)
            {
                return Json(new
                {
                    Success = false,
                    Message = $"Could not locate a robots.txt config that matched the host name of {model.Parameters.HostName}."
                });
            }

            return Json(ConvertToModel(specificConfiguration, hostName, x => x.RobotsContent));
        }

        return Json(ConvertToModels(configurations, x => x.RobotsContent));
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "An error was encountered while processing the getrobottxtconfigurations tool.");
        throw;
    }
}

Вы, возможно, заметили, что мое действие контроллера также имеет Опалаутизация атрибут. Когда вы зарегистрируете свои инструменты в Opal в конечную точку Discovery, у вас есть возможность предоставить токен для носителя, который будет отправлен в заголовок авторизации. Это пользовательский атрибут, который проверяет наличие заголовка авторизации с токеном носителя и проверяет его на токен с определенным пользователем, определенным в моем дополнении. В моем дополнении я позволяю пользователю определять несколько токенов с различными разрешениями чтения/записи, как SO:

Read more:  Запишите на свой счет еще одну победу в SCOTUS для администрации Трампа – -

Завершая

В конце концов, инструменты Opal – это просто REST API с конкретным контрактом JSON. Прежде чем начать строить, стоит подтвердить, какой официальный SDK (JavaScript, Python или C#) лучше всего подходит вашему проекту. Они обеспечивают быстрый путь к работе и бегу. Если вы обнаружите, что ограничения SDK не соответствуют вашим варианту использования, создание собственных конечных точек без SDK дает вам полный контроль над маршрутизацией, аутентификацией и интеграцией с существующей кодовой базой. Это облегчает подключение инструментов к оптимизированным CMS или дополнениям, не беспокоясь о конфликтах и не учитывает без серверного хостинга, таких как функции Azure, если вы развертываете свои инструменты отдельно.

Если вы разработчик, работающий с оптимизированным, я бы посоветовал вам попробовать это самостоятельно. Начните с малого: Создайте конечную точку Discovery, определите инструмент с одним или двумя параметрами и посмотрите, как Opal называет его напрямую. Как только вы увидите, как он работает, у вас будет прочная основа для создания более продвинутых инструментов, адаптированных к вашим проектам.


Я OMVP и автор и сопровождающий Стотт Безопасность и Стотт -роботы для оптимизации CMS 12. Вы можете найти весь мой контент, собранный на https://www.stott.pro/

28 сентября 2025 года

Читайте также

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.