React에서 AG-UI Agent로
Nx Plugin for AWS는 AG-UI 프로토콜을 노출하는 Agent에 React 웹사이트를 연결하는 생성기를 제공합니다. 이는 웹사이트에서 @ag-ui/client HttpAgent와 함께 CopilotKit을 연결하며, AWS IAM 및 Cognito 인증을 지원합니다.
전제 조건
섹션 제목: “전제 조건”이 생성기를 사용하기 전에 다음이 필요합니다:
- React 웹사이트 (
ts#website생성기를 사용하여 생성) protocol=ag-ui를 사용하는 TypeScript 또는 Python Agent (ts#agent또는py#agent생성기를 사용하여 생성)- 배포된 에이전트의 경우,
ts#website#auth생성기를 통해 추가된 Cognito Auth
사용법
섹션 제목: “사용법”생성기 실행
섹션 제목: “생성기 실행”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- 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
- VSCode에서 Nx 콘솔 열기
- 클릭
Generate (UI)"Common Nx Commands" 섹션에서 - 검색
@aws/nx-plugin - connection - 필수 매개변수 입력
- 클릭
Generate
소스 프로젝트로 React 웹사이트를, 타겟 프로젝트로 AG-UI Agent가 포함된 프로젝트를 선택하라는 메시지가 표시됩니다. 타겟 프로젝트에 여러 컴포넌트(여러 에이전트 또는 다른 컴포넌트 유형)가 포함된 경우, 명확히 구분하기 위해 targetComponent를 지정하라는 메시지가 표시됩니다.
| 매개변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| sourceProject 필수 | string | - | 소스 프로젝트 |
| targetProject 필수 | string | - | 연결할 대상 프로젝트 |
| sourceComponent | string | - | 연결을 시작할 소스 컴포넌트 (컴포넌트 이름, 소스 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 소스로 명시적으로 선택하려면 '.'을 사용하세요. |
| targetComponent | string | - | 연결할 대상 컴포넌트 (컴포넌트 이름, 대상 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 대상으로 명시적으로 선택하려면 '.'을 사용하세요. |
| preferInstallDependencies | boolean | true | 생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요 (후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다); 마지막에 한 번만 설치합니다. |
생성기 출력
섹션 제목: “생성기 출력”생성기는 단일 공유 AguiProvider 컴포넌트, 연결된 에이전트당 하나의 훅, 그리고 CopilotKit 채팅 컴포넌트를 위한 테마 래퍼를 생성합니다:
디렉터리src
디렉터리components
- AguiProvider.tsx 모든 AG-UI 에이전트를 위한 단일
CopilotKitProvider. 첫 번째connection실행 시 생성되고 후속 실행 시 각 새 에이전트를 등록하도록 업데이트됩니다. 디렉터리copilot
- index.tsx 웹사이트의
ux(Cloudscape, Shadcn 또는 테마 없음)와 일치하는 슬롯 기본값으로CopilotChat,CopilotSidebar및CopilotPopup을 재내보냅니다. - ThemeComponents .tsx 슬롯별 테마 컴포넌트(예:
CloudscapeAssistantMessage.tsx,ShadcnChatInput.tsx).ux가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 - 로컬 개발:
dev가 값을 에이전트의 로컬 URL(예:http://localhost:8081)로 재정의합니다
공유 AguiProvider는 생성된 모든 훅을 호출하고 각각을 단일 CopilotKitProvider의 selfManagedAgents에 펼쳐서 CopilotKit 컴포넌트에 모두 노출합니다.
CopilotKit 통합
섹션 제목: “CopilotKit 통합”CopilotKit은 AG-UI 프로토콜을 위한 1st-party 참조 React 클라이언트이며 즉시 사용 가능한 채팅 컴포넌트를 제공합니다:
<CopilotChat />— 전체 채팅 인터페이스<CopilotSidebar />— 고정 사이드 패널 채팅<CopilotPopup />— 플로팅 채팅 팝업
이들 중 하나를 <AguiProvider> 래퍼 내부 어디에나 배치할 수 있습니다(이미 main.tsx에 연결되어 있습니다).
생성된 코드는 에이전트의 구성에 따라 인증을 처리합니다:
- IAM (기본값): AWS SigV4 서명된 HTTP 요청을 사용합니다. 자격 증명은 웹사이트의 인증과 함께 구성된 Cognito Identity Pool에서 가져옵니다.
- Cognito: JWT 액세스 토큰을 Bearer 토큰으로
Authorization헤더에 포함합니다.
세션과 스레드
섹션 제목: “세션과 스레드”AG-UI와 AgentCore Runtime은 각각 대화를 다르게 식별하며, 생성된 훅은 이들을 함께 연결합니다:
threadId— AG-UI 대화 식별자로, 요청 본문에 전송됩니다. CopilotKit은 명시적인threadId를 전달하지 않는 한 채팅당 무작위 UUID를 생성합니다.- Session ID — AgentCore Runtime 세션으로,
X-Amzn-Bedrock-AgentCore-Runtime-Session-Id헤더에 전송됩니다. 요청을 처리하는 microVM을 선택하며, 에이전트의session.ts/session.py가 대화 상태를 키로 사용하는 것입니다.
훅은 스레드 ID에서 세션 ID를 파생하여 AgentCore Runtime이 요구하는 33자로 오른쪽 패딩합니다:
function agentCoreSessionId(input: RunAgentInput): string { return (input.threadId ?? '').padEnd(33, '0');}threadId를 설정하지 않는 것이 가장 간단합니다 — CopilotKit이 생성한 UUID는 이미 36자입니다. 명시적으로 전달하는 경우 최소 33자로 만드세요. 패딩은 후행 문자만 다른 스레드 ID를 동일한 세션에 매핑하기 때문입니다.
Session ID와 Thread ID는 모두 브라우저에서 제공됩니다. 각 사용자를 자신의 대화로 제한하려면 py#agent 또는 ts#agent 가이드를 참조하세요.
인프라
섹션 제목: “인프라”에이전트가 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는 에이전트의 이름입니다 — ts#agent 또는 py#agent 생성기를 실행할 때 선택한 것과 동일하며 — 생성된 훅 파일(예: packages/web/src/hooks/useAgui<AgentName>.tsx에서 반환된 키)에서도 찾을 수 있습니다.
웹사이트의 ux와 일치하는 테마가 자동으로 적용되도록 생성된 ./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 Agent 연결
섹션 제목: “여러 AG-UI Agent 연결”에이전트당 한 번씩 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.ux를 읽고 src/components/copilot/index.tsx에 테마 래퍼 모듈을 제공하여 추가 구성 없이 채팅 컴포넌트가 나머지 UI와 일치하도록 합니다:
ux | 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>, }, }}/>로컬 개발
섹션 제목: “로컬 개발”연결 생성기는 자동으로 dev 통합을 구성합니다:
nx dev <website>를 실행하면 에이전트의 로컬 서버도 시작됩니다- 런타임 구성이 로컬 AG-UI URL(예:
http://localhost:8081)을 가리키도록 재정의됩니다 - 웹사이트와 에이전트가 함께 핫 리로드됩니다
pnpm nx dev <WebsiteProject>yarn nx dev <WebsiteProject>npx nx dev <WebsiteProject>bunx nx dev <WebsiteProject>