تنسيقات مهام سير عمل Microsoft Agent Framework - تسلسلي

في التنسيق التسلسلي، يتم تنظيم الوكلاء في البنية الأساسية لبرنامج ربط العمليات التجارية. يعالج كل عامل المهمة بدوره، ويمرر إخراجها إلى العامل التالي في التسلسل. يعد هذا مثاليا لسير العمل حيث تعتمد كل خطوة على الخطوة السابقة، مثل مراجعة المستندات أو مسارات معالجة البيانات أو المنطق متعدد المراحل.

التزامن التسلسلي

Important

بشكل افتراضي، يستهلك كل عامل في التسلسل المحادثة الكاملة للعامل السابق — كل من رسائل الإدخال المقدمة إلى العامل السابق ورسائل الاستجابة الخاصة به. يمكنك تكوين العوامل لاستهلاك رسائل استجابة العامل السابق فقط بدلا من ذلك. راجع التحكم في السياق بين العوامل للحصول على التفاصيل.

ما ستتعلمه

  • كيفية إنشاء مسار تسلسلي من العوامل
  • كيفية تسلسل العوامل حيث يعتمد كل منها على الإخراج السابق
  • كيفية إضافة الموافقة البشرية في التكرار الحلقي لاستدعاءات الأدوات الحساسة
  • كيفية خلط العوامل مع المنفذين المخصصين للمهام المتخصصة
  • كيفية تعقب تدفق المحادثة من خلال المسار

تعريف وكلاءك

في التزامن التسلسلي، يتم تنظيم الوكلاء في مسار حيث يعالج كل عامل المهمة بدوره، ويمرر الإخراج إلى العامل التالي في التسلسل.

إعداد عميل Azure OpenAI

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;

// 1) Set up the Azure OpenAI client
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ??
    throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var client = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .GetProjectOpenAIClient()
    .GetProjectResponsesClient()
    .AsIChatClient(deploymentName);

تحذير

DefaultAzureCredential مناسب للتنمية ولكنه يتطلب دراسة متأنية في الإنتاج. في الإنتاج، ضع في اعتبارك استخدام بيانات اعتماد محددة (على سبيل المثال، ManagedIdentityCredential) لتجنب مشكلات زمن الانتقال، وبحث بيانات الاعتماد غير المقصودة، والمخاطر الأمنية المحتملة من الآليات الاحتياطية.

إنشاء وكلاء متخصصين سيعملون في تسلسل:

// 2) Helper method to create translation agents
static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) =>
    new(chatClient,
        $"You are a translation assistant who only responds in {targetLanguage}. Respond to any " +
        $"input by outputting the name of the input language and then translating the input to {targetLanguage}.");

// Create translation agents for sequential processing
var translationAgents = (from lang in (string[])["French", "Spanish", "English"]
                         select GetTranslationAgent(lang, client));

إعداد التنسيق التسلسلي

إنشاء سير العمل باستخدام AgentWorkflowBuilder:

// 3) Build sequential workflow
var workflow = AgentWorkflowBuilder.BuildSequential(translationAgents);

تشغيل سير العمل التسلسلي

تنفيذ سير العمل ومعالجة الأحداث:

// 4) Run the workflow
var messages = new List<ChatMessage> { new(ChatRole.User, "Hello, world!") };

await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, messages);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));

string? lastExecutorId = null;
List<ChatMessage> result = [];
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
    if (evt is AgentResponseUpdateEvent e)
    {
        if (e.ExecutorId != lastExecutorId)
        {
            lastExecutorId = e.ExecutorId;
            Console.WriteLine();
            Console.Write($"{e.ExecutorId}: ");
        }

        Console.Write(e.Update.Text);
    }
    else if (evt is WorkflowOutputEvent outputEvt)
    {
        result = outputEvt.As<List<ChatMessage>>()!;
        break;
    }
}

// Display final result
Console.WriteLine();
foreach (var message in result)
{
    Console.WriteLine($"{message.Role}: {message.Text}");
}

إخراج العينة

French_Translation: User: Hello, world!
French_Translation: Assistant: English detected. Bonjour, le monde !
Spanish_Translation: Assistant: French detected. ¡Hola, mundo!
English_Translation: Assistant: Spanish detected. Hello, world!

التزامن التسلسلي مع Human-in-the-Loop

تدعم التزامنات المتسلسلة التفاعلات بين البشر في الحلقة من خلال الموافقة على الأداة. عندما يستخدم العاملون أدوات ملتفة مع ApprovalRequiredAIFunction، يتوقف سير العمل مؤقتا ويبعث منها RequestInfoEvent ما يحتوي على ToolApprovalRequestContent. يمكن للأنظمة الخارجية (مثل عامل التشغيل البشري) فحص استدعاء الأداة والموافقة عليها أو رفضها، ويستأنف سير العمل وفقا لذلك.

التزامن التسلسلي مع Human-in-the-Loop

Tip

لمزيد من التفاصيل حول نموذج الطلب والاستجابة، راجع Human-in-the-Loop.

تعريف العوامل باستخدام أدوات Approval-Required

إنشاء عوامل حيث يتم التفاف الأدوات الحساسة مع ApprovalRequiredAIFunction:

ChatClientAgent deployAgent = new(
    client,
    "You are a DevOps engineer. Check staging status first, then deploy to production.",
    "DeployAgent",
    "Handles deployments",
    [
        AIFunctionFactory.Create(CheckStagingStatus),
        new ApprovalRequiredAIFunction(AIFunctionFactory.Create(DeployToProduction))
    ]);

ChatClientAgent verifyAgent = new(
    client,
    "You are a QA engineer. Verify that the deployment was successful and summarize the results.",
    "VerifyAgent",
    "Verifies deployments");

الإنشاء والتشغيل باستخدام معالجة الموافقة

إنشاء سير العمل التسلسلي بشكل طبيعي. تتم معالجة تدفق الموافقة من خلال دفق الحدث:

var workflow = AgentWorkflowBuilder.BuildSequential([deployAgent, verifyAgent]);

await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
    if (evt is RequestInfoEvent e &&
        e.Request.TryGetDataAs(out ToolApprovalRequestContent? approvalRequest))
    {
        await run.SendResponseAsync(
            e.Request.CreateResponse(approvalRequest.CreateResponse(approved: true)));
    }
}

Note

AgentWorkflowBuilder.BuildSequential() يدعم الموافقة على الأداة خارج الصندوق - لا يلزم تكوين إضافي. عندما يستدعي عامل أداة مغلفة ب ApprovalRequiredAIFunction، يتوقف سير العمل مؤقتا تلقائيا ويبعث .RequestInfoEvent

Tip

للحصول على مثال كامل قابل للتشغيل لتدفق الموافقة هذا، راجع العينةGroupChatToolApproval. ينطبق نفس RequestInfoEvent نمط المعالجة على التنسيقات الأخرى.

ما بعد الموافقة على الأداة: ملاحظات تفاعلية

تتيح الموافقة على الأداة للإنسان قبول استدعاء أداة معين أو رفضه، ولكن لا يتضمن التنسيق التسلسلي خطوة مضمنة للإيقاف المؤقت لتعليقات المستخدم الحرة بين الوكلاء، ولا يمكنه إعادة التحكم إلى وكيل سابق. عندما يحتاج العامل إلى الطلب من المستخدم بشكل تفاعلي الحصول على مزيد من المعلومات والتكرار قبل المتابعة؛ على سبيل المثال، جمع تفاصيل الحجز قبل أن تستدعي أداة حجز؛ استخدم إحدى الطرق التالية بدلا من ذلك:

  • يكون تزامن التسليم تفاعليا بشكل افتراضي: عندما يستجيب العامل دون تسليمه، يعود عنصر التحكم إلى المستخدم للإدخال التالي، مما يتيح متعددة الأدوار ذهابا وإيابا داخل التنسيق. تقييد كل عامل إلى هدف تسليم واحد لتقريب تدفق تسلسلي لا يزال يتوقف مؤقتا لإدخال المستخدم.
  • يتيح لك سير العمل المخصص المضمن مع WorkflowBuilder و RequestPort إرسال طلب مكتوب إلى المستخدم في أي وقت وتوجيه الاستجابة مرة أخرى إلى المنفذ، والذي يمكنك وضعه قبل أو بعد الوكلاء في البنية الأساسية لبرنامج ربط العمليات التجارية.

المفاهيم الأساسية

  • المعالجة التسلسلية: يعالج كل عامل إخراج العامل السابق بالترتيب
  • AgentWorkflowBuilder.BuildSequential(): إنشاء سير عمل البنية الأساسية لبرنامج ربط العمليات التجارية من مجموعة من العوامل
  • ChatClientAgent: يمثل وكيلا مدعوما من عميل دردشة مع إرشادات محددة
  • InProcessExecution.RunStreamingAsync(): تشغيل سير العمل وإرجاع StreamingRun لتدفق الأحداث في الوقت الحقيقي
  • معالجة الأحداث: مراقبة تقدم AgentResponseUpdateEvent العامل والإكمال من خلال WorkflowOutputEvent
  • الموافقة على الأداة: التفاف الأدوات الحساسة مع ApprovalRequiredAIFunction لطلب موافقة الإنسان قبل التنفيذ
  • RequestInfoEvent: يتم إصداره عندما تتطلب الأداة الموافقة؛ يحتوي على ToolApprovalRequestContent تفاصيل استدعاء الأداة
  • Interactive HITL: يغطي التنسيق التسلسلي الموافقة على الأدوات؛ للتفاعلية ذهابا وإيابا حيث يقوم العامل بجمع مزيد من المعلومات من المستخدم، استخدم تنسيق التسليم أو سير عمل مخصص RequestPort

في التنسيق التسلسلي، يعالج كل عامل المهمة بدوره، مع تدفق الإخراج من واحد إلى آخر. ابدأ بتعريف العوامل لعملية من مرحلتين:

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

# 1) Create agents using FoundryChatClient
chat_client = FoundryChatClient(
    project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
    model=os.environ["FOUNDRY_MODEL"],
    credential=AzureCliCredential(),
)

writer = chat_client.as_agent(
    instructions=(
        "You are a concise copywriter. Provide a single, punchy marketing sentence based on the prompt."
    ),
    name="writer",
)

reviewer = chat_client.as_agent(
    instructions=(
        "You are a thoughtful reviewer. Give brief feedback on the previous assistant message."
    ),
    name="reviewer",
)

إعداد التنسيق التسلسلي

SequentialBuilder تنشئ الفئة البنية الأساسية لبرنامج ربط العمليات التجارية حيث يقوم الوكلاء بمعالجة المهام بالترتيب. يرى كل عامل محفوظات المحادثات الكاملة ويضيف استجابته:

from agent_framework.orchestrations import SequentialBuilder

# 2) Build sequential workflow: writer -> reviewer
workflow = SequentialBuilder(participants=[writer, reviewer]).build()

تشغيل سير العمل التسلسلي

تنفيذ سير العمل وجمع الإخراج النهائي. إخراج المحطة الطرفية هو يحتوي AgentResponse على رسائل استجابة العامل الأخير:

from agent_framework import AgentResponse

# 3) Run and print the last agent's response
events = await workflow.run("Write a tagline for a budget-friendly eBike.")
outputs = events.get_outputs()

if outputs:
    print("===== Final Response =====")
    final: AgentResponse = outputs[0]
    for msg in final.messages:
        name = msg.author_name or "assistant"
        print(f"[{name}]\n{msg.text}")

إخراج العينة

===== Final Response =====
[reviewer]
This tagline clearly communicates affordability and the benefit of extended travel, making it
appealing to budget-conscious consumers. It has a friendly and motivating tone, though it could
be slightly shorter for more punch. Overall, a strong and effective suggestion!

خيارات متقدمة: خلط العوامل مع المنفذين المخصصين

يدعم التنسيق التسلسلي خلط العوامل مع المنفذين المخصصين للمعالجة المتخصصة. هذا مفيد عندما تحتاج إلى منطق مخصص لا يتطلب LLM:

تعريف منفذ مخصص

Note

عندما يتبع منفذ مخصص عامل في التسلسل، يتلقى AgentExecutorResponse معالجه (لأن العوامل ملتفة داخليا بواسطة AgentExecutor). استخدم agent_response.full_conversation للوصول إلى محفوظات المحادثات الكاملة. يجب على المنفذ المخصص المستخدم كمشارك أخير (فاصل) استدعاء ctx.yield_output(AgentResponse(...)) بحيث يصبح الإخراج الخاص به ناتج المحطة الطرفية لسير العمل.

from agent_framework import AgentExecutorResponse, AgentResponse, Executor, WorkflowContext, handler
from agent_framework import Message
from typing_extensions import Never

class Summarizer(Executor):
    """Terminator custom executor: consumes full conversation and yields a summary as the workflow's final answer."""

    @handler
    async def summarize(
        self,
        agent_response: AgentExecutorResponse,
        ctx: WorkflowContext[Never, AgentResponse]
    ) -> None:
        if not agent_response.full_conversation:
            await ctx.yield_output(AgentResponse(messages=[Message("assistant", ["No conversation to summarize."])]))
            return

        users = sum(1 for m in agent_response.full_conversation if m.role == "user")
        assistants = sum(1 for m in agent_response.full_conversation if m.role == "assistant")
        summary = Message("assistant", [f"Summary -> users:{users} assistants:{assistants}"])
        await ctx.yield_output(AgentResponse(messages=[summary]))

إنشاء سير عمل تسلسلي مختلط

# Create a content agent
content = chat_client.as_agent(
    instructions="Produce a concise paragraph answering the user's request.",
    name="content",
)

# Build sequential workflow: content -> summarizer
summarizer = Summarizer(id="summarizer")
workflow = SequentialBuilder(participants=[content, summarizer]).build()

عينة الإخراج مع المنفذ المخصص

===== Final Summary =====
Summary -> users:1 assistants:1

التحكم في السياق بين العوامل

بشكل افتراضي، يستهلك كل عامل في SequentialBuilder سير العمل المحادثة الكاملة للعامل السابق (رسائل الإدخال + الاستجابة). يقوم الإعداد chain_only_agent_responses=True بتكوين كافة العوامل في التسلسل لاستهلاك رسائل استجابة العامل السابق فقط بدلا من ذلك:

workflow = SequentialBuilder(
    participants=[writer, translator, reviewer],
    chain_only_agent_responses=True,
).build()

هذا مفيد لخطوط أنابيب الترجمة والتحسين التدريجي والسيناريوهات الأخرى حيث يجب أن يركز كل عامل فقط على تحويل إخراج العامل السابق دون التأثر بتحولات المحادثة السابقة.

للحصول على مثال كامل، راجع sequential_chain_only_agent_responses.py في مستودع إطار عمل العامل.

Tip

لمزيد من التحكم الدقيق في تدفق السياق — بما في ذلك وظائف التصفية المخصصة — راجع أوضاع السياق في مرجع عامل المنفذ.

مخرجات متوسطة

بشكل افتراضي، SequentialBuilder يعين المشارك الأخير كمصدر إخراج المحطة الطرفية (output_from). يظهر إخراج المشارك فقط كحدث "output" .

لعرض مخرجات المشاركين السابقين أيضا، مرر intermediate_output_from مع المشاركين الذين تريد تعيينهم كمصادر وسيطة. يؤدي هذا ضمنيا إلى تخفيض هؤلاء المشاركين من المجموعة النهائية الافتراضية — حيث يرسلون "intermediate" الأحداث بدلا من "output" الأحداث:

workflow = SequentialBuilder(
    participants=[writer, reviewer, editor],
    intermediate_output_from=[writer, reviewer],
).build()

يمكنك التعامل مع كل من "intermediate" الأحداث و "output" في الوقت الحقيقي في وضع الدفق:

from agent_framework import AgentResponseUpdate

# Track the last author to format streaming output.
last_author: str | None = None

async for event in workflow.run("Write a tagline for a budget-friendly eBike.", stream=True):
    if event.type in ("output", "intermediate") and isinstance(event.data, AgentResponseUpdate):
        update = event.data
        author = update.author_name
        if author != last_author:
            if last_author is not None:
                print()  # Newline between different authors
            label = "FINAL" if event.type == "output" else "intermediate"
            print(f"[{label}] {author}: {update.text}", end="", flush=True)
            last_author = author
        else:
            print(update.text, end="", flush=True)

التزامن التسلسلي مع Human-in-the-Loop

تدعم التنسيقات التسلسلية التفاعلات بين البشر في الحلقة بطريقتين: الموافقة على أداة للتحكم في استدعاءات الأدوات الحساسة، وطلب معلومات للإيقاف المؤقت بعد كل استجابة عامل لجمع الملاحظات.

التزامن التسلسلي مع Human-in-the-Loop

Tip

لمزيد من التفاصيل حول نموذج الطلب والاستجابة، راجع Human-in-the-Loop.

الموافقة على الأداة في مهام سير العمل المتسلسلة

استخدم @tool(approval_mode="always_require") لوضع علامة على الأدوات التي تحتاج إلى موافقة بشرية قبل التنفيذ. يتوقف سير العمل مؤقتا ويبعث حدثا request_info عندما يحاول العامل استدعاء الأداة.

@tool(approval_mode="always_require")
def execute_database_query(query: str) -> str:
    return f"Query executed successfully: {query}"


database_agent = Agent(
    client=chat_client,
    name="DatabaseAgent",
    instructions="You are a database assistant.",
    tools=[execute_database_query],
)

workflow = SequentialBuilder(participants=[database_agent]).build()

معالجة دفق الحدث ومعالجة طلبات الموافقة:

async def process_event_stream(stream):
    responses = {}
    async for event in stream:
        if event.type == "request_info" and event.data.type == "function_approval_request":
            responses[event.request_id] = event.data.to_function_approval_response(approved=True)
    return responses if responses else None

stream = workflow.run("Check the schema and update all pending orders", stream=True)

pending_responses = await process_event_stream(stream)
while pending_responses is not None:
    stream = workflow.run(stream=True, responses=pending_responses)
    pending_responses = await process_event_stream(stream)

Tip

للحصول على مثال كامل قابل للتشغيل، راجع sequential_builder_tool_approval.py. تعمل الموافقة على الأدوات مع SequentialBuilder دون أي تكوين إضافي للمنشئ.

معلومات الطلب لملاحظات العامل

استخدم .with_request_info() للإيقاف المؤقت بعد استجابة عوامل معينة، ما يسمح بالمدخلات الخارجية (مثل المراجعة البشرية) قبل بدء العامل التالي:

drafter = Agent(
    client=chat_client,
    name="drafter",
    instructions="You are a document drafter. Create a brief draft on the given topic.",
)

editor = Agent(
    client=chat_client,
    name="editor",
    instructions="You are an editor. Review and improve the draft. Incorporate any human feedback.",
)

finalizer = Agent(
    client=chat_client,
    name="finalizer",
    instructions="You are a finalizer. Create a polished final version.",
)

# Enable request info for the editor agent only
workflow = (
    SequentialBuilder(participants=[drafter, editor, finalizer])
    .with_request_info(agents=["editor"])
    .build()
)

async def process_event_stream(stream):
    responses = {}
    async for event in stream:
        if event.type == "request_info":
            responses[event.request_id] = AgentRequestInfoResponse.approve()
    return responses if responses else None

stream = workflow.run("Write a brief introduction to artificial intelligence.", stream=True)

pending_responses = await process_event_stream(stream)
while pending_responses is not None:
    stream = workflow.run(stream=True, responses=pending_responses)
    pending_responses = await process_event_stream(stream)

المفاهيم الأساسية

  • السياق المشترك: بشكل افتراضي، يستهلك كل عامل المحادثة الكاملة للعامل السابق، بما في ذلك رسائل الإدخال والاستجابة
  • التحكم في السياق: استخدم chain_only_agent_responses=True لتكوين العوامل لاستهلاك رسائل استجابة العامل السابق فقط
  • AgentResponse Output: الإخراج الطرفي لسير العمل هو الذي AgentResponse يحتوي على استجابة العامل الأخير (وليس المحادثة الكاملة)
  • Order Matters: ينفذ الوكلاء بدقة بالترتيب المحدد في participants القائمة
  • المشاركون المرنون: يمكنك خلط العوامل والمنفذين المخصصين بأي ترتيب
  • عقد المنهي المخصص: يجب على المنفذ المخصص المستخدم كآخر مشارك استدعاء ctx.yield_output(AgentResponse(...)) لإنتاج إخراج المحطة الطرفية
  • المخرجات المتوسطة: استخدم intermediate_output_from=[...] أو intermediate_output_from="all_other" لعرض تقدم المشارك كأحداث سير عمل وسيطة، وليس فقط إخراج المحطة الطرفية للمشارك الأخير
  • الموافقة على الأداة: استخدم @tool(approval_mode="always_require") للعمليات الحساسة التي تحتاج إلى مراجعة بشرية
  • معلومات الطلب: استخدم .with_request_info(agents=[...]) للإيقاف المؤقت بعد وكلاء معينين للحصول على ملاحظات خارجية

يمكن ل Go إنشاء مهام سير عمل الوكيل المتتالية باستخدام workflow/agentworkflow. NewSequentialWorkflowBuilder يستضيف كل عامل كمنفذ سير عمل، ويربطه بالترتيب، وينتج دفعة الرسالة النهائية كإخراج لسير العمل.

إعداد تكوين Foundry

endpoint := os.Getenv("FOUNDRY_PROJECT_ENDPOINT")
model := cmp.Or(os.Getenv("FOUNDRY_MODEL"), "gpt-4o-mini")

token, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
    return err
}

تحذير

azidentity.NewDefaultAzureCredential مناسب للتنمية ولكنه يتطلب دراسة متأنية في الإنتاج. في الإنتاج، ضع في اعتبارك استخدام بيانات اعتماد معينة، مثل azidentity.NewManagedIdentityCredential، لتجنب مشكلات زمن الانتقال، وبحث بيانات الاعتماد غير المقصودة، والمخاطر الأمنية المحتملة من الآليات الاحتياطية.

تعريف عوامل Go الخاصة بك

إنشاء وكلاء متخصصين سيعملون في تسلسل:

newTranslationAgent := func(language string) *agent.Agent {
    return foundryprovider.NewAgent(
        endpoint,
        token,
        foundryprovider.ModelDeployment(model),
        foundryprovider.AgentConfig{
            Instructions: fmt.Sprintf(
                "You are a translation assistant who only responds in %s. Respond to any input by outputting the name of the input language and then translating the input to %s.",
                language,
                language,
            ),
            Config: agent.Config{Name: language},
        },
    )
}

frenchAgent := newTranslationAgent("French")
spanishAgent := newTranslationAgent("Spanish")
englishAgent := newTranslationAgent("English")

إعداد التنسيق التسلسلي

wf, err := agentworkflow.NewSequentialWorkflowBuilder(
    frenchAgent,
    spanishAgent,
    englishAgent,
).
    WithName("translation-pipeline").
    Build()
if err != nil {
    return err
}

تشغيل سير العمل التسلسلي

تنفيذ سير العمل ومعالجة أحداث الإخراج:

run, err := inproc.Default.RunStreaming(ctx, wf, []*message.Message{message.NewText("Hello, world!")})
if err != nil {
    return err
}
defer run.Close(ctx)

emitEvents := true
if err := run.SendMessage(ctx, workflow.TurnToken{EmitEvents: &emitEvents}); err != nil {
    return err
}

lastExecutorID := ""
for evt, err := range run.WatchStream(ctx) {
    if err != nil {
        return err
    }
    switch e := evt.(type) {
    case workflow.OutputEvent:
        switch value := e.Output.(type) {
        case *agent.ResponseUpdate:
            if e.ExecutorID != lastExecutorID {
                lastExecutorID = e.ExecutorID
                fmt.Printf("\n%s: ", e.ExecutorID)
            }
            fmt.Print(value.String())
        case []*message.Message:
            fmt.Println("\n===== Final Response =====")
            for _, msg := range value {
                fmt.Printf("%s: %s\n", msg.Role, msg.String())
            }
        }
    case workflow.ErrorEvent:
        return e.Error
    case workflow.ExecutorFailedEvent:
        return fmt.Errorf("executor %q failed: %w", e.ExecutorID, e.Error)
    }
}

إخراج العينة

French: English detected. Bonjour, le monde !
Spanish: French detected. ¡Hola, mundo!
English: Spanish detected. Hello, world!

===== Final Response =====
assistant: Spanish detected. Hello, world!

التزامن التسلسلي مع Human-in-the-Loop

يمكن أن تتوقف مهام سير العمل المتسلسلة مؤقتا للموافقة على الأداة عندما يستخدم عامل مستضاف أداة مطلوبة للموافقة. التفاف الأداة مع tool.ApprovalRequiredFunc، ثم الاستماع إلى workflow.RequestInfoEvent والاستجابة ToolApprovalResponseContentباستخدام .

تعريف العوامل باستخدام أدوات Approval-Required

deployAgent := foundryprovider.NewAgent(
    endpoint,
    token,
    foundryprovider.ModelDeployment(model),
    foundryprovider.AgentConfig{
        Instructions: "You are a DevOps engineer. Check staging status first, then deploy to production.",
        Config: agent.Config{
            Name:  "DeployAgent",
            Tools: []tool.Tool{tool.ApprovalRequiredFunc(deployTool)},
        },
    },
)

verifyAgent := foundryprovider.NewAgent(
    endpoint,
    token,
    foundryprovider.ModelDeployment(model),
    foundryprovider.AgentConfig{
        Instructions: "You are a QA engineer. Verify that the deployment was successful and summarize the results.",
        Config:      agent.Config{Name: "VerifyAgent"},
    },
)

wf, err := agentworkflow.NewSequentialWorkflowBuilder(deployAgent, verifyAgent).
    WithName("deployment-pipeline").
    Build()
if err != nil {
    return err
}

الإنشاء والتشغيل باستخدام معالجة الموافقة

معالجة طلبات الموافقة في دفق الحدث:

for evt, err := range run.WatchStream(ctx) {
    if err != nil {
        return err
    }

    requestEvent, ok := evt.(workflow.RequestInfoEvent)
    if !ok {
        continue
    }

    requestContent, ok := requestEvent.Request.Data.As(reflect.TypeFor[*message.ToolApprovalRequestContent]())
    if !ok {
        continue
    }

    approvalRequest := requestContent.(*message.ToolApprovalRequestContent)
    response, err := requestEvent.Request.CreateResponse(approvalRequest.CreateResponse(true, "approved"))
    if err != nil {
        return err
    }

    if err := run.SendResponse(ctx, response); err != nil {
        return err
    }
}

خيارات متقدمة: خلط العوامل مع المنفذين المخصصين

بالنسبة للبنية الأساسية لبرنامج ربط العمليات التجارية المختلطة، يستضيف الوكلاء مع agentworkflow.New وربطهم بالمنفذين المخصصين باستخدام workflow.NewBuilder:

writer := agentworkflow.New(writerAgent, agentworkflow.Config{})

summarizer := workflow.NewExecutor("Summarizer", func(messages []*message.Message) string {
    return summarizeMessages(messages)
}).Bind()

wf, err := workflow.NewBuilder(writer).
    AddEdge(writer, summarizer).
    WithOutputFrom(summarizer).
    Build()
if err != nil {
    return err
}

التحكم في السياق بين العوامل

NewSequentialWorkflowBuilder يستخدم تكوين الوكيل المستضاف الافتراضي، حيث يتلقى كل عامل انتقال البيانات من الخادم رسائل الوكيل السابق الواردة ورسائل الاستجابة. لتسلسل استجابات الوكيل السابقة فقط، قم بتعيين WithChainOnlyAgentResponses(true):

wf, err := agentworkflow.NewSequentialWorkflowBuilder(frenchAgent, spanishAgent, englishAgent).
    WithChainOnlyAgentResponses(true).
    Build()
if err != nil {
    return err
}

مخرجات متوسطة

بشكل افتراضي، NewSequentialWorkflowBuilder يصدر إخراج كل مشارك كإخراج سير عمل متوسط ويصدر دفعة الرسالة النهائية كإخراج المحطة الطرفية. لتحديد مخرجات المشارك التي تريدها بشكل صريح، ادمج WithIntermediateOutputFrom و WithOutputFrom:

wf, err := agentworkflow.NewSequentialWorkflowBuilder(frenchAgent, spanishAgent, englishAgent).
    WithIntermediateOutputFrom(frenchAgent, spanishAgent).
    WithOutputFrom(englishAgent).
    Build()
if err != nil {
    return err
}

يستخدم OutputEvent.IsIntermediate() لتمييز مخرجات المشاركين الوسيطة عن مخرجات المحطة الطرفية.

المفاهيم الأساسية

  • المعالجة التسلسلية: يعالج كل عامل أو منفذ إخراج الخطوة السابقة بالترتيب.
  • تدفق عمل العامل. NewSequentialWorkflowBuilder(): ينشئ سير عمل البنية الأساسية لبرنامج ربط العمليات التجارية من مجموعة من العوامل.
  • العوامل المستضافة: agentworkflow.New يعرض خيارات تكوين العامل لإعادة توجيه الرسائل وإعادة تعيين الدور وتحديث الأحداث واعتراض الطلب.
  • المنفذون المخصصون: يمكن أن تخلط المسارات اليدوية workflow.NewBuilder بين العوامل المستضافة والمنفذين المحددين.
  • الموافقة على الأداة: توقف الأدوات المطلوبة للموافقة سير العمل مؤقتا وتبعث RequestInfoEvent القيم التي ToolApprovalRequestContentتحتوي على .
  • المخرجات المتوسطة: WithIntermediateOutputFrom وضع علامة على مخرجات المشارك المحدد باستخدام workflow.OutputTagIntermediate.

Tip

راجع نموذج أنماط سير عمل العاملوالوكلاء في نموذج مهام سير العمل لسير العمل التسلسلي الكامل القابل للتشغيل.

الخطوات التالية