에이전트 실행

기본 에이전트 추상화는 에이전트를 실행하기 위한 다양한 옵션을 노출합니다. 호출자는 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)}")

전체 스트림을 사용하기 전에 애플리케이션이 중지될 수 있는 경우 비동기 컨텍스트 관리자로 사용하여 ResponseStream 기본 공급자 스트림을 조기 break 에 닫습니다.

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

async with response_stream:
    async for update in response_stream:
        if update.text:
            print(update.text, end="", flush=True)
        if should_stop(update):
            break

전체 사용, 스트림 오류 await response_stream.close()및 블록을 종료하면 async with 기본 스트림이 해제됩니다. 완전 breakasync with 하지 않은 경우 결정적 정리를 제공하지 않습니다.

사용이 시작되기 전에 순서가 지정된 업데이트 및 최종 결과 게이트를 등록 with_update_gate() 할 수 있습니다 with_result_gate(). 게이트가 반환 None 되어 값을 허용하거나 차단할 예외가 발생합니다. 사용 with_update_transform() 및 with_result_transform() 콘텐츠를 교체해야 하는 경우

스트림이 종료되고 모든 게이트가 성공할 때까지 업데이트를 해제하지 않아야 하는 경우 호출 buffer_updates() 합니다. 결과 변환이 최종 응답을 대체하는 경우 스트림이 해당 신뢰할 수 있는 결과에서 버퍼링된 업데이트를 다시 작성할 수 있도록 전달 result_to_updates 합니다. 이전 buffered_and_gated() 도우미는 더 이상 사용되지 않습니다.

게이트 순서 지정, 변환, 버퍼링, 종료 및 정리의 전체 예제는 ResponseStream 샘플을 참조하세요.

인용 및 주석 읽기

텍스트 Content 는 URL, 파일 및 기타 인용된 원본에 포함 annotations 할 수 있습니다. 각 주석에는 다음과 같은 값이 annotated_regions_coordinate_space 포함될 annotated_regions 수 있습니다.

  • "content" 는 인덱스가 생성된 을 참조한다는 의미입니다 Content.text. 필드를 생략할 때 기본값입니다.
  • "source" 는 인덱스가 원본 문서 문자, 페이지 또는 블록과 같은 인용된 원본을 참조한다는 것을 의미합니다.

생성된 출력에서 소스 좌표 영역을 문자 오프셋으로 적용하지 마세요. 주석 제목, URL, 파일 ID 또는 기타 메타데이터를 사용하여 원본을 렌더링합니다.

Go RunText 에서 쌍의 반복기 ResponseStream 인 A를 반환 (ResponseUpdate, error) 합니다.

비 스트리밍의 경우 스트림을 호출 Collect() 하여 모든 업데이트를 단일 응답으로 수집합니다.

resp, err := a.RunText(ctx, "What is the weather like in Amsterdam?").Collect()
if err != nil {
    panic(err)
}
fmt.Println(resp.String())

스트리밍의 경우 루프를 사용하여 range 스트림을 직접 반복합니다.

for update, err := range a.RunText(ctx, "What is the weather like in Amsterdam?", agent.Stream(true)) {
    if err != nil {
        panic(err)
    }
    fmt.Print(update.String())
}

에이전트 실행 옵션

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

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

예를 들어 여기서 에이전트는 a ChatClientAgent 이며 상속되는 개체를 ChatClientAgentRunOptions 전달할 수 있습니다 AgentRunOptions. 이렇게 하면 호출자가 빌드된 항목에 전달되기 전에 에이전트 수준 옵션과 병합되는 사용자 지정 ChatOptions 을 IChatClient 제공할 수 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 제공되면 실행당 옵션이 우선하며 기본값과 병합됩니다.

에이전트 수준 및 실행 수준 도구가 결합되면 단일 매핑(예: {"type": "web_search"} 하나의 공급자 도구)이 처리됩니다. 매핑은 해당 키로 확장되지 않습니다.

옵션은 variadic agent.Option 인수로 전달됩니다. 사용 가능한 옵션은 다음과 같습니다.

  • agent.Stream(true) - 스트리밍 사용
  • agent.WithSession(session) - 다중 턴 대화를 위한 세션 연결
  • agent.WithStructuredOutput(&v) - 형식화된 값으로 구조화된 출력 요청
  • agent.WithResponseFormat(format) - 응답 형식 지정
  • agent.WithTool(tool) - 이 실행에 대한 도구 추가
  • agent.AllowBackgroundResponses(true) - 백그라운드 응답 사용
resp, err := a.RunText(ctx, "Tell me a joke.",
    agent.Stream(true),
    agent.WithSession(session),
).Collect()

응답 형식

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

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

응답에서 텍스트 결과를 추출하려면 모든 항목의 모든 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}")

ResponseStream 는 값을 생성 *agent.ResponseUpdate 합니다. 각 업데이트에는 다음이 포함됩니다.

  • Contents- 텍스트, 함수 호출 및 사용량과 같은 값 조각 message.Content
  • Role - 메시지 역할(예: 도우미 또는 시스템)
  • MessageID / ResponseID - 메시지 및 응답에 대한 식별자

비 스트리밍 응답에서 전체 텍스트 결과를 가져오려면 다음을 사용합니다 Collect().

resp, err := a.RunText(ctx, "What is the weather like in Amsterdam?").Collect()
if err != nil {
    panic(err)
}
fmt.Println(resp.String())

메시지 유형

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

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

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

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

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

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

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

콘텐츠 형식 팩토리 메서드 설명
"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 동의를 완료하도록 요청합니다.

파운드리 스트리밍 및 비 스트리밍 응답은 도구 상자 또는 호스트된 MCP 도구에 사용자 동의가 필요한 경우 콘텐츠를 모두 포함 oauth_consent_request 할 수 있습니다. 응답 콘텐츠를 검사하거나 user_input_requests 비 스트리밍 응답에 텍스트만 포함되어 있다고 가정하는 대신 도구 상자 설정 및 제한 사항은 Foundry 도구 상자를 참조하세요.

함수 호출 콘텐츠는 실행 소유권도 노출합니다. hosted=True 는 공급자 또는 서비스가 호출을 실행하므로 에이전트 프레임워크가 로컬로 실행하지 않음을 의미합니다. server_name 는 호스트된 서버 경계를 설명하지만 자체에서 호스팅되는 호출을 하지 않습니다.

프레임워크 소유 공급자 및 프로토콜 메타데이터는 아래의 한 수준 네임스페이스additional_properties(예: core, openaifoundry또는 a2a)에 속합니다. 어댑터가 프레임워크의 복사 및 with_namespaced_value() 병합 규칙을 보존할 수 있도록 이름 간격 값을 읽거나 업데이트할 때 사용합니다get_namespaced_value().

병합 가능한 스트리밍 및 AgentResponseUpdate 값은 ChatResponseUpdateContent증분 델타 또는 신뢰할 수 있는 페이로드 또는 "replace" 메시지 스냅샷에 대해 설정할 merge_mode"append" 수 있습니다. 최종 응답 집계는 스트리밍 명령을 사용하고 콘텐츠 수준을 merge_mode지웁니다.

공급자 거부는 다음과 같이 Content(type="text")표시됩니다. 공급자가 거부 의미 체계를 노출하면 Python 실험적 직렬화 가능한 표식을 additional_properties["core"]["model_output_kind"] == "refusal"유지합니다. 구조적 출력 추출은 이 표식을 전달하는 텍스트를 구문 분석하지 않습니다.

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

from agent_framework import Message, Content

# A bare string creates one text content item
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}")

bare 문자열과 단일 항목 문자열 목록은 동일합니다 Message("user", "Hello!")Message("user", ["Hello!"]) . 각 문자열은 하나의 텍스트 콘텐츠 항목을 만듭니다.

Go 에이전트 프레임워크는 패키지의 메시지 및 콘텐츠 형식을 message 사용합니다. 응답 업데이트에는 여러 콘텐츠 항목이 포함될 수 있습니다. 각 항목에서 필요한 콘텐츠 형식을 검사합니다.

스트리밍의 경우 도착 시 업데이트를 개별적으로 처리합니다.

for update, err := range a.RunText(ctx, "Tell me a story.", agent.Stream(true)) {
    if err != nil {
        panic(err)
    }
    for _, c := range update.Contents {
        if text, ok := c.(*message.TextContent); ok {
            fmt.Print(text.Text)
        }
    }
}

Tip

전체 실행 가능한 예제는 전체 샘플을 참조하세요.

실행하는 동안 메시지 삽입

agent.Config.MessageInjector agent.MessageInjector 호스트 또는 도구에서 해당 참조를 구성하고 유지합니다. 해당 세션에 대한 지연 도착 컨텍스트를 큐에 대기하기 위해 해당 오류를 호출 EnqueueMessages(session, messages...) 하고 처리합니다.

큐에 대기 중인 메시지는 실행 내에서 후속 공급자 호출 전에 소비됩니다. 이미 진행 중인 요청을 중단하지 않습니다. RequirePerServiceCallHistoryPersistence 상태 비저장 서비스에 대한 호출 간에 삽입된 메시지와 이전 응답을 유지할 수 있습니다.

Go harness는 기본적으로 메시지 인젝터를 구성합니다. 동일한 에이전트를 실행하는 동안 배송 업데이트를 큐에 대기하는 도구에 대한 메시지 삽입 샘플을 참조하세요.

다음 단계