Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи? Написать
Дайджесты новостей
Проектирование API библиотек в эпоху AI-агентов: пять лет опыта создания открытых инструментов

Проектирование API библиотек в эпоху AI-агентов: пять лет опыта создания открытых инструментов

Широкое распространение языковых моделей и автономных AI-агентов, пишущих программный код, ставит перед разработчиками открытых библиотек совершенно новые требования. Традиционно проектирование публичного интерфейса (API) ориентировалось исключительно на человека, который мог вдумчиво прочитать документацию, догадаться об исключениях из контекста или перегрузить метод несколькими неявными аргументами. Для нейросетевых агентов такая неоднозначность становится источником системных галлюцинаций и бесконечных циклов исправления ошибок.

Проблема двусмысленности: почему один метод parse больше не работает

Создатель открытых инструментов для экосистемы TypeScript Дмитрий (автор библиотеки Sury) обобщил пятилетний опыт разработки и пришел к выводу: универсальные методы с неявным поведением должны уйти в прошлое.

Классический пример — единственный метод parse(data). Человек может помнить, что при невалидных данных этот метод выбрасывает синхронное исключение, или же ожидать, что он тихо вернет null. AI-агент, читая типы или краткие подсказки языкового сервера, часто делает неверное предположение о контроле ошибок: он забывает обернуть вызов в блок try-catch, что приводит к аварийному завершению всей программы.

Решением проблемы становится разделение контрактов по принципу явного намерения:

// Базовый контракт типобезопасного результата валидации
export type ExecutionResult<T> =
  | { success: true; value: T }
  | { success: false; issues: string[] };

export interface AgentFriendlySchema<T> {
  // Метод прямо декларирует в названии, что выбросит исключение при ошибке
  parseOrThrow(input: unknown): T;

  // Метод гарантирует безопасное исполнение и возврат типизированного контейнера
  parseAsResult(input: unknown): ExecutionResult<T>;
}

Когда сигнатура метода не оставляет сомнений в сценарии обработки сбоя, и человек, и языковая модель гарантированно выбирают правильный паттерн интеграции.

Разграничение предикатов типа и валидаторов

Второй важный архитектурный аспект — строгое разделение задач быстрой проверки формы данных (type guards) и глубокой валидации бизнес-правил.

Агенты часто пытаются использовать предикат типа is(value): value is T для сложной валидации, не понимая, почему они не получают списка конкретных ошибок. Расширим наш интерфейс схемы, добавив явное разделение между булевым защитником типов и полноценным валидатором:

// Развитие схемы: четкое разделение быстрого гарда и глубокого аудитора
export interface ExtendedAgentSchema<T> extends AgentFriendlySchema<T> {
  // Предикат типа: мгновенная проверка соответствия базовому типу
  is(input: unknown): input is T;

  // Валидатор: сбор всех нарушений бизнес-инвариантов без прерывания потока
  validate(input: unknown): { isValid: boolean; issues: string[] };
}

// Пример конкретной реализации для строковых параметров конфигурации
export const createTokenSchema = (expectedLength: number): ExtendedAgentSchema<string> => ({
  is(input: unknown): input is string {
    return typeof input === 'string' && input.length === expectedLength;
  },

  validate(input: unknown) {
    const issues: string[] = [];
    if (typeof input !== 'string') {
      issues.push('Значение должно иметь строковый тип');
      return { isValid: false, issues };
    }
    if (input.length !== expectedLength) {
      issues.push(`Ожидалась длина строки ${expectedLength}, получено ${input.length}`);
    }
    return { isValid: issues.length === 0, issues };
  },

  parseOrThrow(input: unknown): string {
    const check = this.validate(input);
    if (!check.isValid) {
      throw new Error(`Ошибка схемы: ${check.issues.join('; ')}`);
    }
    return input as string;
  },

  parseAsResult(input: unknown): ExecutionResult<string> {
    const check = this.validate(input);
    if (!check.isValid) {
      return { success: false, issues: check.issues };
    }
    return { success: true, value: input as string };
  },
});
Коридор успеха для моделей

Проектирование API под AI-агентов требует создания узкого «коридора успеха»: публичные функции должны иметь однозначные говорящие имена, а типы TypeScript — жестко направлять генерацию кода по единственному корректному пути.

В эпоху генеративного программирования качество библиотеки оценивается не только скоростью ее выполнения, но и тем, насколько сложно автономному агенту ошибиться при ее использовании.