Activity Protocol 이해하기

Activity Protocol은 Microsoft의 다양한 SDK, 서비스, 클라이언트에서 사용되는 표준 통신 프로토콜입니다. Activity Protocol은 Microsoft 365 Copilot, Microsoft Copilot Studio, Microsoft Teams 및 Microsoft 365 에이전트 SDK에서 사용됩니다. Activity Protocol은 하나의 Activity 구조와 메시지, 이벤트, 상호작용이 채널에서 코드로, 그리고 그 사이의 모든 곳으로 어떻게 흐르는지를 정의합니다. 에이전트는 하나 이상의 채널에 연결하여 사용자와 상호작용하고 다른 에이전트와 협력할 수 있습니다. Activity Protocol은 Microsoft 및 비 Microsoft 클라이언트를 포함한 모든 클라이언트와의 통신 프로토콜을 표준화하여 각 채널마다 별도의 로직을 작성할 필요가 없습니다.

Activity란?

Activity는 사용자와 에이전트 간의 모든 상호작용을 나타내는 구조화된 JSON 객체입니다. Activity는 텍스트 기반 메시지에만 국한되지 않습니다. 여기에는 여러 사용자를 지원하는 클라이언트에서 사용자가 참여하거나 퇴장하는 이벤트, 타이핑 표시, 파일 업로드, 카드 동작, 그리고 개발자가 설계한 맞춤형 이벤트 등 다양한 상호작용 유형이 포함될 수 있습니다.

모든 활동에는 다음에 관한 메타데이터가 포함되어 있습니다.

  • 보낸 사람(From)
  • 수신해야 하는 사람(수신자)
  • 대화 컨텍스트
  • 원본 채널
  • 상호 작용 유형
  • 페이로드 데이터

활동 스키마 - 핵심 속성

이 사양은 Activity Protocol: Activity Protocol - Activity를 정의합니다. Activity Protocol에서 정의된 주요 속성 중 일부는 다음과 같습니다.

속성 Description
Id 활동이 채널에서 시작된 경우 일반적으로 채널이 이 속성을 생성합니다
Type 유형은 활동의 의미를 결정합니다. 예를 들어, 메시지 유형입니다
ChannelID ChannelID는 활동이 발생한 채널을 참조합니다. 예: msteams.
From 활동의 발신자(사용자 또는 에이전트일 수 있음)
Recipient 해당 활동의 대상자
Text 메시지의 텍스트 내용
Attachment 카드, 파일 이미지와 같은 풍부한 콘텐츠

활동 데이터 접근

TurnContext 객체에서 발생하는 작업을 완료하려면 개발자는 활동 내 데이터를 접근해야 합니다.

각 언어별 Microsoft 365 에이전트 SDK에서 TurnContext 클래스를 확인할 수 있습니다.

참고

이 문서의 코드 조각은 C#을 사용합니다. JavaScript와 Python 버전의 문법과 API 구조는 유사합니다.

Microsoft 365 에이전트 SDK에서 TurnContext는 각 대화 턴마다 사용되는 핵심 객체입니다. 이 객체는 수신 액티비티, 응답을 보내는 메서드, 대화 상태 관리, 그리고 단일 대화 턴을 처리하는 데 필요한 컨텍스트에 대한 접근을 제공합니다. 이를 활용해 맥락을 유지하고, 적절한 응답을 보내며, 클라이언트나 채널에서 사용자와 효과적으로 소통하세요. 에이전트가 채널에서 새로운 활동을 수신할 때마다, 에이전트 SDK는 새 TurnContext 인스턴스를 생성하여 이를 등록된 핸들러 또는 메서드에 전달합니다. 이 컨텍스트 객체는 한 턴 동안 존재하며, 턴이 끝나면 폐기됩니다.

은 클라이언트에서 메시지를 보내고, 그 메시지가 코드까지 전달된 뒤 다시 돌아오는 왕복 과정으로 정의됩니다. 코드는 해당 데이터를 처리하고, 필요에 따라 응답을 보내 턴을 완료할 수 있습니다. 이 왕복 과정은 다음과 같은 단계로 나눌 수 있습니다.

  1. 수신 활동: 사용자가 메시지를 보내거나 어떤 행동을 통해 활동을 생성합니다.

  2. 코드가 활동을 수신하고 에이전트가 TurnContext를 사용하여 이를 처리합니다.

  3. 에이전트가 하나 이상의 활동을 다시 보냅니다.

  4. 턴이 끝나면 TurnContext가 폐기됩니다.

TurnContext를 통해 다음과 같은 데이터에 접근할 수 있습니다.

var messageText = turnContext.Activity.Text;
var channelID = turnContext.Activity.ChannelId;

이 코드 조각은 전체 턴의 예시를 보여줍니다.

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken) =>
{
    var userMessage = turnContext.Activity.Text;
    var response = $"you said: {userMessage}";
    await turnContext.SendActivityAsync(MessageFactory.Text(response), cancellationToken);
});

TurnContext 클래스 내부에서 자주 사용되는 주요 정보는 다음과 같습니다.

  • Activity: 활동 정보에 접근하는 주요 방법
  • Adapter: 활동을 생성한 채널 어댑터
  • TurnState: 턴의 상태

활동 유형

활동의 유형은 클라이언트, 사용자, 에이전트 간에 해당 활동의 나머지 부분에서 요구되거나 기대되는 사항을 정의합니다.

여기에는 다음이 포함됩니다.

  • 메시지
  • ConversationUpdate
  • 이벤트
  • 호출
  • 입력

메시지

대표적인 활동 유형은 메시지 유형의 Activity입니다. 이 Activity 유형에는 텍스트, 첨부파일 및 제안된 작업이 포함될 수 있습니다.

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken) =>
{
    var userMessage = turnContext.Activity.Text;
    var response = $"you said: {userMessage}";
    await turnContext.SendActivityAsync(MessageFactory.Text(response), cancellationToken);
});

ConversationUpdate

ConversationUpdate 유형의 Activity는 구성원이 대화에 참여하거나 떠날 때 에이전트에게 알림을 제공합니다. 모든 클라이언트가 이 알림을 지원하는 것은 아니지만, Microsoft Teams는 지원합니다.

다음 코드 조각은 대화에서 새로운 구성원을 환영합니다.

agent.OnActivity(ActivityTypes.ConversationUpdate, async (turnContext turnState, cancellationToken) =>
{
    var membersAdded = turnContext.Activity.MembersAdded
    if (membersAdded != null)
    {
        foreach (var member in membersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome {member.Name}!"), cancellationToken);
            }
        }
    }
})

이벤트

Event 유형의 Activity는 채널이나 클라이언트가 구조화된 데이터를 에이전트에게 전송하기 위해 사용하는 사용자 정의 이벤트입니다. 이 데이터는 Activity 페이로드 구조에 사전에 정의되어 있지 않습니다.

특정 Event 유형에 대응하는 메서드나 라우트 핸들러를 구현해야 합니다. 그 다음, 다음 조건에 따라 원하는 로직을 관리합니다.

  • 이름: 클라이언트가 지정한 이벤트 이름 또는 식별자
  • : 일반적으로 JSON 객체인 이벤트 페이로드
agent.OnActivity(ActivityTypes.Event, async (turnContext turnState, cancellationToken) =>
{
    var eventName = turnContext.Activity.Name;
    var eventValue = turnContext.Activity.Value;

    // custom event (E.g. a switch on eventName)
});

호출

Invoke 유형의 Activity는 클라이언트가 명령이나 작업을 수행하기 위해 에이전트에 호출하는 특정 유형의 활동입니다. 단순한 메시지가 아닙니다. 이러한 유형의 활동은 task/fetch and task/submit을 위한 Microsoft Teams에서 일반적으로 볼 수 있습니다. 모든 채널이 이러한 유형의 활동을 지원하는 것은 아닙니다.

입력

Typing 유형의 Activity는 대화 중 누군가가 입력하고 있음을 나타내는 활동의 한 분류입니다. 예를 들어, Microsoft Teams 클라이언트에서 사람들 간의 대화에서 이 활동을 자주 볼 수 있습니다. 모든 클라이언트가 타이핑 활동을 지원하는 것은 아닙니다. 특히, Microsoft 365 Copilot은 타이핑 활동을 지원하지 않습니다.

await turnContext.SendActivityAsync(new Activity { Type = ActivityTypes.Typing }, cancellationToken); 
await Task.Delay(2000);
await turnContext.SendActivityAsync(MessageFactory.Text("Here is your answer..."), cancellationToken);

활동 만들기 및 보내기

응답을 보내기 위해 TurnContext는 사용자에게 응답을 다시 보내는 여러 가지 메서드 를 제공합니다.

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken))
{
    await turnContext.SendActivityAsync("hello!", cancellationToken: CancellationToken); // uses string directly
    await turnContext.SendActivityAsync(MessageFactory.Text("Hello"), cancellationToken); // uses Message Factory
    await turnContext.SendActivitiesAsync(activities, cancellationToken); // send multiple activities in an Activity array
}

첨부 파일로 작업

에이전트는 사용자(또는 다른 에이전트)가 업로드한 첨부파일을 자주 처리합니다. 클라이언트는 첨부파일이 포함된 Message 활동을 보냅니다(특정 활동 유형이 아닙니다). 코드는 첨부파일이 포함된 메시지를 받아야 하고, 메타데이터를 읽으며, 클라이언트가 제공한 URL에서 파일을 안전하게 가져와야 합니다. 일반적으로 파일을 자신의 저장소로 이동합니다.

첨부파일을 수신하려면

다음 코드는 첨부파일을 받는 방법을 보여줍니다.

agent.OnActivity(ActivityTypes.Message, async(turnContext, turnState, cancellationToken)) =>
{
    var activity = turnContext.Activity;
    if (activity.Attachments != null && activity.Attachments.Count > 0)
    {
        foreach (var attachment in activity.Attachments)
        {
            // get metadata as required e.g. attachment.ContextType or attachment.ContentUrl
            // use the URL to securely download the attachment and complete your business logic
        };
    }
}

일반적으로, 첨부 파일의 실제 내용을 받기 위해 클라이언트는 인증된 GET 요청을 보냅니다. 각 어댑터마다 데이터를 가져오는 방식이 다릅니다. 예를 들어, Teams, OneDrive 등이 있습니다. 또한 이러한 URL들은 보통 수명이 짧으므로, URL이 오래 유효하다고 가정하지 않는 것이 중요합니다. 이러한 제한 때문에 나중에 내용을 참고해야 할 경우 자신의 저장소로 옮기는 것이 중요합니다.

인용

첨부인용 은 동일한 개체 유형이 아니라는 점을 알아두는 것이 중요합니다. Microsoft Teams와 같은 클라이언트들은 각자의 방식으로 인용을 처리합니다. 그들은 Activity엔터티 속성을 활용합니다. activity.Entities.Add를 사용하여 인용을 추가하고, 클라이언트에 따라 특정 Citation 정의를 포함하는 새로운 Entity 객체를 추가할 수 있습니다. 클라이언트가 렌더링하는 방식에 따라 클라이언트에서 역직렬화하는 JSON 개체로 직렬화됩니다. 기본적으로 첨부 파일은 메시지이며 인용은 첨부 파일을 참조할 수 있으며 Activity 페이로드의 Entities에서 전송된 다른 개체입니다.

채널별 구성

Microsoft 365 에이전트 SDK는 개발자들이 지원하는 클라이언트를 포함해 어떤 클라이언트와도 작업할 수 있는 에이전트를 만드는 '허브'로 구축되었습니다. 이 프레임워크를 사용하여 개발자가 자신만의 채널 어댑터를 구축할 수 있는 도구를 제공합니다. 이 아키텍처는 에이전트 개발의 다양성을 제공하며, Microsoft Teams, Slack 등 하나 이상의 클라이언트가 허브에 연결될 수 있도록 클라이언트의 확장성을 지원합니다.

채널마다 기능과 한계가 다릅니다.

ActivitychannelId 속성을 확인하여 해당 활동을 수신한 채널을 확인할 수 있습니다.

채널에는 모든 채널에서 사용하는 일반적인 Activity 페이로드와 일치하지 않는 특정 데이터가 포함되어 있습니다. 이 데이터를 TurnContext.[Activity.ChannelData](/dotnet/api/microsoft.agents.core.models.activity.channeldata) 속성에서 변수로 캐스트하여 코드에 사용할 수 있습니다.

다음 섹션에서는 일반적으로 사용되는 클라이언트와 작업할 때 고려해야 할 사항을 요약합니다.

Microsoft Teams

  • 고급 기능을 갖춘 풍부한 적응형 카드를 지원합니다.
  • 메시지 업데이트 및 삭제를 지원합니다.
  • Teams 기능을 위한 특정 채널 데이터가 있습니다(예: 언급 및 회의 정보).
  • 작업 모듈을 위한 Invoke 활동을 지원합니다.

Microsoft 365 Copilot

  • 주로 메시지 활동에 중점을 둡니다.
  • 응답에 인용과 참조를 지원합니다.
  • 스트리밍 응답이 필요합니다.
  • 풍부한 카드와 적응형 카드에 대한 지원이 제한적입니다.

웹 채팅/DirectLine

웹 채팅은 에이전트가 HTTPS를 통해 통신할 수 있는 HTTP 프로토콜입니다.

  • 모든 활동 유형을 완벽하게 지원합니다.
  • 사용자 지원 채널 데이터를 지원합니다.

비-Microsoft 채널

이러한 채널에는 Slack, Facebook 등이 포함됩니다.

  • 특정 활동 유형에 대한 지원이 제한적일 수 있습니다.
  • 카드 렌더링이 다르거나 지원되지 않을 수도 있습니다.
  • 항상 특정 채널 문서를 확인하세요.

다음 단계