React에서 AG-UI 에이전트로
Nx Plugin for AWS는 AG-UI 프로토콜을 노출하는 Strands Agent에 React 웹사이트를 연결하는 생성기를 제공합니다. 이는 AWS IAM 및 Cognito 인증 지원과 함께 웹사이트의 @ag-ui/client HttpAgent로 CopilotKit을 연결합니다.
사전 요구 사항
섹션 제목: “사전 요구 사항”이 생성기를 사용하기 전에 다음을 준비해야 합니다:
- React 웹사이트 (
ts#react-website생성기를 사용하여 생성) protocol=AG-UI를 사용하는 Python Strands Agent (py#strands-agent생성기를 사용하여 생성)- 배포된 에이전트의 경우,
ts#react-website-auth생성기를 통해 추가된 Cognito Auth
사용법
섹션 제목: “사용법”생성기 실행
섹션 제목: “생성기 실행”- 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
- VSCode에서 Nx 콘솔 열기
- 클릭
Generate (UI)"Common Nx Commands" 섹션에서 - 검색
@aws/nx-plugin - connection - 필수 매개변수 입력
- 클릭
Generate
pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connection소스 프로젝트로 React 웹사이트를, 타겟 프로젝트로 AG-UI Strands Agent가 포함된 프로젝트를 선택하라는 메시지가 표시됩니다. 타겟 프로젝트에 여러 컴포넌트(여러 에이전트 또는 다른 컴포넌트 유형 등)가 포함된 경우, 명확히 구분하기 위해 targetComponent를 지정하라는 메시지가 표시됩니다.
| 매개변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| sourceProject 필수 | string | - | 소스 프로젝트 |
| targetProject 필수 | string | - | 연결할 대상 프로젝트 |
| sourceComponent | string | - | 연결을 시작할 소스 컴포넌트 (컴포넌트 이름, 소스 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 소스로 명시적으로 선택하려면 '.'을 사용하세요. |
| targetComponent | string | - | 연결할 대상 컴포넌트 (컴포넌트 이름, 대상 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 대상으로 명시적으로 선택하려면 '.'을 사용하세요. |
생성기 출력
섹션 제목: “생성기 출력”생성기는 단일 공유 AguiProvider 컴포넌트, 연결된 에이전트당 하나의 훅, 그리고 CopilotKit 채팅 컴포넌트를 위한 테마가 적용된 래퍼를 생성합니다:
디렉터리src
디렉터리components
- AguiProvider.tsx 모든 AG-UI 에이전트를 위한 단일
CopilotKitProvider. 첫 번째connection실행 시 생성되고 후속 실행 시 각 새 에이전트를 등록하도록 업데이트됩니다. 디렉터리copilot
- index.tsx 웹사이트의
uxProvider(Cloudscape, Shadcn 또는 테마 없음)와 일치하는 슬롯 기본값으로CopilotChat,CopilotSidebar,CopilotPopup을 재내보냅니다. - ThemeComponents .tsx 슬롯별 테마 컴포넌트(예:
CloudscapeAssistantMessage.tsx,ShadcnChatInput.tsx).uxProvider가Cloudscape또는Shadcn일 때만 제공됩니다.
- index.tsx 웹사이트의
- AguiProvider.tsx 모든 AG-UI 에이전트를 위한 단일
디렉터리hooks
- useAgui<AgentName>.tsx 하나의 AG-UI 에이전트를 등록합니다.
connection실행당 하나의 파일. - useSigV4.tsx SigV4 서명 (IAM 전용)
- useAgui<AgentName>.tsx 하나의 AG-UI 에이전트를 등록합니다.
다른 에이전트에 대해 connection을 두 번째로 실행하면 새로운 useAgui<AgentName>.tsx 훅이 추가되고 AguiProvider.tsx가 두 훅을 모두 등록하도록 업데이트됩니다 — 프로바이더에 대한 사용자 정의 편집 내용은 보존됩니다. main.tsx는 단일 <AguiProvider> 래퍼를 유지하므로 중첩된 프로바이더가 생기지 않습니다.
다음 종속성이 루트 package.json에 추가됩니다:
@copilotkit/react-core—CopilotKitProvider와 채팅 컴포넌트(CopilotChat,CopilotSidebar,CopilotPopup)를 제공합니다@ag-ui/client— 생성된 훅에서 사용하는HttpAgentaws4fetch,oidc-client-ts,react-oidc-context,@aws-sdk/credential-providers— IAM 인증 전용react-oidc-context— Cognito 인증
작동 방식
섹션 제목: “작동 방식”AG-UI 연결
섹션 제목: “AG-UI 연결”각 useAgui<AgentName> 훅은 런타임 구성에서 에이전트의 런타임 값을 읽고 @ag-ui/client HttpAgent를 인스턴스화합니다:
- 배포됨: 런타임 값은 Bedrock AgentCore Runtime ARN이며, AgentCore HTTPS 엔드포인트로 변환됩니다:
https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT - 로컬 개발:
serve-local이 값을 에이전트의 로컬 URL(예:http://localhost:8081)로 재정의합니다
공유 AguiProvider는 생성된 모든 훅을 호출하고 각각을 단일 CopilotKitProvider의 selfManagedAgents에 전개하여 모든 에이전트를 CopilotKit 컴포넌트에 노출합니다.
CopilotKit 통합
섹션 제목: “CopilotKit 통합”CopilotKit은 AG-UI 프로토콜을 위한 1차 참조 React 클라이언트이며 즉시 사용 가능한 채팅 컴포넌트를 제공합니다:
<CopilotChat />— 전체 채팅 인터페이스<CopilotSidebar />— 고정 사이드 패널 채팅<CopilotPopup />— 플로팅 채팅 팝업
이들 중 하나를 <AguiProvider> 래퍼 내부 어디에나 배치하세요(이미 main.tsx에 연결되어 있습니다).
생성된 코드는 에이전트의 구성에 따라 인증을 처리합니다:
- IAM (기본값): AWS SigV4 서명된 HTTP 요청을 사용합니다. 자격 증명은 웹사이트의 인증과 함께 구성된 Cognito Identity Pool에서 가져옵니다.
- Cognito: JWT 액세스 토큰을 Bearer 토큰으로
Authorization헤더에 포함합니다.
인프라
섹션 제목: “인프라”에이전트가 IAM 인증을 사용하는 경우, Cognito Identity Pool의 인증된 역할에 에이전트를 호출할 수 있는 권한을 부여해야 합니다.
const identity = new UserIdentity(this, 'Identity');const myAgent = new MyAgent(this, 'MyAgent');
// Grant the authenticated Cognito role permission to invoke the agentmyAgent.grantInvokeAccess(identity.identityPool.authenticatedRole);grantInvokeAccess는 에이전트의 런타임 ARN에 대한 모든 AgentCore 호출 작업(InvokeAgentRuntime, InvokeAgentRuntimeWithWebSocketStream)을 연결합니다.
module "identity" { source = "../../common/terraform/src/core/user-identity"}
module "my_agent" { source = "../../common/terraform/src/app/agents/my-agent"
appconfig_application_id = module.runtime_config_appconfig.application_id appconfig_application_arn = module.runtime_config_appconfig.application_arn}
# Grant the authenticated Cognito role permission to invoke the agentresource "aws_iam_policy" "invoke_my_agent" { name = "InvokeMyAgentPolicy" policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = [ "bedrock-agentcore:InvokeAgentRuntime", "bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream", ] Resource = [ module.my_agent.agent_core_runtime_arn, "${module.my_agent.agent_core_runtime_arn}/*", ] }] })}
resource "aws_iam_role_policy_attachment" "invoke_my_agent" { role = module.identity.authenticated_role_name policy_arn = aws_iam_policy.invoke_my_agent.arn}에이전트가 Cognito 인증을 사용하는 경우, 웹사이트를 에이전트에 연결하기 위해 추가 인프라를 정의할 필요가 없습니다.
생성된 코드 사용
섹션 제목: “생성된 코드 사용”채팅 인터페이스 추가
섹션 제목: “채팅 인터페이스 추가”agentId와 함께 CopilotKit 컴포넌트를 인스턴스화하여 사용할 에이전트를 선택합니다. id는 에이전트의 이름입니다 — py#strands-agent 생성기를 실행할 때 선택한 것과 동일하며 — 생성된 훅 파일에서도 찾을 수 있습니다(예: packages/web/src/hooks/useAgui<AgentName>.tsx에서 반환된 키).
웹사이트의 uxProvider와 일치하는 테마가 자동으로 적용되도록 생성된 ./components/copilot 모듈에서 채팅 컴포넌트를 임포트합니다:
import { CopilotChat } from './components/copilot';
function ChatPage() { return ( <CopilotChat agentId="agent" labels={{ welcomeMessageText: 'How can I help you today?', chatInputPlaceholder: 'Ask me anything...', }} /> );}여러 AG-UI 에이전트 연결
섹션 제목: “여러 AG-UI 에이전트 연결”에이전트당 한 번씩 connection 생성기를 실행합니다. 공유 AguiProvider를 통해 등록된 모든 에이전트는 앱의 어디에서나 볼 수 있습니다 — 다른 agentId로 CopilotKit 컴포넌트를 인스턴스화하여 각 채팅을 원하는 에이전트로 라우팅합니다:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="story" /> {/* talks to StoryAgent */}<CopilotChat agentId="research" /> {/* talks to ResearchAgent */}모양과 느낌 사용자 정의
섹션 제목: “모양과 느낌 사용자 정의”<CopilotChat /> (그리고 <CopilotSidebar />, <CopilotPopup />)는 재귀적 슬롯 시스템을 사용합니다 — Tailwind 클래스 문자열, prop 객체 또는 사용자 정의 React 컴포넌트로 하위 컴포넌트를 재정의할 수 있습니다. 전체 슬롯 트리는 CopilotKit 슬롯 가이드를 참조하세요.
내장 테마
섹션 제목: “내장 테마”생성기는 React 웹사이트 프로젝트에서 metadata.uxProvider를 읽고 src/components/copilot/index.tsx에 테마가 적용된 래퍼 모듈을 제공하여 추가 구성 없이 채팅 컴포넌트가 나머지 UI와 일치하도록 합니다:
uxProvider | CopilotChat / CopilotSidebar / CopilotPopup에 적용되는 스타일 |
|---|---|
Cloudscape | 메시지가 gen-AI Avatar를 포함한 Cloudscape ChatBubble 내부에 렌더링됩니다(Cloudscape 생성형 AI 채팅 패턴과 일치); 타이핑 인디케이터는 LoadingBar가 되고 입력은 PromptInput입니다. @cloudscape-design/components 및 @cloudscape-design/chat-components로 구축됩니다. |
Shadcn | 어시스턴트 메시지는 Sparkles 아바타와 함께 bg-muted 버블로 렌더링되고, 사용자 메시지는 User 아바타와 함께 bg-primary 버블에 오른쪽 정렬로 렌더링됩니다. 입력은 둥근 Textarea + 알약 모양의 전송/중지 Button입니다(Enter는 제출, Shift+Enter는 줄바꿈). 공유 common-shadcn 패키지의 shadcn 프리미티브를 사용합니다. |
None (또는 기타) | 테마 없음 — 모듈은 단순히 기본 CopilotKit 컴포넌트를 재내보냅니다. |
테마가 자동으로 적용되도록 로컬 테마 모듈에서 테마가 적용된 컴포넌트를 임포트합니다(@copilotkit/react-core/v2에서 직접 임포트하지 않음):
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="agent" />테마는 슬롯 기본값으로 적용되므로 명시적으로 전달하는 슬롯은 여전히 우선합니다 — 일회성 재정의가 필요할 때마다 완전한 제어권을 유지합니다.
테마 사용자 정의
섹션 제목: “테마 사용자 정의”생성된 테마는 완전히 프로젝트 내부에 있습니다:
src/components/copilot/index.tsx— 테마가 적용된CopilotChat/CopilotSidebar/CopilotPopup과cloudscapeCopilotTheme/shadcnCopilotTheme객체를 내보냅니다. 이 파일을 편집하여 앱의 모든 채팅에 대한 기본 슬롯 연결을 변경합니다.src/components/copilot/<ThemeComponent>.tsx— 슬롯별 테마 컴포넌트(예:CloudscapeAssistantMessage,ShadcnChatInput). 이들을 편집하여 테마를 재연결하지 않고 단일 슬롯의 모양을 조정합니다.
예를 들어, 나머지 테마를 유지하면서 자체 사용자 메시지 렌더러를 삽입하려면 src/components/copilot/의 관련 파일을 편집하고 index.tsx에서 재내보냅니다.
슬롯을 통한 Tailwind 스타일링
섹션 제목: “슬롯을 통한 Tailwind 스타일링”채팅별 재정의는 테마와 함께 여전히 작동합니다 — 슬롯 prop으로 전달하는 모든 것이 테마 기본값을 재정의합니다:
<CopilotChat agentId="agent" // style the input and its children input={{ textArea: 'text-blue-600', sendButton: 'bg-blue-600 hover:bg-blue-700', }} // style nested message slots messageView={{ assistantMessage: 'bg-blue-50 rounded-xl p-2', userMessage: 'bg-blue-100 rounded-xl', }}/>사용자 정의 컴포넌트로 슬롯 교체
섹션 제목: “사용자 정의 컴포넌트로 슬롯 교체”모든 슬롯은 className 대신 React 컴포넌트를 받을 수 있으므로 기본값을 완전히 교체할 수 있습니다:
import { CopilotChat } from './components/copilot';
const MySendButton: React.FC<{ onClick: () => void }> = ({ onClick }) => ( <button onClick={onClick} className="my-send-btn"> Send </button>);
<CopilotChat agentId="agent" input={{ sendButton: MySendButton }}/>;더 깊은 재정의도 동일한 형태를 따릅니다 — 예를 들어 어시스턴트 메시지의 복사 버튼만 교체:
<CopilotChat agentId="agent" messageView={{ assistantMessage: { copyButton: ({ onClick }) => <button onClick={onClick}>Copy</button>, }, }}/>로컬 개발
섹션 제목: “로컬 개발”연결 생성기는 자동으로 serve-local 통합을 구성합니다:
nx serve-local <website>를 실행하면 에이전트의 로컬 서버도 시작됩니다- 런타임 구성이 로컬 AG-UI URL(예:
http://localhost:8081)을 가리키도록 재정의됩니다 - 웹사이트와 에이전트가 함께 핫 리로드됩니다
pnpm nx serve-local <WebsiteProject>yarn nx serve-local <WebsiteProject>npx nx serve-local <WebsiteProject>bunx nx serve-local <WebsiteProject>