Microsoft 에이전트 프레임워크 워크플로 오케스트레이션 - Magentic

마젠틱 오케스트레이션은 AutoGen에서 발명한 Magentic-One 시스템을 기반으로 설계되었습니다. 동적 협업이 필요한 복잡한 개방형 작업을 위해 설계된 유연한 범용 다중 에이전트 패턴입니다. 이 패턴에서 전용 Magentic 관리자는 특수 에이전트 팀을 조정하여 진화하는 컨텍스트, 작업 진행률 및 에이전트 기능에 따라 다음에 조치를 취해야 하는 에이전트를 선택합니다.

Magentic 관리자는 공유 컨텍스트를 유지하고, 진행률을 추적하고, 워크플로를 실시간으로 조정합니다. 이를 통해 시스템은 복잡한 문제를 분석하고, 하위 작업을 위임하고, 에이전트 협업을 통해 솔루션을 반복적으로 구체화할 수 있습니다. 오케스트레이션은 솔루션 경로를 미리 알 수 없으며 여러 라운드의 추론, 연구 및 계산이 필요할 수 있는 시나리오에 특히 적합합니다.

자기 오케스트레이션

팁 (조언)

Magentic 오케스트레이션은 그룹 채팅 오케스트레이션 패턴과 동일한 아키텍처를 가지며, 계획을 사용하여 에이전트 협업을 조정하는 매우 강력한 관리자가 있습니다. 시나리오에서 복잡한 계획 없이 더 간단한 조정이 필요한 경우 그룹 채팅 패턴을 대신 사용하는 것이 좋습니다.

비고

Magentic-One 논문에서 4개의 고도로 특수화된 에이전트는 매우 구체적인 작업 집합을 해결하도록 설계되었습니다. 에이전트 프레임워크의 Magentic 오케스트레이션에서 특정 애플리케이션 요구 사항에 맞게 고유한 특수 에이전트를 정의할 수 있습니다. 그러나 Magentic 오케스트레이션이 원래 Magentic-One 디자인 외부에서 얼마나 잘 수행되는지는 테스트되지 않습니다.

학습 내용

  • 여러 특수 에이전트를 조정하도록 Magentic 관리자를 설정하는 방법
  • 를 사용하여 스트리밍 이벤트를 처리하는 방법 WorkflowEvent
  • 휴먼 인 더 루프 계획 검토를 구현하는 방법
  • 복잡한 작업을 통해 에이전트 공동 작업 및 진행률을 추적하는 방법

특수 에이전트 정의

Magentic 오케스트레이션에서는 관리자가 작업 요구 사항에 따라 동적으로 선택할 수 있는 특수 에이전트를 정의합니다.

#pragma warning disable MAAIW001  // Magentic types are experimental
#pragma warning disable OPENAI001 // HostedCodeInterpreterTool is experimental

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Specialized.Magentic;
using Microsoft.Extensions.AI;

string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5.4-mini";

AIProjectClient projectClient = new(new Uri(endpoint), new DefaultAzureCredential());

AIAgent researcherAgent = projectClient.AsAIAgent(
    deploymentName,
    name: "ResearcherAgent",
    description: "Specialist in research and information gathering.",
    instructions: "You are a researcher. Find relevant information without doing additional computation or quantitative analysis.");

AIAgent coderAgent = projectClient.AsAIAgent(
    deploymentName,
    name: "CoderAgent",
    description: "A helpful assistant that writes and executes code to analyze data.",
    instructions: "You solve quantitative questions by writing and running code. Show the analysis and the computation process clearly.",
    tools: [new HostedCodeInterpreterTool()]);

AIAgent managerAgent = projectClient.AsAIAgent(
    deploymentName,
    name: "MagenticManager",
    description: "Orchestrator that coordinates the research and coding workflow.",
    instructions: "You coordinate the team to complete complex tasks efficiently.");
import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

client = FoundryChatClient(
    project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
    model=os.environ["FOUNDRY_MODEL"],
    credential=AzureCliCredential(),
)

researcher_agent = Agent(
    name="ResearcherAgent",
    description="Specialist in research and information gathering",
    instructions=(
        "You are a Researcher. You find information without additional computation or quantitative analysis."
    ),
    client=client,
)

coder_agent = Agent(
    name="CoderAgent",
    description="A helpful assistant that writes and executes code to process and analyze data.",
    instructions="You solve questions using code. Please provide detailed analysis and computation process.",
    client=client,
    tools=client.get_code_interpreter_tool(),
)

# Create a manager agent for orchestration
manager_agent = Agent(
    name="MagenticManager",
    description="Orchestrator that coordinates the research and coding workflow",
    instructions="You coordinate a team to complete complex tasks efficiently.",
    client=client,
)

마그네틱 워크플로 구축

Magentic 워크플로 작성기를 사용하여 관리자 및 참가자 집합을 사용하여 워크플로를 구성합니다. 또한 빌더는 내부 루프 제한값(최대 조정 횟수, 재계획 전에 허용되는 최대 연속 정체 횟수, 최대 계획 재설정 횟수)과 사람 개입형 계획 검토를 위한 플래그도 제공합니다.

Workflow workflow = new MagenticWorkflowBuilder(managerAgent)
    .AddParticipants([researcherAgent, coderAgent])
    .WithName("Magentic Orchestration Workflow")
    .WithDescription("Coordinates a researcher and coder to solve a complex analytical task.")
    .RequirePlanSignoff(false)
    .WithMaxRounds(10)
    .WithMaxStalls(3)
    .WithMaxResets(2)
    .Build();
from agent_framework.orchestrations import MagenticBuilder

workflow = MagenticBuilder(
    participants=[researcher_agent, coder_agent],
    intermediate_output_from=[researcher_agent, coder_agent],
    manager_agent=manager_agent,
    max_round_count=10,
    max_stall_count=3,
    max_reset_count=2,
).build()

팁 (조언)

표준 관리자는 원래 용지에서 가져온 고정 프롬프트와 함께 Magentic-One 디자인을 기반으로 구현됩니다. 생성자 매개 변수를 통해 사용자 고유의 프롬프트를 전달하여 관리자의 동작을 MagenticBuilder 사용자 지정할 수 있습니다. 관리자를 추가로 사용자 지정하려면 클래스를 서브클래싱하여 사용자 고유의 관리자를 MagenticManagerBase 구현할 수도 있습니다.

중간 출력

비고

이 섹션은 현재 Python 피벗에만 적용됩니다.

intermediate_output_from=[...]MagenticBuilder을 전달하면 특정 참가자가 중간 출력 소스로 지정됩니다. 해당 yield_output 호출은 "intermediate" 이벤트를 발생시키는 반면, 관리자의 최종 합성 응답은 여전히 "output" (터미널) 이벤트로 유지됩니다. 이 매개 변수(기본값)가 없으면 관리자의 터미널 AgentResponse 표면만 표시됩니다.

이는 다음 때문에 Magentic 워크플로에 특히 유용합니다.

  • 작업은 종종 여러 차례의 에이전트 협업으로 장시간 동안 수행됩니다.
  • 워크플로가 스트리밍 모드에서 진행됨에 따라 각 에이전트의 기여도를 실시간으로 표시할 수 있습니다.
  • 워크플로의 중간 추론 단계에 대한 가시성을 제공합니다.

이벤트 스트리밍을 사용하여 워크플로 실행

복잡한 작업을 실행하고 스트리밍 출력 및 오케스트레이션 업데이트에 대한 이벤트를 처리합니다. 터미널 워크플로 출력에는 관리자의 합성된 최종 답변이 포함됩니다.

const string TaskPrompt =
    "I am preparing a report on the energy efficiency of different machine learning model architectures. " +
    "Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 " +
    "on standard datasets (for example, ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). " +
    "Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 " +
    "VM for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model " +
    "per task type (image classification, text classification, and text generation).";

await using StreamingRun run = await InProcessExecution.RunStreamingAsync(
    workflow,
    new List<ChatMessage> { new(ChatRole.User, TaskPrompt) });

await run.TrySendMessageAsync(new TurnToken(emitEvents: true));

string? lastResponseId = null;
WorkflowOutputEvent? finalOutput = null;

await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
    switch (workflowEvent)
    {
        case AgentResponseUpdateEvent updateEvent:
            // Stream per-participant deltas. Group by ResponseId / MessageId / ExecutorId so
            // each new contiguous response prints its executor header once.
            string responseId = updateEvent.Update.ResponseId
                ?? updateEvent.Update.MessageId
                ?? updateEvent.ExecutorId;
            if (!string.Equals(responseId, lastResponseId, StringComparison.Ordinal))
            {
                if (lastResponseId is not null)
                {
                    Console.WriteLine();
                }
                Console.Write($"- {updateEvent.ExecutorId}: ");
                lastResponseId = responseId;
            }
            Console.Write(updateEvent.Update.Text);
            break;

        case MagenticPlanCreatedEvent planCreated:
            Console.WriteLine($"\n[Magentic Initial Plan]\n{planCreated.FullTaskLedger.Text}");
            break;

        case MagenticReplannedEvent replanned:
            Console.WriteLine($"\n[Magentic Replanned]\n{replanned.FullTaskLedger.Text}");
            break;

        case MagenticProgressLedgerUpdatedEvent progressUpdated:
            MagenticProgressLedger ledger = progressUpdated.ProgressLedger;
            Console.WriteLine(
                $"\n[Magentic Progress Ledger] satisfied={ledger.IsRequestSatisfied}, " +
                $"inLoop={ledger.IsInLoop}, progressing={ledger.IsProgressBeingMade}, " +
                $"nextSpeaker={ledger.NextSpeaker}, instruction={ledger.InstructionOrQuestion}");
            break;

        case WorkflowOutputEvent outputEvent when outputEvent.Is<List<ChatMessage>>():
            finalOutput = outputEvent;
            break;

        case WorkflowErrorEvent workflowError:
            Console.Error.WriteLine(workflowError.Exception?.ToString() ?? "Unknown workflow error.");
            break;

        case ExecutorFailedEvent executorFailed:
            Console.Error.WriteLine(
                $"Executor '{executorFailed.ExecutorId}' failed: " +
                (executorFailed.Data?.ToString() ?? "unknown error"));
            break;
    }
}

if (finalOutput?.As<List<ChatMessage>>() is { } transcript)
{
    Console.WriteLine("\n\n=== Final Conversation Transcript ===\n");
    foreach (ChatMessage message in transcript)
    {
        Console.WriteLine($"{message.AuthorName ?? message.Role.ToString()}: {message.Text}");
    }
}
import json
import asyncio
from typing import cast

from agent_framework import (
    AgentResponseUpdate,
    Message,
    WorkflowEvent,
)
from agent_framework.orchestrations import MagenticProgressLedger

task = (
    "I am preparing a report on the energy efficiency of different machine learning model architectures. "
    "Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 "
    "on standard datasets (for example, ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). "
    "Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 "
    "VM for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model "
    "per task type (image classification, text classification, and text generation)."
)

# Keep track of the last executor to format output nicely in streaming mode
last_message_id: str | None = None
stream = workflow.run(task, stream=True)
async for event in stream:
    if event.type in ("intermediate", "output") and isinstance(event.data, AgentResponseUpdate):
        message_id = event.data.message_id
        if message_id != last_message_id:
            if last_message_id is not None:
                print("\n")
            print(f"- {event.executor_id}:", end=" ", flush=True)
            last_message_id = message_id
        print(event.data, end="", flush=True)

    elif event.type == "magentic_orchestrator":
        print(f"\n[Magentic Orchestrator Event] Type: {event.data.event_type.name}")
        if isinstance(event.data.content, Message):
            print(f"Please review the plan:\n{event.data.content.text}")
        elif isinstance(event.data.content, MagenticProgressLedger):
            print(f"Please review progress ledger:\n{json.dumps(event.data.content.to_dict(), indent=2)}")
        else:
            print(f"Unknown data type in MagenticOrchestratorEvent: {type(event.data.content)}")

        # Block to allow user to read the plan/progress before continuing
        # Note: this is for demonstration only and is not the recommended way to handle human interaction.
        # Please refer to `with_plan_review` for proper human interaction during planning phases.
        await asyncio.get_event_loop().run_in_executor(None, input, "Press Enter to continue...")

result = await stream.get_final_response()
if outputs := result.get_outputs():
    print(outputs[-1])

Magentic은 계획 및 진행의 주요 이정표를 나타내는 세 가지 오케스트레이터 이벤트를 보여줍니다.

  • 초기 계획 생성 - 관리자가 초기 작업 계획을 생성했습니다.
  • 재계획됨 — 정체 감지로 인해 또는 사람이 계획 검토를 통해 계획을 수정하여 새 계획이 생성되었습니다.
  • 진행 원장 업데이트됨 — 조정 라운드마다 한 번 생성되며, 현재 진행 원장(요청이 충족되었는지 여부, 팀이 루프에 빠져 있는지 여부, 진전이 이루어지고 있는지 여부, 다음 화자, 그리고 해당 화자에게 보낼 지시)을 담습니다.

Python에서는 이들이 단일 MagenticOrchestratorEvent 내부에 담기며, 그 event_type 열거형은 PLAN_CREATED, REPLANNED, PROGRESS_LEDGER_UPDATED를 구분합니다. .NET에서는 이들이 MagenticPlanCreatedEvent, MagenticReplannedEvent, MagenticProgressLedgerUpdatedEvent의 세 가지 별개의 형식으로 생성되며, 이 모두는 MagenticOrchestratorEvent에서 파생됩니다.

고급: 휴먼 인 더 루프 계획 검토

사용자가 실행 전에 관리자의 제안된 계획을 검토하고 승인할 수 있도록 HITL(휴먼 인 더 루프)을 사용하도록 설정합니다. 이는 계획이 사용자 기대 및 요구 사항에 맞게 조정되도록 하는 데 유용합니다.

계획 검토를 위한 두 가지 옵션이 있습니다.

  1. 수정: 사용자는 계획을 수정하기 위한 피드백을 제공하여 관리자가 피드백에 따라 다시 계획하도록 트리거합니다.
  2. 승인: 사용자가 계획을 수정 없이 승인하여 워크플로가 계속 진행되도록 합니다.

Magentic 워크플로를 빌드할 때 계획 검토를 사용하도록 설정합니다. 기본값은 언어마다 다릅니다. Python 계획 검토는 기본적으로 off이며(enable_plan_review=False) 명시적으로 옵트인합니다. .NET 계획 검토는 기본적으로 on(RequirePlanSignoff 기본값은 true)이며, 이 페이지의 앞부분에 나오는 기본 예제는 상호 작용 없이 엔드 투 엔드를 실행할 수 있도록 옵트아웃되었습니다. 아래 코드에서는 결과 검토 요청을 옵트인하고 처리하는 방법을 보여 줍니다.

플랜 검토 일시 중지는 MagenticPlanReviewRequest 데이터와 함께 워크플로의 요청/응답 메커니즘을 통해 표시됩니다. 이벤트 스트림에서 이를 처리하고 사용자가 계획을 승인하거나 수정한 후 워크플로 MagenticPlanReviewResponse 를 다시 시작합니다.

팁 (조언)

요청 및 응답 가이드에서 요청 및 응답 에 대해 자세히 알아봅니다.

Workflow workflow = new MagenticWorkflowBuilder(managerAgent)
    .AddParticipants([researcherAgent, coderAgent])
    .RequirePlanSignoff(true)
    .WithMaxRounds(10)
    .WithMaxStalls(1)
    .WithMaxResets(2)
    .Build();

CheckpointManager checkpointManager = CheckpointManager.CreateInMemory();
InProcessExecutionEnvironment environment = ExecutionEnvironment.InProcess_Lockstep
    .ToWorkflowExecutionEnvironment()
    .WithCheckpointing(checkpointManager);

await using StreamingRun run = await environment.OpenStreamingAsync(workflow);
await run.TrySendMessageAsync(new List<ChatMessage> { new(ChatRole.User, TaskPrompt) });
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));

ExternalRequest? pendingRequest = null;
CheckpointInfo? lastCheckpoint = null;
WorkflowOutputEvent? finalOutput = null;

async Task<WorkflowOutputEvent?> DrainAsync(StreamingRun activeRun)
{
    WorkflowOutputEvent? output = null;
    await foreach (WorkflowEvent evt in activeRun.WatchStreamAsync(blockOnPendingRequest: false))
    {
        switch (evt)
        {
            case AgentResponseUpdateEvent updateEvent:
                Console.Write(updateEvent.Update.Text);
                break;
            case RequestInfoEvent requestInfo
                when requestInfo.Request.Data.As<MagenticPlanReviewRequest>() is not null:
                pendingRequest = requestInfo.Request;
                break;
            case SuperStepCompletedEvent stepCompleted:
                lastCheckpoint = stepCompleted.CompletionInfo?.Checkpoint ?? lastCheckpoint;
                break;
            case WorkflowOutputEvent outputEvent when outputEvent.Is<List<ChatMessage>>():
                output = outputEvent;
                break;
        }
    }
    return output;
}

finalOutput = await DrainAsync(run);

// Loop until the workflow finishes or the user accepts a plan that runs to completion.
while (finalOutput is null && pendingRequest is not null)
{
    MagenticPlanReviewRequest reviewRequest = pendingRequest.Data.As<MagenticPlanReviewRequest>()!;

    Console.WriteLine("\n\n[Magentic Plan Review Request]");
    if (reviewRequest.CurrentProgress is { } progress)
    {
        Console.WriteLine(
            $"Current progress: satisfied={progress.IsRequestSatisfied}, " +
            $"inLoop={progress.IsInLoop}, progressing={progress.IsProgressBeingMade}");
    }
    if (reviewRequest.IsStalled)
    {
        Console.WriteLine("(Replan triggered by stall detection.)");
    }
    Console.WriteLine($"Proposed plan:\n{reviewRequest.Plan.Text}\n");
    Console.Write("Press Enter to approve, or type feedback to request a revision: ");

    string reply = Console.ReadLine() ?? string.Empty;
    MagenticPlanReviewResponse reviewResponse = string.IsNullOrWhiteSpace(reply)
        ? reviewRequest.Approve()
        : reviewRequest.Revise(reply);

    ExternalResponse response = pendingRequest.CreateResponse(reviewResponse);
    pendingRequest = null;

    await using StreamingRun resumed = await environment.ResumeStreamingAsync(workflow, lastCheckpoint!);
    await resumed.SendResponseAsync(response);
    finalOutput = await DrainAsync(resumed);
}

if (finalOutput?.As<List<ChatMessage>>() is { } transcript)
{
    Console.WriteLine("\n\n=== Final Conversation Transcript ===\n");
    foreach (ChatMessage message in transcript)
    {
        Console.WriteLine($"{message.AuthorName ?? message.Role.ToString()}: {message.Text}");
    }
}
import json
import asyncio
from typing import cast

from agent_framework import (
    AgentResponseUpdate,
    Agent,
    Message,
    WorkflowEvent,
)
from agent_framework.orchestrations import (
    MagenticBuilder,
    MagenticPlanReviewRequest,
    MagenticPlanReviewResponse,
)

workflow = MagenticBuilder(
    participants=[researcher_agent, coder_agent],
    intermediate_output_from=[researcher_agent, coder_agent],
    enable_plan_review=True,
    manager_agent=manager_agent,
    max_round_count=10,
    max_stall_count=1,
    max_reset_count=2,
).build()

pending_request: WorkflowEvent | None = None
pending_responses: dict[str, MagenticPlanReviewResponse] | None = None
final_response: object | None = None

while not final_response:
    if pending_responses is not None:
        stream = workflow.run(stream=True, responses=pending_responses)
    else:
        stream = workflow.run(task, stream=True)

    last_message_id: str | None = None
    async for event in stream:
        if event.type in ("intermediate", "output") and isinstance(event.data, AgentResponseUpdate):
            message_id = event.data.message_id
            if message_id != last_message_id:
                if last_message_id is not None:
                    print("\n")
                print(f"- {event.executor_id}:", end=" ", flush=True)
                last_message_id = message_id
            print(event.data, end="", flush=True)

        elif event.type == "request_info" and event.request_type is MagenticPlanReviewRequest:
            pending_request = event

    result = await stream.get_final_response()
    if outputs := result.get_outputs():
        final_response = outputs[-1]

    pending_responses = None

    # Handle plan review request if any
    if pending_request is not None:
        event_data = cast(MagenticPlanReviewRequest, pending_request.data)

        print("\n\n[Magentic Plan Review Request]")
        if event_data.current_progress is not None:
            print("Current Progress Ledger:")
            print(json.dumps(event_data.current_progress.to_dict(), indent=2))
            print()
        print(f"Proposed Plan:\n{event_data.plan.text}\n")
        print("Please provide your feedback (press Enter to approve):")

        reply = await asyncio.get_event_loop().run_in_executor(None, input, "> ")
        if reply.strip() == "":
            print("Plan approved.\n")
            pending_responses = {pending_request.request_id: event_data.approve()}
        else:
            print("Plan revised by human.\n")
            pending_responses = {pending_request.request_id: event_data.revise(reply)}
        pending_request = None

MagenticPlanReviewRequest는 제안된 계획, 현재 진행 상황 원장(null / None는 초기 검토 시 사용되며 정체 감지로 트리거된 재계획 시 채워짐), 그리고 재계획이 정체 감지에 의해 트리거되었는지를 나타내는 플래그를 포함합니다. 응답은 계획을 있는 그대로 수락하려면 approve()를 호출하고, 관리자에게 다시 계획을 세우도록 요청하려면 피드백과 함께 revise(...)를 호출하여 작성합니다.

주요 개념

  • 동적 조정: Magentic 관리자는 진화하는 컨텍스트에 따라 다음에 작동해야 하는 에이전트를 동적으로 선택합니다.
  • 터미널 출력: 터미널 워크플로 출력은 관리자의 합성된 최종 답변(Python AgentResponse, .NET WorkflowOutputEvent 페이로드가 있는 List<ChatMessage>)을 전달합니다.
  • Orchestrator 이벤트: 계획 생성, 재계획, 진행 원장이 업데이트된 마일스톤은 MagenticOrchestratorEvent를 통해 노출됩니다(Python에서는 event_type 열거형을 포함한 단일 이벤트로, .NET에서는 세 가지 파생 형식으로). 참가자별 스트리밍 델타는 프레임워크의 표준 에이전트 응답 업데이트 이벤트를 통해 전달됩니다.
  • 반복적 구체화: 시스템은 복잡한 문제를 분석하고 여러 라운드를 통해 반복적으로 솔루션을 구체화할 수 있습니다.
  • 진행 상황 추적 및 정체 감지: 진행 상황 원장은 요청이 충족되었는지, 팀이 같은 과정을 반복하고 있는지, 그리고 실제로 진전이 이루어지고 있는지를 추적합니다. 진행되지 않는 연속 라운드는 중단 카운터를 증가시키고 구성된 최대값을 초과하면 자동 재설정 및 다시 계획이 트리거됩니다.
  • 유연한 협업: 에이전트는 관리자가 결정한 순서에 따라 여러 번 호출할 수 있습니다.
  • 인간 감독: MagenticPlanReviewRequest / MagenticPlanReviewResponse를 통한 선택적 human-in-the-loop 계획 검토.
  • 터미디어 출력(지금은 Python만 해당): yield_output 호출이 관리자의 터미널 출력과 함께 "intermediate" 이벤트로 표시되어야 하는 참가자를 지정합니다.

워크플로 실행 흐름

Magentic 오케스트레이션은 다음 실행 패턴을 따릅니다.

  1. 계획 단계: 관리자는 작업을 분석하고 초기 계획을 만듭니다.
  2. 선택적 계획 검토: 사용하도록 설정된 경우 사용자는 계획을 검토하고 승인/수정할 수 있습니다.
  3. 에이전트 선택: 관리자는 각 하위 작업에 가장 적합한 에이전트를 선택합니다.
  4. 실행: 선택한 에이전트가 작업의 해당 부분을 실행합니다.
  5. 진행률 평가: 관리자가 진행률을 평가하고 계획을 업데이트합니다.
  6. 중단 감지: 진행이 중단되면 선택적 사용자 검토 프로세스를 포함하여 자동으로 다시 계획합니다.
  7. 반복: 작업이 완료되거나 제한에 도달할 때까지 3-6단계가 반복됩니다.
  8. 최종 합성: 관리자는 모든 에이전트 출력을 최종 결과로 합성합니다.

완성된 예시

에이전트 프레임워크 샘플 리포지토리의 전체 샘플을 참조하세요.

에이전트 프레임워크 샘플 리포지토리의 전체 샘플을 참조하세요.

다음 단계: