에이전트 실행

기본 에이전트 추상화는 에이전트를 실행하기 위한 다양한 옵션을 노출합니다. 호출자는 0개, 1개 또는 많은 입력 메시지를 제공할 수 있습니다. 호출자는 스트리밍과 비 스트리밍 중에서 선택할 수도 있습니다. 다양한 사용 시나리오를 살펴보겠습니다.

스트리밍 및 비 스트리밍

Microsoft Agent Framework는 에이전트를 실행하기 위한 스트리밍 및 비 스트리밍 방법을 모두 지원합니다.

비 스트리밍의 경우 메서드를 RunAsync 사용합니다.

Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));

스트리밍의 경우 메서드를 RunStreamingAsync 사용합니다.

await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.Write(update);
}

비 스트리밍의 경우 메서드를 run 사용합니다.

result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)

스트리밍의 경우 .와 함께 run메서드를 stream=True 사용합니다. 비동기적으로 반복할 수 있는 개체를 반환 ResponseStream 합니다.

async for update in agent.run("What is the weather like in Amsterdam?", stream=True):
    if update.text:
        print(update.text, end="", flush=True)

ResponseStream

반환된 ResponseStream 개체는 run(..., stream=True) 다음 두 가지 사용 패턴을 지원합니다.

패턴 1: 비동기 반복 - 실시간 표시를 위해 도착하는 업데이트를 처리합니다.

response_stream = agent.run("Tell me a story", stream=True)
async for update in response_stream:
    if update.text:
        print(update.text, end="", flush=True)

패턴 2: 직접 종료 - 반복을 건너뛰고 전체 응답을 가져옵니다.

response_stream = agent.run("Tell me a story", stream=True)
final = await response_stream.get_final_response()
print(final.text)

패턴 3: 결합 - 실시간 표시를 반복한 다음 집계된 결과를 가져옵니다.

response_stream = agent.run("Tell me a story", stream=True)

# First, iterate to display streaming output
async for update in response_stream:
    if update.text:
        print(update.text, end="", flush=True)

# Then get the complete response (uses already-collected updates, does not re-iterate)
final = await response_stream.get_final_response()
print(f"\n\nFull response: {final.text}")
print(f"Messages: {len(final.messages)}")

에이전트 실행 옵션

기본 에이전트 추상화는 각 에이전트 실행에 대한 옵션 개체를 전달할 수 있지만 추상화 수준에서 실행을 사용자 지정하는 기능은 매우 제한적입니다. 에이전트는 크게 달라질 수 있으므로 일반적인 사용자 지정 옵션은 없습니다.

호출자가 작업 중인 에이전트의 형식을 알고 있는 경우 실행을 사용자 지정할 수 있도록 형식별 옵션을 전달할 수 있습니다.

예를 들어 여기서 에이전트는 a ChatClientAgent 이며 상속되는 개체를 ChatClientAgentRunOptions 전달할 수 있습니다 AgentRunOptions. 이렇게 하면 호출자가 빌드된 항목에 전달되기 전에 에이전트 수준 옵션과 병합되는 사용자 지정 ChatOptionsIChatClient 제공할 수 ChatClientAgent 있습니다.

var chatOptions = new ChatOptions() { Tools = [AIFunctionFactory.Create(GetWeather)] };
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", options: new ChatClientAgentRunOptions(chatOptions)));

Python 에이전트는 options 매개 변수를 통해 각 실행을 사용자 지정할 수 있습니다. 옵션은 TypedDict로 전달되며 생성 시간(통해 default_options)과 실행당(통해 options) 둘 다에서 설정할 수 있습니다. 각 공급자에는 공급자별 설정에 대한 전체 IDE 자동 완성 및 형식 검사를 제공하는 고유한 TypedDict 클래스가 있습니다.

일반 옵션은 다음과 같습니다.

  • max_tokens: 생성할 최대 토큰 수
  • temperature: 응답 생성의 임의성을 제어합니다.
  • model: 이 특정 실행에 대한 모델 재정의
  • top_p: Nucleus 샘플링 매개 변수
  • response_format: 응답 형식 지정(예: 구조적 출력)

비고

tools 매개 변수는 instructions 직접 키워드 인수로 유지되며 사전을 options 통해 전달되지 않습니다.

from agent_framework.openai import OpenAIChatClient, OpenAIChatOptions

# Set default options at construction time
agent = OpenAIChatClient().as_agent(
    instructions="You are a helpful assistant",
    default_options={
        "temperature": 0.7,
        "max_tokens": 500
    }
)

# Run with custom options (overrides defaults)
# OpenAIChatOptions provides IDE autocomplete for all OpenAI-specific settings
options: OpenAIChatOptions = {
    "temperature": 0.3,
    "max_tokens": 150,
    "model": "gpt-4o",
    "presence_penalty": 0.5,
    "frequency_penalty": 0.3
}

result = await agent.run(
    "What is the weather like in Amsterdam?",
    options=options
)

# Streaming with custom options
async for update in agent.run(
    "Tell me a detailed weather forecast",
    stream=True,
    options={"temperature": 0.7, "top_p": 0.9},
    tools=[additional_weather_tool]  # tools is still a keyword argument
):
    if update.text:
        print(update.text, end="", flush=True)

각 공급자에는 해당 공급자가 지원하는 전체 옵션 집합을 노출하는 고유한 TypedDict 클래스(예: OpenAIChatOptions, AnthropicChatOptions, OllamaChatOptions)가 있습니다.

실행 default_options 당 옵션이 둘 다 options 제공되면 실행당 옵션이 우선하며 기본값과 병합됩니다.

응답 형식

에이전트의 스트리밍 및 비 스트리밍 응답에는 에이전트에서 생성된 모든 콘텐츠가 모두 포함됩니다. 콘텐츠에는 에이전트의 결과(즉, 사용자 질문에 대한 답변)가 아닌 데이터가 포함될 수 있습니다. 반환된 다른 데이터의 예로는 함수 도구 호출, 함수 도구 호출 결과, 추론 텍스트, 상태 업데이트 등이 있습니다.

반환된 모든 콘텐츠가 결과인 것은 아니므로 결과를 다른 콘텐츠와 격리하려고 할 때 특정 콘텐츠 형식을 찾는 것이 중요합니다.

응답에서 텍스트 결과를 추출하려면 모든 항목의 모든 TextContentChatMessages 항목을 집계해야 합니다. 이를 Text 간소화하기 위해 모든 TextContent을 집계하는 모든 응답 형식에서 속성을 사용할 수 있습니다.

비 스트리밍 사례의 경우 모든 항목이 하나의 AgentResponse 개체로 반환됩니다. AgentResponse 에서는 속성을 통해 Messages 생성된 메시지에 액세스할 수 있습니다.

var response = await agent.RunAsync("What is the weather like in Amsterdam?");
Console.WriteLine(response.Text);
Console.WriteLine(response.Messages.Count);

스트리밍 사례 AgentResponseUpdate 의 경우 개체가 생성될 때 스트리밍됩니다. 각 업데이트에는 에이전트의 결과 일부와 기타 다양한 콘텐츠 항목이 포함될 수 있습니다. 비 스트리밍 사례와 마찬가지로, 속성을 사용하여 Text 업데이트에 포함된 결과의 일부를 가져와서 속성을 통해 Contents 세부 정보를 드릴할 수 있습니다.

await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.WriteLine(update.Text);
    Console.WriteLine(update.Contents.Count);
}

비 스트리밍 사례의 경우 모든 항목이 하나의 AgentResponse 개체로 반환됩니다. AgentResponse 에서는 속성을 통해 messages 생성된 메시지에 액세스할 수 있습니다.

응답에서 텍스트 결과를 추출하려면 모든 항목의 모든 TextContentMessage 항목을 집계해야 합니다. 이를 Text 간소화하기 위해 모든 TextContent을 집계하는 모든 응답 형식에서 속성을 사용할 수 있습니다.

response = await agent.run("What is the weather like in Amsterdam?")
print(response.text)
print(len(response.messages))

# Access individual messages
for message in response.messages:
    print(f"Role: {message.role}, Text: {message.text}")

스트리밍 사례 AgentResponseUpdate 의 경우 개체는 반환ResponseStream된 개체를 통해 run(..., stream=True) 생성될 때 스트리밍됩니다. 각 업데이트에는 에이전트의 결과 일부와 기타 다양한 콘텐츠 항목이 포함될 수 있습니다. 비 스트리밍 사례와 마찬가지로, 속성을 사용하여 text 업데이트에 포함된 결과의 일부를 가져와서 속성을 통해 contents 세부 정보를 드릴할 수 있습니다.

response_stream = agent.run("What is the weather like in Amsterdam?", stream=True)
async for update in response_stream:
    print(f"Update text: {update.text}")
    print(f"Content count: {len(update.contents)}")

    # Access individual content items
    for content in update.contents:
        if hasattr(content, 'text'):
            print(f"Content: {content.text}")

# Get the aggregated final response after streaming
final = await response_stream.get_final_response()
print(f"Complete text: {final.text}")

메시지 유형

에이전트의 입력 및 출력은 메시지로 표시됩니다. 메시지는 콘텐츠 항목으로 세분화됩니다.

Microsoft 에이전트 프레임워크는 Microsoft.Extensions.AI 추상화에서 제공하는 메시지 및 콘텐츠 형식을 사용합니다. 메시지는 클래스로 ChatMessage 표시되고 모든 콘텐츠 클래스는 기본 AIContent 클래스에서 상속됩니다.

다양한 유형의 콘텐츠를 나타내는 데 사용되는 다양한 AIContent 하위 클래스가 있습니다. 일부는 기본 Microsoft.Extensions.AI 추상화의 일부로 제공되지만 공급자는 필요한 경우 고유한 형식을 추가할 수도 있습니다.

다음은 Microsoft.Extensions.AI 인기 있는 몇 가지 유형입니다.

유형 Description
TextContent 사용자 또는 개발자의 입력과 에이전트의 출력을 모두 입력할 수 있는 텍스트 콘텐츠입니다. 일반적으로 에이전트의 텍스트 결과를 포함합니다.
DataContent 입력 및 출력이 모두 될 수 있는 이진 콘텐츠입니다. 이미지, 오디오 또는 비디오 데이터를 에이전트(지원되는 위치)와 오가는 데 사용할 수 있습니다.
UriContent 일반적으로 이미지, 오디오 또는 비디오와 같은 호스트된 콘텐츠를 가리키는 URL입니다.
FunctionCallContent 함수 도구를 호출하기 위한 유추 서비스의 요청입니다.
FunctionResultContent 함수 도구 호출의 결과입니다.

Python 에이전트 프레임워크는 agent_framework 패키지의 메시지 및 콘텐츠 형식을 사용합니다. 메시지는 클래스로 Message 표시되고 모든 콘텐츠 항목은 속성으로 Content 구분된 클래스로 type 표시됩니다.

모든 콘텐츠는 각 콘텐츠 형식에 대한 팩터리 메서드를 사용하여 통합 Content 클래스로 표시됩니다. type 속성을 사용하여 콘텐츠 형식을 확인합니다. 사용할 수 있는 콘텐츠 형식은 다음과 같습니다.

콘텐츠 형식 팩토리 메서드 Description
"text" Content.from_text() 입력 및 출력에 대한 텍스트 콘텐츠입니다. 일반적으로 에이전트의 텍스트 결과를 포함합니다.
"text_reasoning" Content.from_text_reasoning() 사고 체인 추론을 지원하는 모델의 추론 텍스트입니다. 보호된 데이터를 포함할 수 있습니다.
"data" Content.from_data(), Content.from_uri() 데이터 URI로 인코딩된 이진 콘텐츠입니다. 이미지, 오디오, 비디오 및 문서에 사용됩니다.
"uri" Content.from_uri() 이미지, 오디오 또는 비디오와 같은 호스트된 콘텐츠를 가리키는 URL입니다.
"error" Content.from_error() 처리가 실패할 때의 오류 정보입니다. 선택적 오류 코드 및 세부 정보를 포함합니다.
"function_call" Content.from_function_call() 함수 도구를 호출하기 위한 AI 서비스의 요청입니다.
"function_result" Content.from_function_result() 함수 도구 호출의 결과입니다.
"usage" Content.from_usage() AI 서비스의 토큰 사용량 및 청구 정보입니다.
"hosted_file" Content.from_hosted_file() 공급자가 호스트하는 파일에 대한 참조입니다(예: OpenAI에 업로드됨).
"hosted_vector_store" Content.from_hosted_vector_store() 공급자가 호스트하는 벡터 저장소에 대한 참조입니다.
"code_interpreter_tool_call" Content.from_code_interpreter_tool_call() 코드 인터프리터를 통해 코드를 실행하기 위한 AI 서비스의 요청입니다.
"code_interpreter_tool_result" Content.from_code_interpreter_tool_result() 코드 인터프리터 실행의 결과입니다.
"image_generation_tool_call" Content.from_image_generation_tool_call() 이미지를 생성하기 위한 AI 서비스의 요청입니다.
"image_generation_tool_result" Content.from_image_generation_tool_result() 이미지 생성 요청의 결과입니다.
"mcp_server_tool_call" Content.from_mcp_server_tool_call() MCP 서버에서 도구를 호출하는 요청입니다.
"mcp_server_tool_result" Content.from_mcp_server_tool_result() MCP 서버 도구 호출의 결과입니다.
"shell_tool_call" Content.from_shell_tool_call() 셸 명령을 실행하기 위한 AI 서비스의 요청입니다.
"shell_tool_result" Content.from_shell_tool_result() 셸 도구 호출의 집계 결과입니다.
"shell_command_output" Content.from_shell_command_output() 단일 셸 명령 실행의 출력입니다.
"function_approval_request" Content.from_function_approval_request() 함수 호출을 실행하기 전에 사용자 승인 요청입니다.
"function_approval_response" Content.from_function_approval_response() 함수 승인 요청에 대한 사용자의 응답입니다.
"oauth_consent_request" Content.from_oauth_consent_request() 사용자가 제공된 링크를 통해 OAuth 동의를 완료하도록 요청합니다.

다양한 콘텐츠 형식으로 작업하는 방법은 다음과 같습니다.

from agent_framework import Message, Content

# Create a text message
text_message = Message(role="user", contents=["Hello!"])

# Create a message with multiple content types
image_data = b"..."  # your image bytes
mixed_message = Message(
    role="user",
    contents=[
        Content.from_text("Analyze this image:"),
        Content.from_data(data=image_data, media_type="image/png"),
    ]
)

# Access content from responses
response = await agent.run("Describe the image")
for message in response.messages:
    for content in message.contents:
        if content.type == "text":
            print(f"Text: {content.text}")
        elif content.type == "data":
            print(f"Data URI: {content.uri}")
        elif content.type == "uri":
            print(f"External URI: {content.uri}")

다음 단계: