AI research assistant на AWS Strands за 30 строк кода — туториал | AiManual
AiManual Logo Ai / Manual.
31 Май 2026 Гайд

Создание AI research assistant с AWS Strands: туториал за 30 строк кода

Пошаговое руководство по созданию AI-агента-исследователя с AWS Strands и Kiro IDE. Минимум кода, максимум пользы. Реальный пример за 30 строк Python.

Зачем писать 500 строк, если можно 30?

Сколько кода нужно, чтобы собрать настоящего AI-агента, который не просто болтает, а ходит в интернет, читает документы и пишет резюме? Если вы когда-нибудь пробовали склепать research assistant на базе LangChain или собственного бойлерплейта, то знаете: 500 строк — это минимум, и половина из них — обработка ошибок и конфиги. А потом выясняется, что агент галлюцинирует при поиске дат, а веб-скрапинг ломается на первом же рекапче.

AWS увидели эту боль и в начале 2026 года запустили Strands Agents SDK — набор высокоуровневых абстракций поверх Amazon Bedrock и Step Functions. А вместе с ним — Kiro IDE, среду разработки, где можно запустить агента одной кнопкой и сразу увидеть логи. Никаких 'docker-compose up', никаких 15 переменных окружения. Просто код, который работает.

В этом туториале я покажу, как за 30 строк Python сделать research assistant, который ищет последние новости по теме, анализирует PDF-файлы и выдаёт структурированный ответ. И да, это не игрушка — на выходе вы получите готового агента, который можно запускать в AWS Lambda (если не лень добавить ещё 10 строк для деплоя).

Знакомьтесь: AWS Strands — агентный SDK, который не бесит

Strands — это не очередной ORM для AI. Это SDK, который берёт на себя оркестрацию вызовов LLM, управление памятью, повторные попытки и инструменты (tools). Всё, что вы делали через invoke_model в Bedrock, теперь выглядит как вызов обычной функции.

  • Типизированные инструменты — вы объявляете функцию с Pydantic-схемой, и Strands сам генерирует для модели описание tool’a.
  • Встроенная RAG — подключение векторной базы (OpenSearch Serverless или Amazon Aurora) через одну строку конфига.
  • Multi-agent orchestration — можно навесить супервизора без костылей.
  • Observability out-of-the-box — трейсинг через X-Ray и логи в CloudWatch, не нужно ничего лепить.

На момент 31.05.2026 актуальная версия Strands SDK — 2.1.0. В Kiro IDE он предустановлен, так что никакой возни с pip.

Kiro IDE — среда, где магия случается

Kiro — это что-то вроде VS Code, но с интегрированным AI-интерпретатором. Вы пишете код, нажимаете Run Agent, и IDE сама поднимает временную инфраструктуру (через AWS CDK в фоне), запускает агента и показывает стрим мыслей модели. Если что-то пошло не так — можно ткнуть в лог и сразу увидеть, какой tool вернул ошибку.

Для нашего туториала не придётся ничего настраивать вручную — только убедиться, что у вас есть AWS-аккаунт с доступом к Bedrock (модели Claude 3.5 Sonnet v2 или Nova Pro 2.0 — обе доступны по умолчанию).

Туториал: research assistant за 30 строк

Давайте сразу к делу. Откройте Kiro IDE, создайте новый Python-файл research_assistant.py и скопируйте код ниже. Я разберу его по шагам.

1 Установка и импорты

В Kiro IDE все зависимости уже установлены, но для локального запуска (вне IDE) выполните:

pip install aws-strands-sdk pypdf2 httpx

Сам код начинается с импорта:

from strands import Agent, tool
from strands.tools import WebSearch, PDFReader
from pydantic import BaseModel
import httpx

2 Объявляем инструменты

Strands SDK сам умеет вызывать Amazon Bedrock Knowledge Bases, веб-поиск через Exa (провайдер по умолчанию) и читать файлы из S3. Но я хочу показать, как добавить кастомный инструмент — поиск статей по API. Например, будем ходить на NewsAPI (или HackerNews — выбирайте).

class NewsQuery(BaseModel):
    topic: str
    max_results: int = 5

@tool(schema=NewsQuery, description="Ищет последние новости по теме через NewsAPI")
async def fetch_news(query: NewsQuery) -> list[dict]:
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            "https://newsapi.org/v2/everything",
            params={
                "q": query.topic,
                "pageSize": query.max_results,
                "apiKey": "${NEWS_API_KEY}", # подставится из переменных окружения
                "sortBy": "publishedAt"
            }
        )
        return resp.json().get("articles", [])

Обратите внимание на аннотацию @tool — она сообщает Strands, что это функция, которую модель может вызвать. Схема аргументов извлекается из Pydantic-модели автоматически.

3 Создаём агента

agent = Agent(
    model="bedrock/anthropic.claude-3-5-sonnet-v2:0",
    tools=[fetch_news, WebSearch(), PDFReader(source="s3://my-bucket/reports/*.pdf")],
    instructions="Ты — эксперт-аналитик. Отвечай на русском, используй факты из новостей и PDF."
)

Всего три строки, а внутри: модель Claude 3.5 Sonnet v2 (доступна в Bedrock), три инструмента — наш кастомный, встроенный веб-поиск и ридер PDF из S3-бакета. Инструкции передаются в system prompt.

4 Запускаем ассистента

async def main():
    result = await agent.run(
        "Найди новости за последнюю неделю по теме 'AI-агенты AWS'. "
        "Сравни с данными из PDF 'competitors.pdf' и напиши краткий отчёт."
    )
    print(result)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Всё. Агент сам решит, какие инструменты вызвать, в каком порядке. Он может сначала сходить в веб-поиск за новостями, потом прочитать PDF, потом снова поискать, если нужно. Мы же просто получаем финальный ответ.

5 Полный код (30 строк)

from strands import Agent, tool
from strands.tools import WebSearch, PDFReader
from pydantic import BaseModel
import httpx

class NewsQuery(BaseModel):
    topic: str
    max_results: int = 5

@tool(schema=NewsQuery, description="Ищет последние новости по теме через NewsAPI")
async def fetch_news(query: NewsQuery) -> list[dict]:
    async with httpx.AsyncClient() as client:
        resp = await client.get("https://newsapi.org/v2/everything",
            params={"q": query.topic, "pageSize": query.max_results,
                    "apiKey": "${NEWS_API_KEY}", "sortBy": "publishedAt"})
        return resp.json().get("articles", [])

agent = Agent(
    model="bedrock/anthropic.claude-3-5-sonnet-v2:0",
    tools=[fetch_news, WebSearch(), PDFReader(source="s3://my-bucket/reports/*.pdf")],
    instructions="Ты — эксперт-аналитик. Отвечай на русском, используй факты из новостей и PDF."
)

async def main():
    result = await agent.run("Найди новости за последнюю неделю по теме 'AI-агенты AWS'. Сравни с данными из PDF 'competitors.pdf' и напиши краткий отчёт.")
    print(result)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Строк меньше тридцати? Да, если не считать пустые строки и импорты — всё честно. И это полноценный research assistant, который работает в облаке.

Что под капотом? Почему это работает?

Strands SDK при вызове agent.run() делает примерно следующее:

  • Формирует request в Amazon Bedrock, включая описания всех tools (в формате OpenAI tool calling, но адаптированные под Bedrock Converse API).
  • Получает ответ — если модель хочет вызвать инструмент, Strands извлекает имя и аргументы, выполняет функцию, заворачивает результат обратно и отправляет модели следующий запрос.
  • Так продолжается, пока модель не вернёт финальный текстовый ответ.
  • Все вызовы инструментов логируются, таймауты контролируются, ошибки повторяются (retry policy по умолчанию — 3 попытки).

За кулисами Strands использует AWS Step Functions для оркестрации долгих цепочек (чтобы не держать Lambda активной всё время), а Kiro IDE ещё и поднимает временную EventBridge-шину для дебага. Если вам нужен production — просто экспортируете агента в гибридный RAG с Amazon Bedrock и OpenSearch, прикручиваете эндпоинт.

Типичные ошибки и как их избежать

Ошибка 1: Агент не видит PDF-файлы. Убедитесь, что S3-бакет находится в той же AWS-регионе, что и Strands (по умолчанию us-east-1). И что у роли, которую использует Kiro IDE, есть права s3:GetObject и s3:ListBucket.

Ошибка 2: Модель выбирает неправильный инструмент. Проверьте description у каждого tool — он критически важен. Чёткое описание типа “Ищет последние новости по теме через NewsAPI” vs “Просто получает данные” — разница в точности.

Ошибка 3: Превышен лимит шагов (Step Functions). По умолчанию Strands ограничивает цепочку 20 итерациями. Если ваш агент зацикливается — добавьте в инструкцию “Если не нашёл информацию, отвечай честно: ‘данные отсутствуют’”. Или поднимите лимит через agent.run(..., max_iterations=50).

Итог: когда 30 строк превращаются в production

Конечно, в реальном проекте вам понадобится обработка auth, мониторинг стоимости, rate limiting. Но сам каркас — выбор модели, привязка инструментов, запуск — укладывается в 30 строк. И это не просто демка: в моей команде мы запустили такого ассистента для анализа конкурентных отчётов, и он экономит аналитику 2 часа в день.

Если захотите пойти дальше — советую заглянуть в статью про прикручивание веб-поиска к Strands Agents SDK + Exa — там мы разбираем, как победить галлюцинации с помощью ранжирования источников. А если вас бесит бойлерплейт, посмотрите сборку на Bun за 30 минут — другой подход, но тоже лаконичный.

Кстати, если хотите прокачаться в создании AI-продуктов до уровня Senior, рекомендую курс AI-креатор: создаём контент с помощью нейросетей — там разбирают не только промпты, но и архитектуру агентов.

А теперь идите и соберите своего research assistant. Уверен, у вас уйдёт меньше времени, чем на чтение этой статьи.

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