Сборка AI-агента для редактирования изображений на Bedrock AgentCore + Stability AI | AiManual
AiManual Logo Ai / Manual.
07 Июл 2026 Гайд

Серверный AI-агент редактирования изображений: пошаговая сборка с Bedrock AgentCore и Stability AI

Пошаговое руководство по созданию серверного AI-агента для редактирования изображений с Bedrock AgentCore, Claude Sonnet и Stability AI. Развертывание через AWS

Вы когда-нибудь пытались объяснить дизайнеру, что нужно "чуть сместить объект вправо, сделать фон теплее и добавить легкое свечение"? Дизайнер кивает, через час присылает не то. Потом ещё час, снова не то. А если дизайнер — это AI, который понимает с первого раза и работает за секунды? Причём живёт не в забугорном API, а у вас на сервере, под полным контролем.

💡
Идея: объединить Bedrock AgentCore (оркестратор), Claude Sonnet v4 (интеллект) и Stability AI Diffusion 3.5 (генерация) в одного серверного агента, который принимает запросы на естественном языке и редактирует изображения. Фронтенд на React. Развёртывание — одна команда CDK.

Сегодня я соберу такого агента вживую. Без маркетинговой шелухи, исключительно код и архитектурные решения. Если вы работали с Agentic AI на Amazon Bedrock, половина покажется знакомой. Но редактирование изображений — зверь посложнее текстовых сценариев.

Почему серверный агент, а не очередной SaaS?

Сценарий: у вас внутренняя дизайн-студия, нужно обрабатывать тысячи изображений в день. Отправлять их в облачные сервисы — дорого, небезопасно (NDA, персданные), да ещё и задержки. Серверный агент, развёрнутый в вашем VPC, работает на ваших моделях (через Bedrock), латентность — миллисекунды, данные не уходят наружу. И он понимает контекст: "сделай как в прошлый раз, но с синим оттенком", а не просто "примени фильтр".

AgentCore — штука, которая в прошлом году перевернула представление об оркестрации. Вместо жестких DAG-ов и длинных цепочек Lambda — конфигурационный подход: описал инструменты (какие функции доступны), дал модели (Claude Sonnet) инструкцию, и агент сам решает, что вызвать и в каком порядке. CI/CD для таких агентов настраивается отдельно, но в этой статье мы развернём всё одной командой через CDK.

Архитектура: скелет нашего монстра

Осторожно: эта архитектура — не pet-проект. Это production-ready решение, которое я использую в реальном SaaS для автоматизации дизайна. Если вы хотите просто "поиграться" — можно упростить, но я покажу полную версию.

Компоненты:

  • Frontend (React + Chakra UI) — загрузка/просмотр изображений, отправка запросов на естественном языке, показ истории.
  • API Gateway + Lambda Authorizer — входная точка, проверка токенов.
  • Bedrock AgentCore — мозг, который принимает промпт пользователя, разбивает на шаги, вызывает инструменты.
  • Claude Sonnet v4 (2026) — модель reasoning, последняя версия от Anthropic через Bedrock. Понимает сложные инструкции про цвета, композицию, стили.
  • Stability AI Diffusion 3.5 (API через SageMaker или прямой вызов) — генерация и редактирование. На данный момент это самая мощная модель Stability с режимами inpaint, outpaint, img2img, controlnets.
  • Lambda функции (Python 3.12) — каждая обёртка вокруг одного действия: загрузить, применить inpaint, изменить фон, сохранить результат в S3.
  • S3 + DynamoDB — хранение исходников, результатов, метаданных.
  • AWS CDK (TypeScript) — инфраструктура как код, стек примерно на 200 строк.

Звучит громоздко? На деле деплой занимает 4 минуты.

Поехали: разворачиваем инфраструктуру

Предполагаю, что у вас есть аккаунт AWS, установлены AWS CLI, Node.js 20+, Python 3.12. Всё остальное подтянет CDK.

mkdir image-editor-agent && cd image-editor-agent
npx aws-cdk init app --language typescript
npm install @aws-cdk/aws-bedrock-alpha @aws-cdk/aws-lambda-python-alpha aws-cdk-lib

Теперь главный файл стека. Я опущу импорты и boilerplate, покажу суть — определение агента и инструментов.

// lib/image-editor-stack.ts

const agentRole = new Role(this, 'AgentRole', {
  assumedBy: new ServicePrincipal('bedrock.amazonaws.com'),
  managedPolicies: [
    ManagedPolicy.fromAwsManagedPolicyName('AmazonBedrockFullAccess'),
    ManagedPolicy.fromAwsManagedPolicyName('AWSLambda_FullAccess'),
  ],
});

const agent = new bedrock.CfnAgent(this, 'ImageEditorAgent', {
  agentName: 'image-editor-agent',
  agentResourceRoleArn: agentRole.roleArn,
  foundationModel: 'anthropic.claude-sonnet-4-20260408',
  instruction: `Ты — агент редактирования изображений.
  Получаешь запрос пользователя на естественном языке.
  Определяешь, какие инструменты нужно вызвать и в каком порядке.
  Если запрос многокомпонентный, разбивай на подзадачи.
  Всегда возвращай результат пользователю в понятном виде.`,
  actionGroups: [
    {
      actionGroupName: 'image-actions',
      // ... здесь ссылки на Lambda функции
    }
  ],
});

Ключевой момент: actionGroups — это конфигурация инструментов, которые видит модель. Каждая Lambda — это один инструмент. Агент сам решает, как их скомбинировать.

1 Lambda-функции: что внутри

Давайте разберём одну ключевую функцию — inpaint (замена части изображения).

# lambda/image_editor/inpaint.py

import boto3
import json
import base64
from urllib.parse import urlparse

bedrock_runtime = boto3.client('bedrock-runtime', region_name='us-east-1')
s3 = boto3.client('s3')

def handler(event, context):
    # event содержит поля: image_url, mask_url, prompt
    image_bytes = download_from_s3(event['image_url'])
    mask_bytes = download_from_s3(event['mask_url']) if event.get('mask_url') else None
    
    body = {
        "task_type": "inpainting",
        "prompt": event['prompt'],
        "image": base64.b64encode(image_bytes).decode(),
        "mask": base64.b64encode(mask_bytes).decode() if mask_bytes else None,
        "cfg_scale": 7,
        "steps": 50
    }
    
    response = bedrock_runtime.invoke_model(
        modelId='stability.stable-diffusion-3-5-large',
        contentType='application/json',
        accept='application/json',
        body=json.dumps(body)
    )
    
    result = json.loads(response['body'].read())
    output_image = base64.b64decode(result['artifacts'][0]['base64'])
    
    result_url = upload_to_s3(output_image, event.get('output_bucket'))
    return {
        'statusCode': 200,
        'body': json.dumps({'result_url': result_url})
    }

Почему именно Stability Diffusion 3.5 Large? Потому что на июль 2026 это единственная модель в Bedrock, которая одновременно поддерживает inpaint, outpaint, controlnet и img2img с качеством, близким к Midjourney. Плюс latency — около 3 секунд на генерацию 1024x1024. Для серверного сценария идеально.

Аналогично пишем функции change_background, upscale, apply_style. Каждая принимает JSON события от AgentCore, делает вызов Stability, сохраняет результат в S3 и возвращает URL.

2 Конфигурация инструментов в AgentCore

Вернёмся к стеку. Пропишем action group, который свяжет агента с Lambda.

const inpaintFn = new python_lambda.PythonFunction(this, 'InpaintFn', {
  entry: 'lambda/image_editor',
  index: 'inpaint.py',
  handler: 'handler',
  runtime: Runtime.PYTHON_3_12,
  timeout: Duration.seconds(60),
  memorySize: 1024,
});

// ... остальные функции

agent.actionGroups = [
  {
    actionGroupName: 'image-edit-tools',
    actionGroupExecutor: {
      lambda: inpaintFn.functionArn,
    },
    functionSchema: {
      functions: [
        {
          name: 'inpaint',
          description: 'Replace a region of the image with new content based on a prompt. Requires image URL and mask URL.',
          parameters: {
            image_url: { type: 'string', description: 'S3 URL of the original image' },
            mask_url: { type: 'string', description: 'S3 URL of the mask (white area = replace)' },
            prompt: { type: 'string', description: 'Description of what to generate in the masked area' },
          },
        },
        {
          name: 'change_background',
          description: 'Replace the background of an image. Automatically detects subject.',
          parameters: {
            image_url: { type: 'string' },
            prompt: { type: 'string', description: 'New background description' },
          },
        },
      ],
    },
  },
];

Обратите внимание: AgentCore автоматически генерирует OpenAPI-схему для каждого инструмента. Claude Sonnet читает её и решает, какие параметры передать. Если вы допустите ошибку в типе (например, скажете, что параметр integer, а передадите строку), модель может сгенерировать невалидный вызов. Проверяйте схемы тщательно.

Типичная ошибка: описать параметр mask_url как обязательный, но не предусмотреть, что пользователь может захотеть inpaint без маски (модель сгенерирует маску сама). Лучше сделать mask_url опциональным, а внутри Lambda добавить логику: если маски нет — используем автоматическую сегментацию.

3 Фронтенд: React-приложение, которое общается с агентом

Не буду писать весь компонент, покажу ключевой момент — как отправлять запрос и получать результат.

// frontend/src/App.jsx

import { useState } from 'react';
import { invokeAgent } from './bedrockClient';

function App() {
  const [prompt, setPrompt] = useState('');
  const [image, setImage] = useState(null);
  const [result, setResult] = useState(null);

  const handleSubmit = async () => {
    // 1. Загружаем изображение в S3 через presigned URL
    const imageUrl = await uploadFile(image);

    // 2. Вызываем AgentCore через SDK
    const response = await invokeAgent({
      agentId: process.env.REACT_APP_AGENT_ID,
      agentAliasId: process.env.REACT_APP_ALIAS_ID,
      sessionId: 'session-' + Date.now(),
      inputText: `${prompt} для изображения ${imageUrl}`, 
    });

    // 3. Парсим ответ
    setResult(parseAgentResponse(response));
  };

  return (
    <div className="p-8">
      <textarea value={prompt} onChange={e => setPrompt(e.target.value)} 
                placeholder="Опиши, что изменить..." 
                className="w-full p-4 border rounded" />
      <input type="file" onChange={e => setImage(e.target.files[0])} />
      <button onClick={handleSubmit} className="bg-indigo-600 text-white px-6 py-2 rounded">
        Отправить агенту
      </button>
      {result && <img src={result} alt="Edited" />}
    </div>
  );
}

Функция invokeAgent использует AWS SDK v3 для вызова Bedrock Agent Runtime. Важно: агент может вернуть не только финальный ответ, но и промежуточные шаги. Например, он сообщит: "Сначала удалю фон, затем применю фильтр, затем увеличу резкость". Пользователю это показывать не обязательно, но для отладки — gold.

Деплой одной командой

cdk bootstrap
cdk deploy --all

После деплоя вы получите в выводе:
- Agent ID и Alias ID (для фронтенда)
- URL API Gateway (если вы добавили REST API для прямого вызова)
- S3 bucket для изображений.

Теперь можно открыть фронтенд (локально или на Amplify) и попробовать: "Сделай из этой фотографии стиль киберпанк, фон замени на неоновый город, а на переднем плане добавь дождь". Агент сам решит: сначала change_background, потом apply_style, потом inpaint для дождя.

Нюансы, которые взорвут вам мозг (и как их избежать)

1. Таймауты

AgentCore по умолчанию ждёт ответ от Lambda 30 секунд. Если ваша модель Stability генерирует 15 секунд, а ещё есть загрузка/скачивание, легко превысить лимит. Решение: увеличьте timeout в CDK до 5 минут, а в конфигурации агента установите idleSessionTTLInSeconds не меньше 600.

2. Стоимость

Каждый вызов Stability Diffusion 3.5 Large стоит около $0.08 за изображение 1024x1024. Агент может сделать несколько вызовов на один запрос (например, 3 инструмента). Плюс $0.003 за каждый вызов Claude Sonnet. Итог: $0.25-0.30 за сложное редактирование. Для 10 000 запросов в месяц — $3000. Дороговато? Для бизнеса, который раньше платил дизайнерам $10 000 — дешево.

3. Безопасность маски

Пользователь может загрузить маску, которая выходит за границы изображения, или маску с некорректным альфа-каналом. Валидируйте на Lambda: если размеры не совпадают — возвращайте ошибку с понятным сообщением. Иначе агент будет повторять вызов с теми же данными, тратя деньги.

А что с тестированием всего этого?

Если вы думаете, что запустить агента в прод без тестов — хорошая идея, то вы никогда не видели, как Claude Sonnet вместо изменения цвета генерирует "извините, я не могу выполнить этот запрос из-за политики безопасности". Да, такое бывает. Тестирование агентов с LangSmith и pytest — единственный способ спать спокойно.

Что дальше? (спойлер: мультимодальность)

Уже сейчас можно расширить агента: добавить инструменты для анализа изображения (Claude Vision), чтобы агент сам понимал, что на фото, и предлагал варианты. Или добавить поддержку видео — Stability AI недавно выпустила модель для генерации коротких клипов. Но это уже тема для отдельной статьи.

Главный инсайт, который я вынес из этого проекта: AgentCore — это не просто замена Step Functions. Это сдвиг парадигмы: вы перестаёте программировать логику вызовов, а просто описываете, что умеют ваши инструменты, и модель сама прокладывает путь. Чем точнее описаны инструменты, тем реже агент ошибается. Инвестируйте время в качество описаний параметров — это окупится сторицей.

Подписаться на канал