AWS 기술 블로그

Strands Agents 1.0 소개: 프로덕션에 간편하게 바로 적용 가능한 다중 에이전트 오케스트레이션

이 글은 AWS Open Source Blog에 게시된 ‘Introducing Strands Agents 1.0: Production-Ready Multi-Agent Orchestration Made Simple‘를 번역했습니다.

오늘 Strands Agents SDK 1.0 버전을 발표하게 되어 기쁩니다. 이는 AI 에이전트를 간편하고 안정적이며 프로덕션 환경에 바로 적용할 수 있도록 구축하기 위한 저희의 여정에 있어 중요한 이정표가 될 것입니다. Strands Agents는 모델 기반 접근 방식을 채택하여 단 몇 줄의 코드만으로 AI 에이전트를 구축하고 실행할 수 있는 오픈소스 SDK입니다. Strands는 간단한 에이전트 사용 사례부터 복잡한 에이전트 사용 사례까지, 그리고 로컬 개발부터 프로덕션 환경 배포까지 확장 가능합니다.

2025년 5월 프리뷰 버전으로 출시된 이후, GitHub에서 2,000개 이상의 별점과 PyPI에서 15만 건 이상의 다운로드를 기록했습니다. Strands 1.0은 Strands가 단일 에이전트에 제공했던 것과 동일한 수준의 간편함을 다중 에이전트 애플리케이션에도 제공하며, 4개의 새로운 기본 요소와 Agent to Agent(A2A) 프로토콜 지원을 추가합니다. 다중 에이전트 아키텍처를 프로덕션 환경에 적용하기 위해 1.0에는 원격 데이터 저장소에서 에이전트 상태를 검색하는 새로운 세션 관리자와 SDK 전반의 향상된 비동기 지원 기능이 포함되어 있습니다. 어떤 모델로든 에이전트를 구축할 수 있는 유연성을 위해 Anthropic, Meta, OpenAI, Cohere, Mistral, Stability, Writer, Baseten 등의 파트너들이 다섯 가지 추가 모델 제공자 API를 지원했습니다(풀 리퀘스트 참조). 이러한 업데이트에 대해 자세히 살펴보겠습니다. 전체 코드 샘플은 strandsagents.com에서 확인할 수 있습니다.

다중 에이전트 패턴 간소화

다중 에이전트 패턴을 사용하면 특화된 AI 에이전트들이 함께 작업하여, 작업 위임, 지식 공유, 작업 조정 등 단일 에이전트로는 처리할 수 없는 복잡한 문제를 해결할 수 있습니다. Strands 1.0은 단일 에이전트를 생성하는 데 사용하는 모델/도구/프롬프트 조합을 확장하여 여러 에이전트를 조율할 수 있도록 하는 네 가지 직관적인 기본 요소를 소개합니다.

1. 도구로서의 에이전트(Agents-as-Tools): 간소화된 계층적 위임

도구로서의 에이전트 패턴은 특화된 에이전트를 다른 에이전트가 호출할 수 있는 지능형 도구로 변환하여, 오케스트레이터 역할을 하는 에이전트가 요청 제어권을 포기하지 않고도 도메인 전문 에이전트와 동적으로 협의하는 계층적 위임을 가능하게 합니다. 이는 인간 팀의 업무 방식과 유사합니다. 프로젝트 관리자는 모든 것을 알 필요가 없으며, 각 작업에 대해 어떤 전문가와 협의해야 하는지만 알면 됩니다.

from strands import Agent, tool 
from strands_tools import calculator, file_write, python_repl, journal 

@tool 

def web_search(query: str) -> str: 
    return "Dummy web search results here!" 

# 특화된 에이전트 생성 

research_analyst_agent = Agent( 
    system_prompt="You are a research specialist who gathers and analyzes information about local startup markets", 
    tools=[web_search, calculator, file_write, python_repl] 
) 

travel_advisor_agent = Agent( 
    system_prompt="You are a travel expert who helps with trip planning and destination advice", 
    tools=[web_search, journal] 
) 

# 에이전트를 도구로 변환 

@tool 

def research_analyst(query: str) -> str: 
    response = research_analyst_agent(query) 
    return str(response) 

@tool 

def travel_advisor(query: str) -> str: 
    response = travel_advisor_agent(query) 
    return str(response) 

# 오케스트레이터는 자연스럽게 전문가에게 위임

executive_assistant = Agent(  
    tools=[research_analyst, travel_advisor]  
) 

result = executive_assistant("I have a business meeting in Portland next week. Suggest a nice place to stay near the local startup scene, and suggest a few startups to visit") 

이 간략한 예시에서는 여행 및 연구 에이전트를 정의하고, 개별 에이전트는 전문 분야에 초점을 맞춘 특화된 프롬프트와 도구를 가지고 있습니다. 이것들은 운영 보조 에이전트가 사용자 요청에 대한 입력을 위해 호출할 수 있습니다. 운영 보조 에이전트는 다른 에이전트의 입력을 종합하여 사용자에게 응답을 제공합니다. 도구로서의 에이전트(Agents-as-Tools)에 대해 자세한 내용은 Strands 문서를 참조하세요.

2. 핸드오프(Handoffs): 명시적 제어 이전

핸드오프를 통해 에이전트는 자신의 전문 분야를 벗어난 작업에 직면했을 때 인간에게 명확하게 책임을 이양할 수 있으며, 이양 과정에서 전체 대화의 컨텍스트는 그대로 유지할 수 있습니다. Strands는 에이전트가 대화 기록과 컨텍스트를 유지하면서 원활하게 제어권을 이양할 수 있도록 내장된 handoff_to_user 도구를 제공합니다. 이것은 예를 들면, 고객 서비스 담당자가 고객에게 사례에 대한 추가 정보를 요청하는 것과 같은 기능입니다.

from strands import Agent
from strands_tools import handoff_to_user

SYSTEM_PROMPT="""
Answer the user's support query. Ask them questions with the handoff_to_user tool when you need more information
"""

# 에이전트의 도구 목록에 handoff_to_user 도구 포함
agent = Agent(
    system_prompt=SYSTEM_PROMPT,
    tools=[handoff_to_user]
)

# 에이전트는 고객을 위한 질문이 포함된 handoff_to_user 도구를 호출
agent("I have a question about my order.")

에이전트는 가능하도록 프롬프트를 주었을 때, 인간에게 직접 질문할 수도 있습니다.

from strands import Agent

SYSTEM_PROMPT="""
Answer the user's support query. Ask them questions when you need more information
"""

agent = Agent(
    system_prompt=SYSTEM_PROMPT,
)

# 에이전트는 텍스트로 스트리밍하여 질문
agent("I have a question about my order.")

3. Swarms: 자체 조직화 협업 팀

Swarm은 공유 메모리를 통해 동적으로 조정되는 자율적인 에이전트 팀을 생성하여 여러 특화된 에이전트가 복잡한 작업에 대해 협업할 수 있도록 합니다. 이것은 전문가들이 서로의 아이디어를 발전시키고, 팀이 스스로 조직하여 최상의 공동 결과를 도출하는 브레인스토밍 세션과 같다고 생각할 수 있습니다.

import logging  
from strands import Agent 
from strands.multiagent import Swarm 
from strands_tools import memory, calculator, file_write 

# Strands 디버그 로그 수준을 활성화하고 stderr에 출력 

logging.getLogger("strands.multiagent").setLevel(logging.DEBUG) 
logging.basicConfig( 
    format="%(levelname)s | %(name)s | %(message)s", 
    handlers=[logging.StreamHandler()] 
) 

researcher = Agent( 
    name="researcher", 
    system_prompt="You research topics thoroughly using your memory and built-in knowledge", 
    tools=[memory] 
) 

analyst = Agent( 
    name="analyst", 
    system_prompt="You analyze data and create insights", 
    tools=[calculator, memory] 
) 

writer = Agent( 
    name="writer", 
    system_prompt="You write comprehensive reports based on research and analysis", 
    tools=[file_write, memory] 
) 

# Swarm은 자동으로 에이전트를 조율 

market_research_team = Swarm([researcher, analyst, writer]) 
result = market_research_team( 
    "What is the history of AI since 1950? Create a comprehensive report" 
) 

Swarms에 대해 자세히 알아보려면 Strands 문서를 참조하세요.

4. Graphs: 결정론적 워크플로우 제어

Graphs를 사용하면 조건부 라우팅 및 의사 결정 지점이 포함된 명확한 에이전트 워크플로를 정의할 수 있으며, 이는 특정 단계, 승인 또는 품질 게이트가 필요한 프로세스에 유용합니다. 잘 설계된 조립 라인이나 승인 체인처럼 graphs는 에이전트가 미리 정의된 비즈니스 규칙을 항상 올바른 순서대로 처리할 수 있도록 보장합니다.

from strands import Agent  
from strands.multiagent import GraphBuilder  

analyzer_agent = Agent(  
    name="analyzer",  
    system_prompt="Analyze customer requests and categorize them",  
    tools=[text_classifier, sentiment_analyzer]  
) 

normal_processor = Agent(  
    name="normal_processor",  
    system_prompt="Handle routine requests automatically",  
    tools=[knowledge_base, auto_responder]  
)  

 critical_processor = Agent(  
    name="critical_processor",  
    system_prompt="Handle critical requests quickly",  
    tools=[knowledge_base, escalate_to_support_agent]  
)  

# 결정론적 워크플로우 구축 

builder = GraphBuilder()  
builder.add_node(analyzer_agent, "analyze")  
builder.add_node(normal_processor, "normal_processor")  
builder.add_node(critical_processor, "critical_processor") 

# 조건부 라우팅 정의

def is_approved(state): 
    return True 
def is_critical(state): 
    return False 

builder.add_edge("analyze", "normal_processor", condition=is_approved)  
builder.add_edge("analyze", "critical_processor", condition=is_critical)  
builder.set_entry_point("analyze")  
customer_support_graph = builder.build() 

# 사용자 입력으로 그래프 실행 

results = customer_support_graph("I need help with my order!") 

Graphs에 대해 자세히 알아보려면 Strands 문서를 참조하세요.

이러한 다중 에이전트 패턴은 점진적으로 도입하고 자유롭게 결합할 수 있도록 설계되었습니다. 단일 에이전트로 시작하여 전문 에이전트를 도구로 추가하고, Swarm으로 발전시켜며, 필요에 따라 graphs를 사용하여 조율할 수 있습니다. 패턴을 조합하고 일치시켜 정교한 시스템을 만들 수 있습니다. Swarm은 graphs를 포함할 수 있고, graphs는 Swarm을 조율할 수 있으며, 어떤 패턴이든 다른 에이전트를 도구로 사용하는 에이전트를 사용할 수 있습니다.

from strands import Agent, tool 
from strands.multiagent import GraphBuilder, Swarm 
from strands_tools import memory, calculator, python_repl, file_write  

# 단일 에이전트로 시작

agent = Agent(tools=[memory]) 

# 리드 오케스트레이터 에이전트가 상담할 수 있는 전문 에이전트 생성
data_analyst = Agent(name="analyst", tools=[calculator, python_repl]) 

@tool 

def data_analyst_tool(query: str) -> str: 
    return str(data_analyst(query)) 

analyst_orchestrator = Agent(tools=[memory, data_analyst_tool]) # 도구로서의 에이전트(Agents-as-tools) 

# 패턴을 함께 구성 - Swarm을 사용하는 그래프

researcher = Agent(name="researcher", tools=[memory]) 
writer = Agent(name="writer", tools=[file_write]) 

research_swarm = Swarm([researcher, analyst_orchestrator, writer]) 

review_agent = Agent(system_prompt="Review the research quality and suggest improvements") 

builder = GraphBuilder() 

builder.add_node(research_swarm, "research") # 그래프 노드로서의 Swarm(Swarm as graph node) 

builder.add_node(review_agent, "review") 

builder.add_edge("research", "review") 

graph = builder.build() 

# 패턴은 자연스럽게 중첩됨 - 그래프 내 스웜, 도구로서의 에이전트 등  

result = graph("How has green energy evolved over the last few years?") 

A2A를 통한 다중 에이전트 시스템

Strands 1.0은 서로 다른 플랫폼의 에이전트 간 원활한 통신을 지원하는 개방형 표준인 Agent-to-Agent(A2A) 프로토콜을 지원합니다. 모든 Strands 에이전트는 A2A 기능을 사용하여 네트워크 접근을 가능하게 하고 A2A 프로토콜을 준수할 수 있습니다. 외부 조직의 A2A 에이전트도 모든 Strands 다중 에이전트 패턴 내에서 직접 사용할 수 있습니다.

from strands import Agent 
from strands.multiagent.a2a import A2AServer 
from strands_tools.a2a_client import A2AClientToolProvider 

# A2A 프로토콜을 통해 에이전트 제공 

local_agent = Agent(name="analyzer", tools=[web_search, data_analysis]) 

a2a_agent = A2AServer(agent=local_agent, port=9000) 

a2a_agent.serve() # AgentCard는 http://localhost:9000/.well-known/agent.json에서 사용 가능

# 원격 A2A 에이전트 사용

partner_agent_url = "https://partner.com" 

cloud_agent_url = "https://cloud.ai" 

# 원격 A2A 활성화 에이전트에 연결

a2a_tool_provider = A2AClientToolProvider(known_agent_urls=[partner_agent_url, cloud_agent_url]) 

# 원격 에이전트 오케스트레이션

orchestrator = Agent(tools=[a2a_tool_provider.tools]) 

A2A는 에이전트 기능에 대한 표준화된 설명인 에이전트 카드와 같은 기능을 제공하므로, A2A 지원 다중 에이전트 시스템은 다른 팀이나 다른 조직에서 생성한 에이전트를 쉽게 검색하고 연결할 수 있습니다. Strands는 에이전트에게 제공한 도구를 기반으로 에이전트 카드를 자동 생성합니다. 완전한 작동 예제를 보고 A2A 통합을 시작하려면 샘플 저장소Strands A2A 문서를 참조하세요.

프로덕션 준비 완료

Strands는 공식 출시 훨씬 전부터 Amazon Q Developer 및 AWS Glue와 같이 Amazon 팀에서 프로덕션 환경에서 사용되어 왔지만, 전 세계 수백 명의 고객과 협력하여 프로덕션 요구 사항을 충족하도록 Strands를 확장해 왔습니다. 이러한 업데이트에는 외부 데이터 저장소에 데이터를 저장하고 복구하는 기능을 지원하는 세션 관리 추상화, 구조화된 출력, 향상된 비동기 지원 등이 포함됩니다(릴리스 변경 로그).

내구성 있는 세션 관리

에이전트 대화 및 상태의 자동 지속성 및 복원을 지원하는 세션 관리 추상화인 SessionManager를 추가했습니다. 이를 통해 에이전트는 Amazon Simple Storage Service(Amazon S3)와 같은 스토리지 백엔드에 전체 기록을 저장하고 컴퓨팅이 재시작된 후에도 대화를 원활하게 재개할 수 있습니다. 다음은 기본적인 파일 기반 지속성을 사용하는 예입니다.

from strands import Agent 
from strands.session.file_session_manager import FileSessionManager 

# 파일 기반 스토리지로 세션 관리자 생성 

Session_manager = FileSessionManager(session_id=”customer_support”, base_dir="./agent_sessions") 

# 에이전트는 모든 대화를 자동으로 유지 

agent = Agent( 
    id="support_bot_1", 
    session_manager=session_manager, 
    tools=[knowledge_base, ticket_system] 
) 

# 대화가 진행됨에 따라 메시지가 자동으로 저장됨

agent("Help me reset my password") 

agent("I can't access my email") 

# 나중에, 재시작 후에도 전체 대화 복원

restored_session_manager = FileSessionManager(session_id=”customer_support”, base_dir="./agent_sessions") 

restored_agent = Agent( 
    id="support_bot_1",  
    session_manager=restored_session_manager, 
    tools=[knowledge_base, ticket_system] 
) 

# 에이전트는 전체 대화 기록을 기억하고 원활하게 계속할 수 있음

데이터 액세스 객체(DAO) 패턴을 통해 자체 스토리지 백엔드 구현으로 이 추상화를 확장할 수 있으며, Strands에는 기본적으로 로컬 파일 시스템과 Amazon S3 백엔드가 포함되어 있습니다. 각 에이전트는 추적을 위해 고유 ID를 받으며, 시스템은 다중 에이전트 시나리오에서 동일 세션 내의 동시 실행 에이전트를 처리하여 배포, 확장 이벤트 및 시스템 재시작 전반에 걸쳐 에이전트가 컨텍스트를 유지하도록 보장합니다. Strands 문서에서 세션 관리에 대해 자세히 알아보세요.

네이티브 비동기 지원 및 성능 향상

프로덕션 워크로드는 안정성과 응답 성능을 요구합니다. 1.0 버전에서는 전체 스택에서 비동기 작업을 지원하도록 Strands 이벤트 루프 아키텍처를 개선했습니다. 이제 도구 및 모델 제공자는 차단 없이 비동기 방식으로 실행되어 진정한 동시 실행을 구현할 수 있습니다. 새로운 stream_async 메서드는 텍스트, 도구 사용, 추론 단계 등 모든 에이전트 이벤트를 실시간으로 스트리밍하며, 사용자가 이탈할 때를 위한 내장 취소 지원을 제공합니다.

import asyncio 
from fastapi import FastAPI 
from fastapi.responses import StreamingResponse 
from strands import Agent 
from strands_tools import calculator 

app = FastAPI() 

@app.post("/chat") 

async def chat_endpoint(message: str): 
    async def stream_response(): 
        agent = Agent(tools=[web_search, calculator]) 
        # 실시간으로 에이전트 응답 스트리밍 
        async for event in agent.stream_async(message): 
            if "data" in event: 
                yield f"data: {event['data']}\n\n" 
            elif "current_tool_use" in event: 
                yield f"event: tool\ndata: Using {event['current_tool_use']['name']}\n\n" 
    return StreamingResponse(stream_response(), media_type="text/event-stream") 

# 동시 실행 에이전트 평가 

async def evaluate_models_concurrently(prompt: str): 
    async def stream(agent: Agent): 
        print(f"STARTING: {agent.name}") 
        async for event in agent.stream_async(prompt): 
            # 이벤트 처리 
        print(f"ENDING: {agent.name}") 
        return event[“result”]  # 마지막 이벤트는 에이전트 결과 
    agents = [ 
        Agent(name="claude", model="us.anthropic.claude-3-7-sonnet-20250219-v1:0”), 
        Agent(name="deepseek”, model="us.deepseek.r1-v1:0”), 
        Agent(name="nova", model="us.amazon.nova-pro-v1:0") 
    ] 

    # 모든 에이전트 동시에 실행
    responses = await asyncio.gather(*[stream(agent) for agent in agents]) 

    return responses 

네이티브 비동기 지원에 대해 자세히 알아보려면 Strands 문서를 참조하세요.

확장된 모델 제공자 지원

고객들은 다양한 작업에 다양한 모델을 사용할 수 있는 유연성이 필요하다고 이야기했습니다. 이를 위해 Strands Agents는 모델 제공업체 커뮤니티의 강력한 지원을 받았습니다. Anthropic, Meta, OpenAI, Cohere, Mistral, Stability, Writer와 같은 모델 제공업체들은 Strands Agent에서 자체 모델 API를 코드와 함께 사용할 수 있도록 기여해 왔습니다. 제공업체의 API 인프라를 통해 Strands Agents에 액세스하면 개발자는 인프라 관리 없이 AI 기반 솔루션 구축에 집중할 수 있습니다. 이러한 추가 기능은 LiteLLM을 통해 Amazon Bedrock, OpenAI 및 모든 OpenAI 호환 엔드포인트의 모든 모델에 대한 미리보기 출시 지원을 보완합니다. Strands Agents를 사용하면 도구나 로직을 수정하지 않고도 각각의 에이전트에 대해 서로 다른 모델을 사용하거나 모델과 모델 제공업체를 전환할 수 있습니다.

from strands import Agent
from strands.models import BedrockModel
from strands.models.openai import OpenAIModel
from strands.models.anthropic import AnthropicModel

# 다양한 모델 제공자 구성
bedrock_model = BedrockModel(
    model_id="us.amazon.nova-pro-v1:0",
    temperature=0.3,
    top_p=0.8,
    region_name="us-west-2"
)

openai_model = OpenAIModel(
    client_args={
        "api_key": "your-api-key",
    },
    model_id="gpt-4o",
    params={
        "max_tokens": 1000,
        "temperature": 0.7,
    }
)

anthropic_model = AnthropicModel(
    client_args={
        "api_key": "your-api-key",
    },
    max_tokens=1028,
    model_id="claude-3-7-sonnet-20250219",
    params={
        "temperature": 0.5,
    }
)

# 모델 교체 또는 동일한 시스템에서 다른 에이전트에 대해 다른 모델 사용
researcher = Agent(
    name="researcher",
    model=anthropic_model,
    tools=[web_search]
)

writer = Agent(
    name="writer", 
    model=openai_model,
    tools=[document_formatter]
)

analyzer = Agent(
    name="analyzer",
    model=bedrock_model,
    tools=[data_processor]
)

Strands 커뮤니티는 사용, 피드백, 그리고 직접적인 코드 기여를 통해 이러한 모든 업데이트를 형성하는 데 중요한 역할을 해왔습니다. 0.1.0 버전과 1.0 버전 사이에 Strands에 병합된 150개 이상의 풀 리퀘스트 중 22%는 버그 수정, 모델 제공자 추가, 문서 작성, 기능 추가, 그리고 성능 향상을 위한 클래스 리팩토링 등을 담당한 커뮤니티 구성원들의 기여로 이루어졌습니다. Strands를 프로토타입 단계에서 프로덕션 단계로 전환하는 가장 간편한 방법으로 만들어 주신 모든 분들께 진심으로 감사드립니다.

AI의 미래는 멀티 에이전트이며, Strands 1.0을 통해 그 미래가 프로덕션 단계에 준비되었습니다. 지금 바로 strandsagents.com에서 빌드를 시작하세요.

Yangsoo Kim

Yangsoo Kim

김양수 솔루션즈 아키텍트는 엔터프라이즈 기업 고객들을 대상으로 AWS의 다양한 솔루션들에 대한 기술 지원을 했던 경험을 바탕으로, 리테일 고객들이 최적의 아키텍처를 통해 AWS의 솔루션을 보다 잘 활용할 수 있도록 지원하고 있습니다.