์ฌ๊ธฐ์์๋ Strands agent๋ฅผ ์ด์ฉํด Agentic AI๋ฅผ ๊ตฌํํ๋๊ฒ์ ์ค๋ช ํฉ๋๋ค. Strands Agent๋ AI agent ๊ตฌ์ถ ๋ฐ ์คํ์ ์ํด ์ค๊ณ๋ ์คํ์์ค SDK์ ๋๋ค. ๊ณํ(planning), ์ฌ๊ณ ์ฐ๊ฒฐ(chaining thoughts), ๋๊ตฌ ํธ์ถ, Reflection๊ณผ ๊ฐ์ agent ๊ธฐ๋ฅ์ ์ฝ๊ฒ ํ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด LLM model๊ณผ tool์ ์ฐ๊ฒฐํ๋ฉฐ, ๋ชจ๋ธ์ ์ถ๋ก ๋ฅ๋ ฅ์ ์ด์ฉํ์ฌ ๋๊ตฌ๋ฅผ ๊ณํํ๊ณ ์คํํฉ๋๋ค. ํ์ฌ Amazon Bedrock, Anthropic, Meta์ ๋ชจ๋ธ์ ์ง์ํ๋ฉฐ, Accenture, Anthropic, Meta์ ๊ฐ์ ๊ธฐ์ ๋ค์ด ์ฐธ์ฌํ๊ณ ์์ต๋๋ค.
์ฌ๊ธฐ์์ ์ฌ์ฉํ๋ architecture๋ ์๋์ ๊ฐ์ต๋๋ค. Agent์ ๊ธฐ๋ณธ๋์ ํ์ธ ๋ฐ ๊ตฌํ์ ์ํด EC2์ docker ํํ๋ก ํ์ฌ๋์ด ALB์ CloudFront๋ฅผ ์ด์ฉํด ์ฌ์ฉ์๊ฐ streamlit์ผ๋ก ๋์์ ํ ์คํธ ํ ์ ์์ต๋๋ค. Agent๊ฐ ์์ฑํ๋ ๊ทธ๋ฆผ์ด๋ ๋ฌธ์๋ S3๋ฅผ ์ด์ฉํด ๊ณต์ ๋ ์ ์์ผ๋ฉฐ, EC2์ ๋ด์ฅ๋ MCP server/client๋ฅผ ์ด์ฉํด ์ธํฐ๋ท๊ฒ์(Tavily), RAG(knowledge base) AWS tools(use-aws), AWS Document๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
Strands agent๋ ์๋์ ๊ฐ์ Agent Loop์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก, ์ ์ ํ tool์ ์ ํํ์ฌ ์คํํ๊ณ , reasoning์ ํตํด ๋ฐ๋ณต์ ์ผ๋ก ํ์ํ ๋์์ ์ํํฉ๋๋ค.
Tool๋ค์ ์๋์ ๊ฐ์ด ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
agent = Agent(
max_parallel_tools=4
)app.py์ ๊ฐ์ด ์ฌ์ฉ์๊ฐ "RAG", "Agent"์ ์ ํํ ์ ์์ต๋๋ค. "Agent"์ Strands agent๋ฅผ ์ด์ฉํ์ฌ MCP๋ก ํ์์ tool๋ค์ ์ด์ฉํ์ฌ RAG๋ฑ์ ํ์ฉํ ์ ์์ต๋๋ค. Streamlit์ UI๋ฅผ ์ํ์ฌ user์ ์ ๋ ฅ๊ณผ ๊ฒฐ๊ณผ์ธ response์ Session State๋ก ๊ด๋ฆฌํฉ๋๋ค.
if prompt := st.chat_input("๋ฉ์์ง๋ฅผ ์
๋ ฅํ์ธ์."):
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("assistant"):
containers = {
"tools": st.empty(),
"status": st.empty(),
"notification": [st.empty() for _ in range(1000)],
"key": st.empty()
}
if mode == 'Agent':
response, image_urls = asyncio.run(chat.run_strands_agent(
query=prompt,
strands_tools=selected_strands_tools,
mcp_servers=selected_mcp_servers,
containers=containers))
st.session_state.messages.append({
"role": "assistant",
"content": response,
"images": image_urls if image_urls else []
})์๋์ ๊ฐ์ด system prompt, model, tool ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ agent๋ฅผ ์์ฑํฉ๋๋ค.
def create_agent(system_prompt, tools):
if system_prompt==None:
system_prompt = (
"๋น์ ์ ์ด๋ฆ์ ์์ฐ์ด๊ณ , ์ง๋ฌธ์ ๋ํด ์น์ ํ๊ฒ ๋ต๋ณํ๋ ์ฌ๋ ค๊น์ ์ธ๊ณต์ง๋ฅ ๋์ฐ๋ฏธ์
๋๋ค."
"์ํฉ์ ๋ง๋ ๊ตฌ์ฒด์ ์ธ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถฉ๋ถํ ์ ๊ณตํฉ๋๋ค."
"๋ชจ๋ฅด๋ ์ง๋ฌธ์ ๋ฐ์ผ๋ฉด ์์งํ ๋ชจ๋ฅธ๋ค๊ณ ๋งํฉ๋๋ค."
)
model = get_model()
agent = Agent(
model=model,
system_prompt=system_prompt,
tools=tools,
conversation_manager=conversation_manager
)
return agentchat.py์ ๊ฐ์ด Agent๋ฅผ ์คํํ๊ณ stream์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ๋ณด์ฌ์ค๋๋ค. ์ด๋, ์๋์ ๊ฐ์ด event์์ "data"๋ง์ ์ถ์ถํ ํ์ full_response๋ก ์ ์ฅํ ํ์ markdown์ผ๋ก ํ์ํฉ๋๋ค.
async def run_strands_agent(query, strands_tools, mcp_servers, containers):
await strands_agent.initiate_agent(
system_prompt=None,
strands_tools=strands_tools,
mcp_servers=mcp_servers
)
final_result = current = ""
with strands_agent.mcp_manager.get_active_clients(mcp_servers) as _:
agent_stream = strands_agent.agent.stream_async(query)
async for event in agent_stream:
text = ""
if "data" in event:
text = event["data"]
logger.info(f"[data] {text}")
current += text
elif "result" in event:
final = event["result"]
message = final.message
if message:
content = message.get("content", [])
result = content[0].get("text", "")
final_result = result
return final_result๋ํ ๋ด์ฉ์ ์ด์ฉํด ๋ํ๋ฅผ ์ด์ด๋๊ฐ๊ณ ์ ํ ๊ฒฝ์ฐ์ ์๋์ ๊ฐ์ด SlidingWindowConversationManager์ ์ด์ฉํด์ window_size๋งํผ ์ด์ ๋ํ๋ฅผ ๊ฐ์ ธ์ ํ์ฉํ ์ ์์ต๋๋ค. ์์ธํ ์ฝ๋๋ chat.py์ ์ฐธ์กฐํฉ๋๋ค.
from strands.agent.conversation_manager import SlidingWindowConversationManager
conversation_manager = SlidingWindowConversationManager(
window_size=10,
)
agent = Agent(
model=model,
system_prompt=system,
tools=[
calculator,
current_time,
use_aws
],
conversation_manager=conversation_manager
)์๋์ ๊ฐ์ด MCPClient๋ก stdio_mcp_client์ ์ง์ ํ ํ์ list_tools_sync์ ์ด์ฉํด tool ์ ๋ณด๋ฅผ ์ถ์ถํฉ๋๋ค. MCP tool์ strands tool๊ณผ ํจ๊ป ์๋์ฒ๋ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
from strands.tools.mcp import MCPClient
from strands_tools import calculator, current_time, use_aws
stdio_mcp_client = MCPClient(lambda: stdio_client(
StdioServerParameters(command="uvx", args=["awslabs.aws-documentation-mcp-server@latest"])
))
with stdio_mcp_client as client:
aws_documentation_tools = client.list_tools_sync()
logger.info(f"aws_documentation_tools: {aws_documentation_tools}")
tools=[
calculator,
current_time,
use_aws
]
tools.extend(aws_documentation_tools)
agent = Agent(
model=model,
system_prompt=system,
tools=tools,
conversation_manager=conversation_manager
)๋ํ, wikipedia ๊ฒ์์ ์ํ MCP server์ ์๋ ์๋์ ๊ฐ์ต๋๋ค. ์์ธํ ์ฝ๋๋ mcp_server_wikipedia.py์ ์ฐธ์กฐํฉ๋๋ค.
from mcp.server.fastmcp import FastMCP
import wikipedia
import logging
import sys
logging.basicConfig(
level=logging.INFO, # Default to INFO level
format='%(filename)s:%(lineno)d | %(message)s',
handlers=[
logging.StreamHandler(sys.stderr)
]
)
logger = logging.getLogger("rag")
mcp = FastMCP(
"Wikipedia",
dependencies=["wikipedia"],
)
@mcp.tool()
def search(query: str):
logger.info(f"Searching Wikipedia for: {query}")
return wikipedia.search(query)
@mcp.tool()
def summary(query: str):
return wikipedia.summary(query)
@mcp.tool()
def page(query: str):
return wikipedia.page(query)
@mcp.tool()
def random():
return wikipedia.random()
@mcp.tool()
def set_lang(lang: str):
wikipedia.set_lang(lang)
return f"Language set to {lang}"
if __name__ == "__main__":
mcp.run()MCP Server๋ฅผ ๋์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ์ฌ MCPClientManager๋ฅผ ์ ์ํฉ๋๋ค. add_client๋ MCP ์๋ฒ์ name, command, args, env๋ก MCP Client๋ฅผ ์ ์ํฉ๋๋ค.
class MCPClientManager:
def __init__(self):
self.clients: Dict[str, MCPClient] = {}
def add_client(self, name: str, command: str, args: List[str], env: dict[str, str] = {}) -> None:
"""Add a new MCP client"""
self.clients[name] = MCPClient(lambda: stdio_client(
StdioServerParameters(
command=command, args=args, env=env
)
))
def remove_client(self, name: str) -> None:
"""Remove an MCP client"""
if name in self.clients:
del self.clients[name]
@contextmanager
def get_active_clients(self, active_clients: List[str]):
"""Manage active clients context"""
active_contexts = []
for client_name in active_clients:
if client_name in self.clients:
active_contexts.append(self.clients[client_name])
if active_contexts:
with contextlib.ExitStack() as stack:
for client in active_contexts:
stack.enter_context(client)
yield
else:
yield
# Initialize MCP client manager
mcp_manager = MCPClientManager()Streamlit์ผ๋ก ๊ตฌํํ app.py์์ tool๋ค์ ์ ํํ๋ฉด mcp_tools๋ฅผ ์ป์ ์ ์์ต๋๋ค. ์ดํ ์๋์ ๊ฐ์ด agent ์์ฑ์์ active client์ผ๋ก ๋ถํฐ tool list๋ฅผ ๊ฐ์ ธ์์ tools๋ก ํ์ฉํฉ๋๋ค.
tools = []
for mcp_tool in mcp_servers:
with mcp_manager.get_active_clients([mcp_tool]) as _:
client = mcp_manager.get_client(mcp_tool)
mcp_servers_list = client.list_tools_sync()
tools.extend(mcp_servers_list)
agent = create_agent(system_prompt, tools)
tool_list = get_tool_list(tools)์์ฑ๋ agent๋ ์๋์ ๊ฐ์ด mcp_manager๋ฅผ ์ด์ฉํด ์คํํฉ๋๋ค.
with mcp_manager.get_active_clients(mcp_tools) as _:
agent_stream = agent.stream_async(question)
tool_name = ""
async for event in agent_stream:
if "message" in event:
message = event["message"]
for content in message["content"]:
if "text" in content:
final_response = content["text"]Agent๋ฅผ ์๋์ ๊ฐ์ด ์คํํ์ฌ agent_stream์ ์ป์ต๋๋ค.
with mcp_manager.get_active_clients(mcp_servers) as _:
agent_stream = agent.stream_async(question)์ฌ์ฉ์ ๊ฒฝํ์ ์ํด์๋ streamํํ๋ก ์ถ๋ ฅ์ ์ป์ ์ ์์ด์ผ ํฉ๋๋ค. ์ด๋ ์๋์ ๊ฐ์ด agent_stream์์ event๋ฅผ ๊บผ๋ธํ "data"์์ ์ถ์ถํ์ฌ ์๋์ ๊ฐ์ด current_response์ stream ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์์ ๋ณด์ฌ์ค๋๋ค.
async for event in agent_stream:
if "data" in event:
text_data = event["data"]
current_response += text_data
containers["notification"][index].markdown(current_response)Strands agent๋ multi step reasoning์ ํตํด ์ฌ๋ฌ๋ฒ ๊ฒฐ๊ณผ๊ฐ ๋์ต๋๋ค. ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํด ์๋์ ๊ฐ์ด message์ content์์ text๋ฅผ ์ถ์ถํ์ฌ ๋ง์ง๋ง๋ง์ ์ถ์ถํฉ๋๋ค. ๋ํ tool๋ง๋ค reference๊ฐ ๋ค๋ฅด๋ฏ๋ก ์๋์ ๊ฐ์ด tool content์ text์์ reference๋ฅผ ์ถ์ถํฉ๋๋ค.
if "message" in event:
message = event["message"]
for msg_content in message["content"]:
result = msg_content["text"]
current_response = ""
tool_content = msg_content["toolResult"]["content"]
for content in tool_content:
content, urls, refs = get_tool_info(tool_name, content["text"])
if refs:
for r in refs:
references.append(r)generate_image_with_colors๋ผ๋ tool์ ์ต์ข ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ ์๋์ ๊ฐ์ด event_loop_metrics์์ ์ถ์ถํฉํ์ฌ image_urls๋ก ํ์ฉํฉ๋๋ค.
if "event_loop_metrics" in event and \
hasattr(event["event_loop_metrics"], "tool_metrics") and \
"generate_image_with_colors" in event["event_loop_metrics"].tool_metrics:
tool_info = event["event_loop_metrics"].tool_metrics["generate_image_with_colors"].tool
if "input" in tool_info and "filename" in tool_info["input"]:
fname = tool_info["input"]["filename"]
if fname:
url = f"{path}/{s3_image_prefix}/{parse.quote(fname)}.png"
if url not in image_urls:
image_urls.append(url)Agents as Tools์ ๊ฐ์ด orchestrator agent๋ฅผ ์ด์ฉํด research_assistant, product_recommendation_assistant, trip_planning_assistant์ ๊ฐ์ ์ฌ๋ฌ agents๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค. agent-as-tools์ ๊ฐ์ด supervisorํํ์ multi agent์ tool์ ์ํ agent์ ์ด์ฉํด ๊ตฌํํ ์ ์์ต๋๋ค.
strands_supervisor.py์ ๊ฐ์ด supervisor๋ฅผ ์ํ orchestration agent๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ด agent๋ research_assistant, product_recommendation_assistant, trip_planning_assistant์ agent๋ก ๋ง๋ค์ด์ง tool์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
orchestrator = Agent(
model=strands_agent.get_model(),
system_prompt=MAIN_SYSTEM_PROMPT,
tools=[
research_assistant,
product_recommendation_assistant,
trip_planning_assistant,
file_write,
],
)
agent_stream = orchestrator.stream_async(question)
result = await show_streams(agent_stream, containers)์ฌ๊ธฐ์ trip_planning_assistant๋ ์๋์ ๊ฐ์ด travel_agent๋ผ๋ agent๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
@tool
async def trip_planning_assistant(query: str) -> str:
"""
Create travel itineraries and provide travel advice.
Args:
query: A travel planning request with destination and preferences
Returns:
A detailed travel itinerary or travel advice
"""
travel_agent = Agent(
model=strands_agent.get_model(),
system_prompt=TRIP_PLANNING_ASSISTANT_PROMPT,
)
agent_stream = travel_agent.stream_async(query)
result = await show_streams(agent_stream, containers)
return resultSupervisor๋ ์ ๋ฌธ agent์ธ collaborator๋ก hand off๋ฅผ ์ํํจ์ผ๋ก์จ ๋ ํฅ์๋ ๋ต๋ณ์ ์ป์ ์ ์์ต๋๋ค.
Multi-Agent Systems and Swarm Intelligence์ ๊ฐ์ด Agent๋ค์ด ์๋ก ํ์กฐํ๋ฉด์ ๋ณต์กํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์์ต๋๋ค.
Mesh Swarm Architecture์ ๊ฐ์ด ์ฌ๋ฌ agent๋ค๊ฐ์ ํ์ ์ ์ํํ ์ ์์ต๋๋ค. Research agent๋ ๋ ผ๋ฆฌ์ ์ธ ๋ต๋ณ์, creative agent๋ ํฅ๋ฏธ๋ก์ด ๋ต๋ณ์ ์ ๊ณตํฉ๋๋ค. ์ด๋, critical agent๋ก ๋ agent๋ค์ ๊ฐ์ ์ ์ ๋์ถํ ํ์, summarizer agent๋ก ์ต์ ์ ๋ต๋ณ์ ๊ตฌํ ์ ์์ต๋๋ค.
์ด๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ strands_swarm.py์ ์ฐธ์กฐํฉ๋๋ค. ๊ฐ agent์ ํ๋ฅด์๋์ ๋ง๊ฒ MCP tool๊ณผ ํจ๊ป agent๋ฅผ ์ ์ ํฉ๋๋ค.
# Create specialized agents with different expertise
# research agent
system_prompt = (
"๋น์ ์ ์ ๋ณด ์์ง๊ณผ ๋ถ์์ ์ ๋ฌธ์ผ๋ก ํ๋ ์ฐ๊ตฌ์์
๋๋ค. "
"๋น์ ์ ์ญํ ์ ํด๋น ์ฃผ์ ์ ๋ํ ์ฌ์ค์ ์ ๋ณด์ ์ฐ๊ตฌ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค. "
"์ ํํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ณ ๋ฌธ์ ์ ํต์ฌ์ ์ธ ์ธก๋ฉด๋ค์ ํ์
ํ๋ ๋ฐ ์ง์คํด์ผ ํฉ๋๋ค. "
"๋ค๋ฅธ ์์ด์ ํธ๋ก๋ถํฐ ์
๋ ฅ์ ๋ฐ์ ๋, ๊ทธ๋ค์ ์ ๋ณด๊ฐ ๋น์ ์ ์ฐ๊ตฌ์ ์ผ์นํ๋์ง ํ๊ฐํ์ธ์. "
)
model = strands_agent.get_model()
research_agent = Agent(
model=model,
system_prompt=system_prompt,
tools=tools
)
# Creative Agent
system_prompt = (
"๋น์ ์ ํ์ ์ ์ธ ์๋ฃจ์
์์ฑ์ ์ ๋ฌธ์ผ๋ก ํ๋ ์ฐฝ์์ ์์ด์ ํธ์
๋๋ค. "
"๋น์ ์ ์ญํ ์ ํ์ ๋ฐํ ์ฌ๊ณ ์์ ๋ฒ์ด๋ ์ฐฝ์์ ์ธ ์ ๊ทผ๋ฒ์ ์ ์ํ๋ ๊ฒ์
๋๋ค. "
"๋ค๋ฅธ ์์ด์ ํธ๋ค๋ก๋ถํฐ ์ป์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ํ๋, ๋น์ ๋ง์ ๋
์ฐฝ์ ์ธ ์ฐฝ์์ ๊ด์ ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค. "
"๋ค๋ฅธ ์ฌ๋๋ค์ด ๊ณ ๋ คํ์ง ์์์ ์๋ ์๋ ์ฐธ์ ํ ์ ๊ทผ๋ฒ์ ์ง์คํ์ธ์. "
)
creative_agent = Agent(
model=model,
system_prompt=system_prompt,
tools=tools
)
# Critical Agent
system_prompt = (
"๋น์ ์ ์ ์์๋ฅผ ๋ถ์ํ๊ณ ๊ฒฐํจ์ ์ฐพ๋ ๊ฒ์ ์ ๋ฌธ์ผ๋ก ํ๋ ๋นํ์ ์์ด์ ํธ์
๋๋ค. "
"๋น์ ์ ์ญํ ์ ๋ค๋ฅธ ์์ด์ ํธ๋ค์ด ์ ์ํ ํด๊ฒฐ์ฑ
์ ํ๊ฐํ๊ณ ์ ์ฌ์ ์ธ ๋ฌธ์ ์ ๋ค์ ์๋ณํ๋ ๊ฒ์
๋๋ค. "
"์ ์๋ ํด๊ฒฐ์ฑ
์ ์ ์คํ ๊ฒํ ํ๊ณ , ์ฝ์ ์ด๋ ๊ฐ๊ณผ๋ ๋ถ๋ถ์ ์ฐพ์๋ด๋ฉฐ, ๊ฐ์ ๋ฐฉ์์ ์ ์ํด์ผ ํฉ๋๋ค. "
"๋นํํ ๋๋ ๊ฑด์ค์ ์ผ๋ก ํ๋, ์ต์ข
ํด๊ฒฐ์ฑ
์ด ๊ฒฌ๊ณ ํ๋๋ก ๋ณด์ฅํ์ธ์. "
)
critical_agent = Agent(
model=model,
system_prompt=system_prompt,
tools=tools
)
# summarizer agent
system_prompt = (
"๋น์ ์ ์ ๋ณด ์ข
ํฉ์ ์ ๋ฌธ์ผ๋ก ํ๋ ์์ฝ ์์ด์ ํธ์
๋๋ค. "
"๋น์ ์ ์ญํ ์ ๋ชจ๋ ์์ด์ ํธ๋ก๋ถํฐ ํต์ฐฐ๋ ฅ์ ์์งํ๊ณ ์์ง๋ ฅ ์๋ ์ต์ข
ํด๊ฒฐ์ฑ
์ ๋ง๋๋ ๊ฒ์
๋๋ค."
"์ต๊ณ ์ ์์ด๋์ด๋ค์ ๊ฒฐํฉํ๊ณ ๋นํ์ ๋ค์ ๋ค๋ฃจ์ด ํฌ๊ด์ ์ธ ๋ต๋ณ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. "
"์๋ ์ง๋ฌธ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃจ๋ ๋ช
ํํ๊ณ ์คํ ๊ฐ๋ฅํ ์์ฝ์ ์์ฑํ๋ ๋ฐ ์ง์คํ์ธ์. "
)
summarizer_agent = Agent(
model=model,
system_prompt=system_prompt,
callback_handler=None)์ฃผ์ด์ง ์ง๋ฌธ์ ๋ํด research, creative, critical agent์ ์๋ต์ ๊ตฌํ๊ณ , ์์ ์ ๊ฒฐ๊ณผ์ ํจ๊ฒ ๋ค๋ฅธ agent๋ค์ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌํฉ๋๋ค.
result = research_agent.stream_async(question)
research_result = await show_streams(result, containers)
result = creative_agent.stream_async(question)
creative_result = await show_streams(result, containers)
result = critical_agent.stream_async(question)
critical_result = await show_streams(result, containers)
research_messages = []
creative_messages = []
critical_messages = []
creative_messages.append(f"From Research Agent: {research_result}")
critical_messages.append(f"From Research Agent: {research_result}")
summarizer_messages.append(f"From Research Agent: {research_result}")
research_messages.append(f"From Creative Agent: {creative_result}")
critical_messages.append(f"From Creative Agent: {creative_result}")
summarizer_messages.append(f"From Creative Agent: {creative_result}")
research_messages.append(f"From Critical Agent: {critical_result}")
creative_messages.append(f"From Critical Agent: {critical_result}")
summarizer_messages.append(f"From Critical Agent: {critical_result}")๊ฒฐ๊ณผ๋ฅผ refineํ๊ณ ์ป์ด์ง ๊ฒฐ๊ณผ๋ฅผ summarizer agent์ ์ ๋ฌํฉ๋๋ค.
result = research_agent.stream_async(research_prompt)
refined_research = await show_streams(result, containers)
result = creative_agent.stream_async(creative_prompt)
refined_creative = await show_streams(result, containers)
result = critical_agent.stream_async(critical_prompt)
refined_critical = await show_streams(result, containers)
summarizer_messages.append(f"From Research Agent (Phase 2): {refined_research}")
summarizer_messages.append(f"From Creative Agent (Phase 2): {refined_creative}")
summarizer_messages.append(f"From Critical Agent (Phase 2): {refined_critical}")์ดํ ์๋์ ๊ฐ์ด ์์ฝํฉ๋๋ค.
summarizer_prompt = f"""
Original query: {question}
Please synthesize the following inputs from all agents into a comprehensive final solution:
{"\n\n".join(summarizer_messages)}
Create a well-structured final answer that incorporates the research findings,
creative ideas, and addresses the critical feedback.
"""
result = summarizer_agent.stream_async(summarizer_prompt)
final_solution = await show_streams(result, containers)research, creative, critical agent๋ค์ ๋ณ๋ ฌ๋ก ์คํ์ด ๊ฐ๋ฅํฉ๋๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ ํํ๋ก๋ ๊ตฌํํ ์ ์์ต๋๋ค.
tasks = [
_research_agent_worker(research_agent, question, request_id),
_creative_agent_worker(creative_agent, question, request_id),
_critical_agent_worker(critical_agent, question, request_id)
]
results = await asyncio.gather(*tasks)
research_result, creative_result, critical_result = results
summarizer_agent = create_summarizer_agent(question, tools)
summarizer_messages = []
creative_messages.append(f"From Research Agent: {research_result}")
critical_messages.append(f"From Research Agent: {research_result}")
summarizer_messages.append(f"From Research Agent: {research_result}")
research_messages.append(f"From Creative Agent: {creative_result}")
critical_messages.append(f"From Creative Agent: {creative_result}")
summarizer_messages.append(f"From Creative Agent: {creative_result}")
research_messages.append(f"From Critical Agent: {critical_result}")
creative_messages.append(f"From Critical Agent: {critical_result}")
summarizer_messages.append(f"From Critical Agent: {critical_result}")Creating Swarm of agents using Strands Agents์์ strands agent์์ swarm์ ์ฌ์ฉํ ์ ์๋๋ก tool์ ์ ๊ณตํ๊ณ ์์ต๋๋ค. ์ด๋ agent์์ ์ค์ ํ ์ ์๋ ํ์ ์ต์ ์ ์๋์ ๊ฐ์ต๋๋ค.
- Collaborative: Agents build upon others' insights and seek consensus
- Competitive: Agents develop independent solutions and unique perspectives
- Hybrid: Balances cooperation with independent exploration
ํ์ ํ๋ swarm agent๋ค๋ก๋ถํฐ ์ป์ด์ง ๊ฒฐ๊ณผ๋ฅผ summarized agent๋ก ์ ๋ฆฌํ์ฌ ๋ต๋ณํฉ๋๋ค. ์๋๋ swarm tool์ ์ฌ์ฉํ ๋์ diagram์ ๋๋ค. ์ฌ๊ธฐ์ swarm agent์ ์ซ์๋ swarm_size๋ก ์กฐ์ ํฉ๋๋ค.
strands_swarm_tool.py์ ๊ฐ์ด strands agent๋ฅผ ์ด์ฉํด swarm ํํ์ multi agent๋ฅผ ๊ตฌํํ๊ณ , ์ด๋ฅผ ํตํด ๋ณต์กํ ๋ฌธ์ ๋ฅผ ํ ์ ์์ต๋๋ค.
from strands_tools import swarm
agent = Agent(
model=strands_agent.get_model(),
system_prompt=system_prompt,
tools=[swarm]
)
result = agent.tool.swarm(
task=question,
swarm_size=3,
coordination_pattern="collaborative"
)
logger.info(f"result of swarm: {result}")์ด๋์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค. ์ ๋ฌธ agent์ ๋ํ role๊ณผ prompt๋ฅผ ์์ฑํ ํ์ ์์ฝ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
Agent Workflows์ ์ด์ฉํ๋ฉด ๊ฐ๋จํ workflow๋ฅผ ์์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
strands_workflow.py์์๋ ์๋์ ๊ฐ์ด researcher, analyst, writer๋ฅผ ํตํด ์ข๋ ์ฌํ๋ ๋ณด๊ณ ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
async def run_workflow(question, containers):
model = strands_agent.get_model()
researcher = Agent(
model=model,
system_prompt="research specialist. Find key information.",
callback_handler=None
)
analyst = Agent(
model=model,
system_prompt="You analyze research data and extract insights. Analyze these research findings.",
callback_handler=None
)
writer = Agent(
model=model,
system_prompt="You create polished reports based on analysis. Create a report based on this analysis.",
callback_handler=None
)
# Step 1: Research
add_notification(containers, f"์ง๋ฌธ: {question}")
query = f"๋ค์์ ์ง๋ฌธ์ ๋ถ์ํ์ธ์. <question>{question}</question>"
research_stream = researcher.stream_async(query)
research_result = await show_streams(research_stream, containers)
# Step 2: Analysis
add_notification(containers, f"๋ถ์: {research_result}")
analysis = f"๋ค์์ ๋ถ์ํด์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๊ณ ์ดํดํ๊ธฐ ์ฝ๊ฒ ๋ถ์ํ์ธ์. <research>{research_result}</research>"
analysis_stream = analyst.stream_async(analysis)
analysis_result = await show_streams(analysis_stream, containers)
# Step 3: Report writing
add_notification(containers, f"๋ณด๊ณ ์: {analysis_result}")
report = f"๋ค์์ ๋ด์ฉ์ ์ฐธ์กฐํ์ฌ ์์ธํ ๋ณด๊ณ ์๋ฅผ ์์ฑํ์ธ์. <subject>{analysis_result}</subject>"
report_stream = writer.stream_async(report)
report_result = await show_streams(report_stream, containers)
return report_resultAgent Graphs์ ๊ฐ์ด ๋ค๋จ๊ณ๋ก ๋ ๋ณต์กํ Graph๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ์ด๋์ agent๋ค์ ๊ตฌ์ฑ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
strands_graph.py์ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ graph์ ์์์ coordinator์ ๋๋ค. ์ด agent๋ economic_department, technical_analysis, social_analysis์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
coordinator = Agent(
system_prompt=COORDINATOR_SYSTEM_PROMPT,
tools=[economic_department, technical_analysis, social_analysis]
)
agent_stream = coordinator.stream_async(f"Provide a comprehensive analysis of: {question}")์ฌ๊ธฐ์ economic_department๋ ์๋์ ๊ฐ์ด tool๋ก ๊ตฌํ๋ฉ๋๋ค. ์ด agent๋ market_research, financial_analysis๋ฅผ tool๋ก ๊ฐ์ง๊ณ ์์ต๋๋ค.
@tool
async def economic_department(query: str) -> str:
"""Coordinate economic analysis across market and financial domains."""
logger.info("๐ Economic Department coordinating analysis...")
if isKorean(query):
system_prompt = (
"๋น์ ์ ๊ฒฝ์ ๋ถ์ ๊ด๋ฆฌ์์
๋๋ค. ๊ฒฝ์ ๋ถ์์ ์กฐ์ ํ๊ณ ํตํฉํฉ๋๋ค."
"์์ฅ ๊ด๋ จ ์ง๋ฌธ์๋ market_research ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ธ์."
"๊ฒฝ์ ์ ์ง๋ฌธ์๋ financial_analysis ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ธ์."
"๊ฒฐ๊ณผ๋ฅผ ํตํฉํ์ฌ ํตํฉ๋ ๊ฒฝ์ ๊ด์ ์ ์ ๊ณตํ์ธ์."
"์ค์: ์ง๋ฌธ์ด ๋ช
ํํ๊ฒ ํ ์์ญ์ ์ง์ค๋์ง ์๋ ํ ๋ ๋๊ตฌ๋ฅผ ๋ชจ๋ ์ฌ์ฉํ์ฌ ์ฒ ์ ํ ๋ถ์์ ์ํํ์ธ์."
)
else:
system_prompt = (
"You are an economic department manager who coordinates specialized economic analyses. "
"For market-related questions, use the market_research tool. "
"For financial questions, use the financial_analysis tool. "
"Synthesize the results into a cohesive economic perspective. "
"Important: Make sure to use both tools for comprehensive analysis unless the query is clearly focused on just one area."
)
econ_manager = Agent(
system_prompt=system_prompt,
tools=[market_research, financial_analysis],
callback_handler=None
)
agent_stream = econ_manager.stream_async(query)
result = await show_streams(agent_stream, containers)
return resultstrands_plan_and_execute.py์์๋ plan and execute pattern์ agent๋ฅผ ๊ตฌํํฉ๋๋ค. "planner"์์ ๋จผ์ plan์ ์์ฑํ ํ์ executer๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌํฉ๋๋ค. ์ด๋, ๋ชจ๋ plan์ด ์คํ์ด ์๋์๋ค๋ฉด replanner๊ฐ ์๋ก์ด ๊ณํ์ ์ธ์๋๋ค. ๋ง์ฝ ๋ชจ๋ plan์ด ์คํ์ด ๋์๋ค๋ฉด synthesizer๋ก ์ ํ๋์ด ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
์์ธํ ์ฝ๋๋ strands_plan_and_execute.py๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
builder = GraphBuilder()
# Add nodes
builder.add_node(planner, "planner")
builder.add_node(executor, "executor")
builder.add_node(replanner, "replanner")
builder.add_node(synthesizer, "synthesizer")
# Set entry points (optional - will be auto-detected if not specified)
builder.set_entry_point("planner")
# Add edges (dependencies)
builder.add_edge("planner", "executor")
builder.add_edge("executor", "replanner")
builder.add_edge("replanner", "synthesizer", condition=lambda state: decide_next_step(state) == "synthesizer")
builder.add_edge("replanner", "executor", condition=lambda state: decide_next_step(state) == "executor")Graph with Loops - Multi-Agent Feedback Cycles์ ์ด์ฉํด ์๋์ ๊ฐ์ feedback loop์ ๊ตฌํํฉ๋๋ค.
์์ธํ ์ฝ๋๋ strands_graph_with_loop.py์ ์ฐธ์กฐํฉ๋๋ค. ์ด ์ฝ๋๋ graph_loops_example.py์ ์ฐธ์กฐํ์์ต๋๋ค.
checker = QualityChecker(approval_after=2)
builder = GraphBuilder()
builder.add_node(writer, "writer")
builder.add_node(checker, "checker")
builder.add_node(finalizer, "finalizer")
builder.add_edge("writer", "checker")
builder.add_edge("checker", "writer", condition=needs_revision)
builder.add_edge("checker", "finalizer", condition=is_approved)
builder.set_entry_point("writer")
graph = builder.build()
result = await graph.invoke_async(question)Chatbot์ ์ฐ์์ ์ธ ์ฌ์ฉ์์ ์ํธ์์ฉ์ ํตํด ์ฌ์ฉ์์ ๊ฒฝํ์ ํฅ์์ํฌ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด ์ด์ ๋ํ์ ๋ด์ฉ์ ์๋ก์ด ๋ํ์์ ํ์ฉํ ์ ์์ด์ผํ๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก chatbot์ sliding window๋ฅผ ์ด์ฉํด ์๋ก์ด transaction๋ง๋ค ์ด์ ๋ํ๋ด์ฉ์ context๋ก ์ ๊ณตํด์ผ ํ์ต๋๋ค. ์ฌ๊ธฐ์์๋ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ด์ ๋ํ๋ด์ฉ์ ์ฐธ์กฐํ ์ ์๋๋ก short term/long term ๋ฉ๋ชจ๋ฆฌ๋ฅผ MCP๋ฅผ ์ด์ฉํด ํ์ฉํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด context์ ๋ถํ์ํ ์ด์ ๋ํ๊ฐ ํฌํจ๋์ง ์์์ ์ฌ์ฉ์์ ์๋๋ฅผ ๋ช ํํ ๋ฐ์ํ๊ณ ๋น์ฉ๋ ์ต์ ํ ํ ์ ์์ต๋๋ค.
Short term memory๋ฅผ ์ํด์๋ ๋ํ transaction์ ์๋์ ๊ฐ์ด agentcore์ memory์ ์ ์ฅํฉ๋๋ค. ์์ธํ ์ฝ๋๋ agentcore_memory.py์ ์ฐธ์กฐํฉ๋๋ค.
def save_conversation_to_memory(memory_id, actor_id, session_id, query, result):
event_timestamp = datetime.now(timezone.utc)
conversation = [
(query, "USER"),
(result, "ASSISTANT")
]
memory_result = memory_client.create_event(
memory_id=memory_id,
actor_id=actor_id,
session_id=session_id,
event_timestamp=event_timestamp,
messages=conversation
)์ดํ, ๋ํ์ค์ ์ฌ์ฉ์์ ์ด์ ๋ํ์ ๋ณด๊ฐ ํ์ํ๋ค๋ฉด, mcp_server_short_term_memory.py์ ๊ฐ์ด memory, actor, session๋ก max_results ๋งํผ์ ์ด์ ๋ํ๋ฅผ ์กฐํํ์ฌ ํ์ฉํฉ๋๋ค.
events = client.list_events(
memory_id=memory_id,
actor_id=actor_id,
session_id=session_id,
max_results=max_results
)Long term meory๋ฅผ ์ํด ํ์ํ ์ ๋ณด์๋ memory, actor, session, namespace๊ฐ ์์ต๋๋ค. ์๋์ ๊ฐ์ด ์ด๋ฏธ ์ ์ฅ๋ ๊ฐ์ด ์๋ค๋ฉด ๊ฐ์ ธ์ค๊ณ , ์๋ค๋ฉด ์์ฑํฉ๋๋ค. ์์ธํ ์ฝ๋๋ strands_agent.py์ ์ฐธ์กฐํฉ๋๋ค.
# initate memory variables
memory_id, actor_id, session_id, namespace = agentcore_memory.load_memory_variables(chat.user_id)
logger.info(f"memory_id: {memory_id}, actor_id: {actor_id}, session_id: {session_id}, namespace: {namespace}")
if memory_id is None:
# retrieve memory id
memory_id = agentcore_memory.retrieve_memory_id()
logger.info(f"memory_id: {memory_id}")
# create memory if not exists
if memory_id is None:
memory_id = agentcore_memory.create_memory(namespace)
# create strategy if not exists
agentcore_memory.create_strategy_if_not_exists(memory_id=memory_id, namespace=namespace, strategy_name=chat.user_id)
# save memory variables
agentcore_memory.update_memory_variables(
user_id=chat.user_id,
memory_id=memory_id,
actor_id=actor_id,
session_id=session_id,
namespace=namespace)์์ฑํ AI ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ํ์ค ํ์ํ ๋ฉ๋ชจ๋ฆฌ ์ ๋ณด๊ฐ ์๋ค๋ฉด ์ด๋ฅผ MCP๋ฅผ ์ด์ฉํด ์กฐํํฉ๋๋ค. mcp_server_long_term_memory.py์์๋ long term memory๋ฅผ ์ด์ฉํด ๋ํ ์ด๋ฒคํธ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์กฐํํ ์ ์์ต๋๋ค. ์๋๋ ์ ๊ท๋ก ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
response = create_event(
memory_id=memory_id,
actor_id=actor_id,
session_id=session_id,
content=content,
event_timestamp=datetime.now(timezone.utc),
)
event_data = response.get("event", {}) if isinstance(response, dict) else {}๋ํ์ ํ์ํ ์ ๋ณด๋ ์๋์ ๊ฐ์ด ์กฐํํฉ๋๋ค.
contents = []
response = retrieve_memory_records(
memory_id=memory_id,
namespace=namespace,
search_query=query,
max_results=max_results,
next_token=next_token,
)
relevant_data = {}
if isinstance(response, dict):
if "memoryRecordSummaries" in response:
relevant_data["memoryRecordSummaries"] = response["memoryRecordSummaries"]
for memory_record_summary in relevant_data["memoryRecordSummaries"]:
json_content = memory_record_summary["content"]["text"]
content = json.loads(json_content)
contents.append(content)์๋์ ๊ฐ์ด "๋ด๊ฐ ์ข์ํ๋ ์คํฌ์ธ ๋?"๋ฅผ ์ ๋ ฅํ๋ฉด long term memory์์ ์ฌ์ฉ์์ ๋ํ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ต๋ณํ ์ ์์ต๋๋ค.
AWS console์ EC2๋ก ์ ์ํ์ฌ Launch an instance๋ฅผ ์ ํํฉ๋๋ค. [Launch instance]๋ฅผ ์ ํํ ํ์ ์ ๋นํ Name์ ์ ๋ ฅํฉ๋๋ค. (์: es) key pair์ "Proceed without key pair"์ ์ ํํ๊ณ ๋์ด๊ฐ๋๋ค.
Instance๊ฐ ์ค๋น๋๋ฉด [Connet] - [EC2 Instance Connect]๋ฅผ ์ ํํ์ฌ ์๋์ฒ๋ผ ์ ์ํฉ๋๋ค.
์ดํ ์๋์ ๊ฐ์ด python, pip, git, boto3๋ฅผ ์ค์นํฉ๋๋ค.
sudo yum install python3 python3-pip git docker -y
pip install boto3
Workshop์ ๊ฒฝ์ฐ์ ์๋ ํํ๋ก ๋ Credential์ ๋ณต์ฌํ์ฌ EC2 ํฐ๋ฏธ๋์ ์ ๋ ฅํฉ๋๋ค.
์๋์ ๊ฐ์ด git source๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
git clone https://github.com/kyopark2014/strands-agent์๋์ ๊ฐ์ด installer.py๋ฅผ ์ด์ฉํด ์ค์น๋ฅผ ์์ํฉ๋๋ค.
cd strands-agent && python3 installer.pyAPI ๊ตฌํ์ ํ์ํ credential์ secret์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค. ๋ฐ๋ผ์ ์ค์น์ ํ์ํ credential ์ ๋ ฅ์ด ํ์ํ๋ฐ ์๋์ ๊ฐ์ ๋ฐฉ์์ ํ์ฉํ์ฌ ๋ฏธ๋ฆฌ credential์ ์ค๋นํฉ๋๋ค.
- ์ผ๋ฐ ์ธํฐ๋ท ๊ฒ์: Tavily Search์ ์ ์ํ์ฌ ๊ฐ์ ํ API Key๋ฅผ ๋ฐ๊ธํฉ๋๋ค. ์ด๊ฒ์ tvly-๋ก ์์ํฉ๋๋ค.
- ๋ ์จ ๊ฒ์: openweathermap์ ์ ์ํ์ฌ API Key๋ฅผ ๋ฐ๊ธํฉ๋๋ค. ์ด๋ price plan์ "Free"๋ฅผ ์ ํํฉ๋๋ค.
์ค์น๊ฐ ์๋ฃ๋๋ฉด ์๋์ ๊ฐ์ CloudFront๋ก ์ ์ํ์ฌ ๋์์ ํ์ธํฉ๋๋ค.
์ธํ๋ผ๊ฐ ๋์ด์ ํ์์์ ๋์๋ uninstaller.py๋ฅผ ์ด์ฉํด ์ ๊ฑฐํฉ๋๋ค.
python uninstaller.py
AWS console์ EC2๋ก ์ ์ํ์ฌ Launch an instance๋ฅผ ์ ํํ์ฌ ์๋์ ๊ฐ์ด ์๋์ ๊ฐ์ด "app-for-es-us"๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๋ instance id๋ฅผ ์ ํํฉ๋๋ค.
[connect]๋ฅผ ์ ํํ ํ์ Session Manager๋ฅผ ์ ํํ์ฌ ์ ์ํฉ๋๋ค.
์ดํ ์๋์ ๊ฐ์ด ์ ๋ฐ์ดํธํ ํ์ ๋ค์ ๋ธ๋ผ์ฐ์ ์์ ํ์ธํฉ๋๋ค.
cd ~/strands-agent/ && sudo ./update.sh
EC2 console์์ "app-for-es-us"๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๋ instance id๋ฅผ ์ ํ ํ ํ์, EC2์ Session Manager๋ฅผ ์ด์ฉํด ์ ์ํฉ๋๋ค.
๋จผ์ ์๋์ ๊ฐ์ด ํ์ฌ docker container ID๋ฅผ ํ์ธํฉ๋๋ค.
sudo docker ps
์ดํ ์๋์ ๊ฐ์ด container ID๋ฅผ ์ด์ฉํด ๋ก๊ทธ๋ฅผ ํ์ธํฉ๋๋ค.
sudo docker logs [container ID]
์ค์ ์คํ์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
AWS ํ๊ฒฝ์ ์ ํ์ฉํ๊ธฐ ์ํด์๋ AWS CLI๋ฅผ ์ค์นํ์ฌ์ผ ํฉ๋๋ค. EC2์์ ๋ฐฐํฌํ๋ ๊ฒฝ์ฐ์๋ ๋ณ๋๋ก ์ค์น๊ฐ ํ์ํ์ง ์์ต๋๋ค. Local์ ์ค์น์๋ ์๋ ๋ช ๋ น์ด๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
AWS credential์ ์๋์ ๊ฐ์ด AWS CLI๋ฅผ ์ด์ฉํด ๋ฑ๋กํฉ๋๋ค.
aws configure
์ค์นํ๋ค๊ฐ ๋ฐ์ํ๋ ๊ฐ์ข ๋ฌธ์ ๋ Kiro-cli๋ฅผ ์ด์ฉํด ๋น ๋ฅด๊ฒ ์์ ํฉ๋๋ค. ์๋์ ๊ฐ์ด ์ค์นํ ์ ์์ง๋ง, Windows์์๋ Kiro ์ค์น์์ ๋ค์ด๋ก๋ ์ค์นํฉ๋๋ค. ์คํ์๋ ์ ์์ "kiro-cli"๋ผ๊ณ ์ ๋ ฅํฉ๋๋ค.
curl -fsSL https://cli.kiro.dev/install | bashvenv๋ก ํ๊ฒฝ์ ๊ตฌ์ฑํ๋ฉด ํธ๋ฆฌํ๊ฒ ํจํค์ง๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์๋์ ๊ฐ์ด ํ๊ฒฝ์ ์ค์ ํฉ๋๋ค.
python -m venv .venv
source .venv/bin/activate
์ดํ ๋ค์ด๋ก๋ ๋ฐ์ github ํด๋๋ก ์ด๋ํ ํ์ ์๋์ ๊ฐ์ด ํ์ํ ํจํค์ง๋ฅผ ์ถ๊ฐ๋ก ์ค์น ํฉ๋๋ค.
pip install -r requirements.txt
์ดํ ์๋์ ๊ฐ์ ๋ช ๋ น์ด๋ก streamlit์ ์คํํฉ๋๋ค.
streamlit run application/app.py
"us-west-2์ AWS bucket ๋ฆฌ์คํธ๋?"์ ๊ฐ์ด ์ ๋ ฅํ๋ฉด, aws cli๋ฅผ ํตํด ํ์ํ operation์ ์ํํ๊ณ ์ป์ด์ง ๊ฒฐ๊ณผ๋ฅผ ์๋์ ๊ฐ์ด ๋ณด์ฌ์ค๋๋ค.
MCP๋ก wikipedia๋ฅผ ์ค์ ํ๊ณ "strand์ ๋ํด ์ค๋ช ํด์ฃผ์ธ์."๋ผ๊ณ ์ง๋ฌธํ๋ฉด wikipedia์ search tool์ ์ด์ฉํ์ฌ ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
ํน์ Cloudwatch์ ๋ก๊ทธ๋ฅผ ์ฝ์ด์, ๋ก๊ทธ์ ํน์ด์ ์ ํ์ธํ ์ ์์ต๋๋ค.
"Image generation" MCP๋ฅผ ์ ํํ๊ณ , "AWS์ ํ๊ตญ์ธ solutions architect์ ๋ชจ์ต์ ๊ทธ๋ ค์ฃผ์ธ์."๋ผ๊ณ ์ ๋ ฅํ๋ฉด ์๋์ ๊ฐ์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
Introducing Strands Agents, an Open Source AI Agents SDK
Strands Agents์ ์คํ ์์ค AI ์์ด์ ํธ SDK ์ดํด๋ณด๊ธฐ
Drug Discovery Agent based on Amazon Bedrock
์์ฑํ AI๋ก AWS ๋ณด์ ์ ๊ฒ ์๋ํํ๊ธฐ: Q CLI์์ Strands Agents๊น์ง
AI Agent๋ฅผ ํ์ฉํ EKS ์ ํ๋ฆฌ์ผ์ด์ ๋ฐ ์ธํ๋ผ ํธ๋ฌ๋ธ์ํ
Strands Agents ๋ฐ AgentCore์ ํจ๊ปํ๋ ๋ฐ์ด์คยท์ ์ฝ ์ฐ๊ตฌ ์ด์์คํดํธ ๊ตฌํํ๊ธฐ
Strands Agents & Amazon Bedrock AgentCore ์ํฌ์ต
Agentic AI๋ก ๊ตฌํํ๋ ๋ฆฌ๋ทฐ ๊ด๋ฆฌ ์๋ํ
Strands Agent Workshop (ํ๊ตญ์ด)
Agentic AI Workshop: AI Fund Manager
Workshop - Strands SDK์ AgentCore๋ฅผ ํ์ฉํ ์์ด์ ํฑ AI
