استجابات خلفية العامل

يدعم Microsoft Agent Framework استجابات الخلفية لمعالجة العمليات طويلة الأمد التي قد تستغرق وقتا لإكمالها. تمكن هذه الميزة الوكلاء من البدء في معالجة طلب وإرجاع رمز متابعة يمكن استخدامه للاستقصاء عن النتائج أو استئناف التدفقات التي تمت مقاطعتها.

Tip

للحصول على مثال عمل كامل، راجع نموذج استجابات الخلفية.

متى تستخدم استجابات الخلفية

تعد استجابات الخلفية مفيدة بشكل خاص ل:

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

كيفية عمل استجابات الخلفية

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

  1. الإكمال الفوري: يكمل العامل المهمة بسرعة ويعيد الاستجابة النهائية دون رمز متابعة مميز
  2. معالجة الخلفية: يبدأ العامل المعالجة في الخلفية ويعيد رمز متابعة بدلا من النتيجة النهائية

يحتوي الرمز المميز للمتابعة على جميع المعلومات الضرورية إما للاستقصاء للاكتمال باستخدام واجهة برمجة تطبيقات العامل غير المتدفقة أو استئناف دفق متقطع باستخدام واجهة برمجة تطبيقات عامل البث. يعني الرمز المميز الغائب (nullفي .NET أو None في Python أو سلسلة فارغة في Go) أن العملية قد اكتملت أو فشلت أو لا يمكنها المتابعة بشكل أكبر، على سبيل المثال، عندما يكون إدخال المستخدم مطلوبا.

تمكين استجابات الخلفية

لتمكين استجابات الخلفية، قم بتعيين الخاصية AllowBackgroundResponses إلى true في AgentRunOptions:

using Microsoft.Agents.AI;

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

Note

حاليا، فقط الوكلاء الذين يستخدمون واجهة برمجة تطبيقات استجابات OpenAI يدعمون استجابات الخلفية: عامل استجابات OpenAIوعامل استجابات OpenAI Azure.

قد لا تسمح بعض العوامل بالتحكم الصريح في استجابات الخلفية. يمكن لهؤلاء الوكلاء أن يقرروا بشكل مستقل ما إذا كانوا سيبدأون استجابة خلفية استنادا إلى تعقيد العملية، بغض النظر عن AllowBackgroundResponses الإعداد.

الاستجابات الخلفية غير المتدفقة

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

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
    .AsAIAgent(
        model: "<deployment-name>",
        instructions: "You are a helpful assistant.");

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

AgentSession session = await agent.CreateSessionAsync();

// Get initial response - may return with or without a continuation token.
AgentResponse response = await agent.RunAsync(
    "Write a very long novel about otters in space.",
    session,
    options);

// Continue to poll until the final response is received
while (response.ContinuationToken is not null)
{
    // Wait before polling again.
    await Task.Delay(TimeSpan.FromSeconds(2));

    options.ContinuationToken = response.ContinuationToken;
    response = await agent.RunAsync(session, options);
}

Console.WriteLine(response.Text);

تحذير

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

نقاط رئيسية:

  • قد يكتمل الاستدعاء الأولي على الفور (لا يوجد رمز مميز للمتابعة) أو بدء عملية في الخلفية (مع رمز المتابعة المميز)
  • إذا لم يتم إرجاع رمز مميز للمتابعة، تكتمل العملية وتحتوي الاستجابة على النتيجة النهائية
  • إذا تم إرجاع رمز مميز للمتابعة، فقد بدأ العامل عملية خلفية تتطلب الاستقصاء
  • استخدام الرمز المميز للمتابعة من الاستجابة السابقة في مكالمات التحقق اللاحقة
  • عندما ContinuationToken يكون null، تكتمل العملية

استجابات الخلفية المتدفقة

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

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
    .AsAIAgent(
        model: "<deployment-name>",
        instructions: "You are a helpful assistant.");

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

AgentSession session = await agent.CreateSessionAsync();

AgentResponseUpdate? latestReceivedUpdate = null;

await foreach (var update in agent.RunStreamingAsync(
    "Write a very long novel about otters in space.",
    session,
    options))
{
    Console.Write(update.Text);

    latestReceivedUpdate = update;

    // Simulate an interruption
    break;
}

// Resume from interruption point captured by the continuation token
options.ContinuationToken = latestReceivedUpdate?.ContinuationToken;
await foreach (var update in agent.RunStreamingAsync(session, options))
{
    Console.Write(update.Text);
}

نقاط رئيسية:

  • يحتوي كل AgentResponseUpdate منها على رمز مميز للمتابعة يمكن استخدامه لاستئنافه
  • تخزين الرمز المميز للمتابعة من آخر تحديث تم تلقيه قبل الانقطاع
  • استخدم رمز المتابعة المخزن لاستئناف الدفق من نقطة الانقطاع

Tip

راجع نماذج .NET للحصول على أمثلة كاملة قابلة للتشغيل.

Tip

للحصول على مثال عمل كامل، راجع نموذج استجابات الخلفية.

تمكين استجابات الخلفية

لتمكين استجابات الخلفية، مرر background الخيار عند استدعاء agent.run():

session = agent.create_session()
response = await agent.run(
    messages="Your prompt here",
    session=session,
    options={"background": True},
)

Note

Python العوامل المدعومة من واجهة برمجة تطبيقات استجابات OpenAI أو Azure OpenAI Responses أو Microsoft Foundry تدعم استجابات الخلفية.

باستخدام FoundryChatClient، يمكن للاستجابات الخلفية تشغيل أدوات الوظائف المحلية إما مع تخزين الاستجابة من جانب الموفر (store=True) أو إعادة التشغيل عديمة الحالة (store=False). احتفظ بنفس الجلسة أثناء الاستقصاء حتى تتمكن الاستجابة المستأنفة من متابعة حلقة الأدوات المحلية.

الاستجابات الخلفية غير المتدفقة

بالنسبة للسيناريوهات غير المتدفقة، عند تشغيل عامل في البداية باستخدام background=True، قد يعود على الفور باستخدام continuation_token. إذا كان continuation_token هو None، فقد اكتملت العملية. وإلا، يتم الاستقصاء عن طريق تمرير الرمز المميز مرة أخرى في المكالمات اللاحقة:

import asyncio
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient

agent = Agent(
    name="researcher",
    instructions="You are a helpful research assistant.",
    client=OpenAIChatClient(model="o3"),
)

session = agent.create_session()

# Start a background run — returns immediately
response = await agent.run(
    messages="Briefly explain the theory of relativity in two sentences.",
    session=session,
    options={"background": True},
)

# Poll until the operation completes
while response.continuation_token is not None:
    await asyncio.sleep(2)
    response = await agent.run(
        session=session,
        options={"continuation_token": response.continuation_token},
    )

# Done — response.text contains the final result
print(response.text)

النقاط الرئيسية

  • قد يكتمل الاستدعاء الأولي على الفور (لا يوجد رمز مميز للمتابعة) أو بدء عملية في الخلفية (مع رمز المتابعة المميز)
  • continuation_token استخدم من الاستجابة السابقة في مكالمات الاستقصاء اللاحقة
  • عندما continuation_token يكون None، تكتمل العملية

استجابات الخلفية المتدفقة

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

session = agent.create_session()

# Start a streaming background run
last_token = None
stream = agent.run(
    messages="Briefly list three benefits of exercise.",
    stream=True,
    session=session,
    options={"background": True},
)

# Read chunks — each update carries a continuation_token
async for update in stream:
    last_token = update.continuation_token
    if update.text:
        print(update.text, end="", flush=True)
    # If interrupted (e.g., network issue), break and resume later

استئناف الدفق المتقطع

إذا تمت مقاطعة الدفق، فاستخدم آخر continuation_token استئناف من حيث توقف:

if last_token is not None:
    stream = agent.run(
        stream=True,
        session=session,
        options={"continuation_token": last_token},
    )
    async for update in stream:
        if update.text:
            print(update.text, end="", flush=True)

النقاط الرئيسية

  • يحتوي كل AgentResponseUpdate منها على continuation_token استئناف
  • تخزين الرمز المميز من آخر تحديث تم تلقيه قبل المقاطعة
  • تمرير الرمز المميز المخزن عبر options={"continuation_token": token} لاستئناف

تمكين استجابات الخلفية

مرر agent.AllowBackgroundResponses(true) عند بدء تشغيل، ثم أعد استخدام جلسة عمل صريحة من خلال agent.WithSession(session). يجب أن يدعم الموفر والنشر تنفيذ الخلفية؛ تعيين الخيار لا يجعل كل عامل غير متزامن.

الاستجابات الخلفية غير المتدفقة

ابدأ العملية، ثم قم باستطلاع الرأي بينما response.ContinuationToken لا يكون فارغا. المتابعة مع a.Run(ctx, nil, ...)، وليس RunText: يجب ألا تحتوي استدعاءات المتابعة على رسائل جديدة.

يحد نموذج استجابات OpenAI Azure الذي تم الاحتفاظ به العملية بمهلة، وينتظر بين الاستقصاءات، ويتوقف على الفور عند الإلغاء:

// Copyright (c) Microsoft. All rights reserved.

// This sample demonstrates long-running agent operations using the OpenAI
// Responses API "background" option. A background run returns quickly with a
// continuation token instead of the final answer; the caller then polls with
// that token until the operation completes.
//
// Ported from the Python getting-started "background responses" sample.
package main

import (
    "context"
    "time"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/examples/internal/demo"
    "github.com/microsoft/agent-framework-go/provider/openaiprovider"
    "github.com/openai/openai-go/v3"
    "github.com/openai/openai-go/v3/azure"
    "github.com/openai/openai-go/v3/option"
)

var logger = demo.NewLogger(
    "Background Responses",
    "Starts a background Responses run and polls with the continuation token until it completes.",
    "Model", demo.Deployment,
)

func main() {
    // Bound the whole sample so a run that never completes (stuck queued, a bad
    // continuation token, etc.) cannot hang indefinitely.
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
    defer cancel()

    token := demo.AzureTokenCredential()

    client := openai.NewClient(
        option.WithBaseURL(demo.Endpoint),
        azure.WithTokenCredential(token),
    )

    researcher := openaiprovider.NewResponsesAgent(
        client,
        openaiprovider.AgentConfig{
            Model:        demo.Deployment,
            Instructions: "You are a helpful research assistant. Be concise.",
            Config: agent.Config{
                Name:        "Researcher",
                Middlewares: []agent.Middleware{logger},
            },
        },
    )

    // Background runs are tied to a session so that follow-up polls target the
    // same operation.
    session, err := researcher.CreateSession(ctx)
    if err != nil {
        demo.Panic(err)
    }

    // Start a background run. It returns quickly with a continuation token
    // rather than the final answer. (If the model or endpoint does not support
    // background execution, the run simply completes inline with no token.)
    resp, err := researcher.RunText(ctx,
        "Briefly explain the theory of relativity in two sentences.",
        agent.WithSession(session),
        agent.AllowBackgroundResponses(true),
    ).Collect()
    if err != nil {
        demo.Panic(err)
    }

    // Poll until the operation completes — i.e. until a run no longer returns a
    // continuation token. Continuation runs must not carry any messages, so use
    // Run with a nil message slice.
    for resp.ContinuationToken != "" {
        // Wait between polls, but stop promptly if the context is cancelled or
        // its deadline is reached rather than sleeping through it.
        select {
        case <-ctx.Done():
            demo.Panic(ctx.Err())
        case <-time.After(2 * time.Second):
        }
        resp, err = researcher.Run(ctx, nil,
            agent.WithSession(session),
            agent.WithContinuationToken(resp.ContinuationToken),
        ).Collect()
        if err != nil {
            demo.Panic(err)
        }
    }

    // The final response holds the completed result.
    demo.Response(resp, nil)
}

تعيين AZURE_OPENAI_ENDPOINT وAZURE_OPENAI_DEPLOYMENT_NAME، والمصادقة باستخدام بيانات اعتماد Azure قبل تشغيل هذا النموذج. يقوم بطباعة الاستجابة المكتملة بعد انتهاء الاستقصاء. لا تحتوي الاستجابة المكتملة على الفور على رمز مميز للمتابعة ولا تحتاج إلى التحقق.

استجابات الخلفية المتدفقة

ابدأ تشغيل دفق باستخدام agent.Stream(true) و agent.AllowBackgroundResponses(true). احتفظ بالرمز المميز للمتابعة من آخر تحديث تتلقاه. إذا تمت مقاطعة الاتصال، فاستأنف العمل بدون رسائل جديدة:

for update, err := range a.Run(
    ctx,
    nil,
    agent.WithSession(session),
    agent.WithContinuationToken(lastToken),
    agent.Stream(true),
) {
    if err != nil {
        panic(err)
    }
    lastToken = update.ContinuationToken
    fmt.Print(update.String())
}

استئناف فقط عندما لا يكون الرمز المميز المحفوظ فارغا. الاحتفاظ بكل من جلسة العمل والرمز المميز في تخزين التطبيق إذا كان يجب أن تنجو العملية من إعادة تشغيل العملية.

استخدام استجابات الخلفية مع Harness Agent

يظل عامل Harness عامل إطار عمل عامل قياسي، لذلك تستخدم استجابات خلفية الموفر نفس الخيارات لكل تشغيل الموثقة أعلاه. لا يمكن بناء Harness استجابات خلفية الموفر تلقائيا: يتم تعيينه AllowBackgroundResponses في .NET أو options={"background": True} في Python أو agent.AllowBackgroundResponses(true) في Go عند بدء التشغيل. احتفظ بجلسة العمل والاحتفاظ بالرموز المميزة للمتابعة عندما يجب أن تنجو العملية من إعادة تشغيل العملية.

هذا منفصل عن وكلاء الخلفية، الذين يفوضون العمل إلى وكلاء تابعين بدلا من متابعة طلب موفر واحد.

أفضل الممارسات

عند العمل مع استجابات الخلفية، ضع في اعتبارك أفضل الممارسات التالية:

  • تنفيذ فواصل زمنية مناسبة للاستقصاء لتجنب إرباك الخدمة
  • استخدام التراجع الأسي للفواصل الزمنية للاستقصاء إذا كانت العملية تستغرق وقتا أطول من المتوقع
  • تحقق من وجود رمز مميز للمتابعة غير موجود (nullأو None، أو سلسلة Go فارغة) لتحديد وقت اكتمال المعالجة
  • ضع في اعتبارك تخزين الرموز المميزة للمتابعة باستمرار للعمليات التي قد تمتد عبر جلسات عمل المستخدم

القيود والاعتبارات

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

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