Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O MAF .NET pode expor um fluxo de trabalho através de AG-UI convertendo o fluxo de trabalho para um AIAgent e mapeando-o como qualquer outro agente:
AIAgent workflowAgent = AgentWorkflowBuilder
.BuildSequential(researcher, reporter)
.AsAIAgent();
app.MapAGUIServer("/", workflowAgent);
O endpoint transmite em fluxo o texto padrão e o resultado das chamadas de ferramenta dos agentes que o constituem.
AuthorName Identifica o agente que produziu cada atualização.
O MAF .NET de momento não mapeia o comportamento específico do ciclo de vida do fluxo de trabalho para a AG-UI. Os clientes não recebem eventos das etapas do fluxo de trabalho, instantâneos de atividades, interrupções do fluxo de trabalho ou operações de retomação do fluxo de trabalho equivalentes às da integração em Python. Encapsular um fluxo de trabalho como AIAgent não adiciona esses mapeamentos.
Para o estado atual do rastreio .NET, consulte microsoft/agent-framework #2494. Para construção e execução de workflows independentes do AG-UI, veja conceitos de workflow MAF.
Passos seguintes
Este tutorial mostra-lhe como expor fluxos de trabalho do Agent Framework através de um endpoint AG-UI. Os fluxos de trabalho orquestram múltiplos agentes e ferramentas num grafo de execução definido, e a integração AG-UI transmite eventos ricos de workflow — rastreamento de passos, instantâneos de atividades, interrupções e eventos personalizados — para clientes web em tempo real.
Pré-requisitos
Antes de começar, certifique-se de que tem:
- Python 3.10 ou posterior
-
agent-framework-ag-uieagent-framework-foundryinstalado - Familiaridade com o tutorial de Início
- Compreensão básica dos conceitos de workflow do Agent Framework
Quando usar fluxos de trabalho com AG-UI
Use um fluxo de trabalho em vez de um único agente quando precisar:
- Orquestração multi-agente: Encaminhar tarefas entre agentes especializados (por exemplo, triagem → reembolso → ordem)
-
Etapas estruturadas de execução: Acompanhar o progresso através de fases definidas com
STEP_STARTED/STEP_FINISHEDeventos - Interrupção / retomada de fluxos: Pausar a execução para recolher entradas humanas ou aprovações, e retomar
-
Streaming de eventos personalizados: Emitir eventos específicos do domínio (
request_info,status,workflow_output) para o cliente
Envolver um Fluxo de Trabalho com o AgentFrameworkWorkflow
AgentFrameworkWorkflow é um wrapper leve que adapta um nativo Workflow ao protocolo AG-UI. Pode fornecer uma instância de workflow pré-configurada ou uma fábrica que crie um novo workflow por thread.
Instância direta
Use uma instância direta em que um único objeto de workflow possa servir todos os pedidos em segurança (por exemplo, pipelines sem estado):
from agent_framework import Workflow
from agent_framework.ag_ui import AgentFrameworkWorkflow
workflow = build_my_workflow() # returns a Workflow
ag_ui_workflow = AgentFrameworkWorkflow(
workflow=workflow,
name="my-workflow",
description="Single-instance workflow.",
)
Fábrica com escopo de rosca
Use workflow_factory quando cada thread de conversa precisar do seu próprio estado de fluxo de trabalho. A fábrica recebe o thread_id e devolve um novo Workflow:
from agent_framework.ag_ui import AgentFrameworkWorkflow
ag_ui_workflow = AgentFrameworkWorkflow(
workflow_factory=lambda thread_id: build_my_workflow(),
name="my-workflow",
description="Thread-scoped workflow.",
)
Importante
Deve passar ou umworkflowou outroworkflow_factory, mas não ambos. O invólucro gera um ValueError se ambos forem fornecidos.
Registo do Ponto Final
Registe o fluxo de trabalho add_agent_framework_fastapi_endpoint da mesma forma que registaria um único agente:
from fastapi import FastAPI
from agent_framework.ag_ui import (
AgentFrameworkWorkflow,
add_agent_framework_fastapi_endpoint,
)
app = FastAPI(title="Workflow AG-UI Server")
ag_ui_workflow = AgentFrameworkWorkflow(
workflow_factory=lambda thread_id: build_my_workflow(),
name="handoff-demo",
description="Multi-agent handoff workflow.",
)
add_agent_framework_fastapi_endpoint(
app=app,
agent=ag_ui_workflow,
path="/workflow",
)
Também pode passar diretamente um "bare" Workflow — o endpoint envolve-o automaticamente em AgentFrameworkWorkflow:
add_agent_framework_fastapi_endpoint(app, my_workflow, "/workflow")
AG-UI Eventos Emitidos pelos Fluxos de Trabalho
As execuções de workflow emitem um conjunto mais rico de eventos de AG-UI em comparação com as execuções de agente único:
| Event | Quando emitido | Descrição |
|---|---|---|
RUN_STARTED |
A corrida começa | Marca o início da execução do fluxo de trabalho |
STEP_STARTED |
Um executor ou superstep é iniciado |
step_name identifica o agente ou passo (por exemplo, "triage_agent") |
TEXT_MESSAGE_* |
Agente produz texto | Eventos padrão de texto em streaming |
TOOL_CALL_* |
O agente invoca uma ferramenta | Eventos padrão de chamada de ferramenta |
REASONING_* |
O fluxo de trabalho emite texto de um executor configurado em intermediate_output_from |
Transmite texto intermédio como bloco de raciocínio. O alias de evento obsoleto "data" segue o mesmo caminho. |
STEP_FINISHED |
Um executor ou superstep conclui | Fecha o passo para o acompanhamento do progresso da interface de utilizador |
CUSTOM (status) |
Alterações no estado do fluxo de trabalho | Contém {"state": "<value>"} no valor do evento |
CUSTOM (request_info) |
O fluxo de trabalho solicita a entrada humana | Contém o payload de pedido para o cliente renderizar um prompt |
CUSTOM (workflow_output) |
A saída do fluxo de trabalho não pode ser convertida em conteúdo de mensagem | Contém a saída serializada para renderização personalizada do cliente. |
RUN_FINISHED |
Corrida concluída | Inclui outcome.type == "interrupt" e outcome.interrupts quando o fluxo de trabalho está à espera de entrada |
Os clientes podem usar STEP_STARTED / STEP_FINISHED eventos para renderizar indicadores de progresso que mostram qual agente está atualmente ativo.
A integração fecha blocos de raciocínio aberto e texto antes de um evento terminal ou pedido de entrada humana, pelo que os clientes recebem uma sequência completa de eventos.
Quando um fluxo de trabalho em Python falha, RUN_ERROR usa a mensagem Workflow execution failed. pública genérica mais um código de erro. Um executor_failed evento também expõe a mensagem genérica e o tipo de erro. Detalhes internos de exceções e rastreamentos permanecem nos registos do servidor.
Interrupção e retomada
Os fluxos de trabalho podem pausar a execução para recolher contributos humanos ou aprovações de ferramentas. A integração AG-UI trata disto através do protocolo de interrupção/reinício.
Como funcionam as interrupções
Durante a execução, o fluxo de trabalho gera um pedido pendente (por exemplo, um
HandoffAgentUserRequesta solicitar mais detalhes, ou uma ferramenta comapproval_mode="always_require").A ponte AG-UI emite um evento
CUSTOMcomname="request_info"que contém os dados do pedido.A execução termina com um evento
RUN_FINISHEDem que o campooutcome.interruptscontém as solicitações pendentes:{ "type": "RUN_FINISHED", "threadId": "abc123", "runId": "run_xyz", "outcome": { "type": "interrupt", "interrupts": [ { "id": "request-id-1", "reason": "input_required", "message": "Provide the requested information.", "responseSchema": { "type": "string" }, "metadata": { "agent_framework": { "request_type": "HandoffAgentUserRequest" } } } ] } }O cliente renderiza a interface para o utilizador responder (uma entrada de texto, um botão de aprovação, etc.).
Como funciona o currículo
O cliente envia um novo pedido com um array canónico resume . Cada entrada identifica a interrupção e fornece a resposta do utilizador:
{
"threadId": "abc123",
"messages": [],
"resume": [
{
"interruptId": "request-id-1",
"status": "resolved",
"payload": "User's response text or approval decision"
}
]
}
O servidor converte a carga útil de retomada em respostas do fluxo de trabalho e continua a execução a partir do ponto em que parou. Para cancelar a execução interrompida, defina status para "cancelled" e omita payload.
Persistir e retomar os pontos de verificação do fluxo de trabalho
Configure checkpoint_storage em AgentFrameworkWorkflow para guardar o estado subjacente do fluxo de trabalho no final de cada superetapa. Em vez disso, pode passar o mesmo argumento ao add_agent_framework_fastapi_endpoint quando registar um fluxo de trabalho. Se o fluxo de trabalho subjacente foi criado com armazenamento de pontos de verificação, o adaptador pode usar esse construtor ou o armazenamento em tempo de execução diretamente, pelo que não é necessário duplicar a configuração no encapsulador ou no ponto terminal.
O exemplo seguinte utiliza armazenamento em memória para um fluxo de trabalho de curta duração:
from agent_framework import InMemoryCheckpointStorage
from agent_framework.ag_ui import (
AgentFrameworkWorkflow,
add_agent_framework_fastapi_endpoint,
)
from fastapi import FastAPI
app = FastAPI()
checkpoint_storage = InMemoryCheckpointStorage()
workflow = build_my_workflow()
ag_ui_workflow = AgentFrameworkWorkflow(
workflow=workflow,
checkpoint_storage=checkpoint_storage,
)
add_agent_framework_fastapi_endpoint(
app,
ag_ui_workflow,
"/workflow",
)
Quando uma execução é pausada e está disponível um ponto de controlo de pausa, cada interrupção no evento RUN_FINISHED inclui o ID desse ponto de controlo em metadata.agent_framework.checkpoint_id. Use esse valor emitido para retomar a pausa exata entre instâncias da aplicação sem uma pesquisa separada de ponto de verificação mais recente.
AgentFrameworkWorkflow.run() recebe a carga útil do pedido AG-UI, pelo que o cliente fornece o ID do ponto de controlo através de propriedades reencaminhadas, em vez de um argumento Python checkpoint_id. Uma retoma apenas de um ponto de controlo não inclui uma nova mensagem do utilizador:
{
"threadId": "abc123",
"messages": [],
"forwardedProps": {
"checkpointId": "checkpoint-id-from-interrupt-metadata"
}
}
O adaptador restaura o estado do fluxo de trabalho guardado e continua a execução. Se o checkpoint contiver uma interrupção pendente, inclua tanto o ID do checkpoint como a carga canónica resume no mesmo pedido. O adaptador restaura o ponto de verificação antes de emitir a resposta à interrupção. Use o valor de metadata.agent_framework.checkpoint_id como forwardedProps.checkpointId.
O adaptador associa cada novo checkpoint ao Snapshot Scope da solicitação e ao threadId fornecido pelo cliente. Rejeita um pedido de currículo quando nenhum dos valores corresponde. Os checkpoints escritos antes da introdução dos metadados de propriedade continuam a ser retomáveis para compatibilidade.
Esta verificação não substitui a autorização do terminal nem o armazenamento protegido do ponto de verificação. Para obter mais informações, consulte Considerações de segurança.
InMemoryCheckpointStorage Não sobrevive a reinícios de processos. Para opções de armazenamento duráveis e seleção de pontos de controlo, consulte Pontos de controlo.
Pontos de controlo do fluxo de trabalho e instantâneos de threads do AG-UI
Os checkpoints de fluxo de trabalho e os snapshots AG-UI thread mantêm dados diferentes:
| Mecanismo de persistência | Lojas | Purpose |
|---|---|---|
| Ponto de verificação do fluxo de trabalho do Agent Framework | Estado do executor e de execução, incluindo pedidos pendentes | Retomar a execução do fluxo de trabalho a partir do estado de execução guardado |
| captura da thread AG-UI | Resultado do protocolo reproduzível, como mensagens, estado partilhado e a interrupção mais recente | Reidrate o fio visível pelo cliente |
Podes configurar ambos os mecanismos. Um checkpoint de workflow não substitui um snapshot de thread AG-UI, e esse snapshot de thread AG-UI não contém o estado do executor necessário para retomar a execução do workflow.
Exemplo Completo: Fluxo de Trabalho de Transferência Multi-Agente
Este exemplo mostra um fluxo de trabalho de apoio ao cliente com três agentes que transferem trabalho entre si, utilizam ferramentas que requerem aprovação e solicitam intervenção humana quando necessário.
Defina os agentes e ferramentas
"""AG-UI workflow server with multi-agent handoff."""
import os
from agent_framework import Agent, Message, Workflow, tool
from agent_framework.ag_ui import (
AgentFrameworkWorkflow,
add_agent_framework_fastapi_endpoint,
)
from agent_framework.foundry import FoundryChatClient
from agent_framework.orchestrations import HandoffBuilder
from azure.identity import AzureCliCredential
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
@tool(approval_mode="always_require")
def submit_refund(refund_description: str, amount: str, order_id: str) -> str:
"""Capture a refund request for manual review before processing."""
return f"Refund recorded for order {order_id} (amount: {amount}): {refund_description}"
@tool(approval_mode="always_require")
def submit_replacement(order_id: str, shipping_preference: str, replacement_note: str) -> str:
"""Capture a replacement request for manual review before processing."""
return f"Replacement recorded for order {order_id} (shipping: {shipping_preference}): {replacement_note}"
@tool(approval_mode="never_require")
def lookup_order_details(order_id: str) -> dict[str, str]:
"""Return order details for a given order ID."""
return {
"order_id": order_id,
"item_name": "Wireless Headphones",
"amount": "$129.99",
"status": "delivered",
}
Criar o fluxo de trabalho
def create_handoff_workflow() -> Workflow:
"""Build a handoff workflow with triage, refund, and order agents."""
client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_MODEL"],
credential=AzureCliCredential(),
)
triage = Agent(id="triage_agent", name="triage_agent", instructions="...", client=client)
refund = Agent(id="refund_agent", name="refund_agent", instructions="...", client=client,
tools=[lookup_order_details, submit_refund])
order = Agent(id="order_agent", name="order_agent", instructions="...", client=client,
tools=[lookup_order_details, submit_replacement])
def termination_condition(conversation: list[Message]) -> bool:
for msg in reversed(conversation):
if msg.role == "assistant" and (msg.text or "").strip().lower().endswith("case complete."):
return True
return False
builder = HandoffBuilder(
name="support_workflow",
participants=[triage, refund, order],
termination_condition=termination_condition,
)
builder.add_handoff(triage, [refund], description="Route refund requests.")
builder.add_handoff(triage, [order], description="Route replacement requests.")
builder.add_handoff(refund, [order], description="Route to order after refund.")
builder.add_handoff(order, [triage], description="Route back after completion.")
return builder.with_start_agent(triage).build()
Criar a aplicação FastAPI
app = FastAPI(title="Workflow AG-UI Demo")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
ag_ui_workflow = AgentFrameworkWorkflow(
workflow_factory=lambda _thread_id: create_handoff_workflow(),
name="support_workflow",
description="Customer support handoff workflow.",
)
add_agent_framework_fastapi_endpoint(
app=app,
agent=ag_ui_workflow,
path="/support",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8888)
Sequência de eventos
Uma interação típica com vários turnos produz eventos como:
RUN_STARTED threadId=abc123
STEP_STARTED stepName=triage_agent
TEXT_MESSAGE_START role=assistant
TEXT_MESSAGE_CONTENT delta="I'll look into your refund..."
TEXT_MESSAGE_END
STEP_FINISHED stepName=triage_agent
STEP_STARTED stepName=refund_agent
TOOL_CALL_START toolCallName=lookup_order_details
TOOL_CALL_ARGS delta='{"order_id":"12345"}'
TOOL_CALL_END
TOOL_CALL_START toolCallName=submit_refund
TOOL_CALL_ARGS delta='{"order_id":"12345","amount":"$129.99",...}'
TOOL_CALL_END
RUN_FINISHED outcome={type: "interrupt", interrupts: [{id: "...", reason: "tool_call"}]}
O cliente pode então mostrar um diálogo de aprovação e retomar com a decisão do utilizador.
Receção de Propriedades Encaminhadas
clientes de AG-UI (como o CopilotKit) podem incluir um campo `forwarded_props` (ou `forwardedProps`) na entrada de carga útil. A integração AG-UI passa automaticamente estas propriedades para o método do fluxo de trabalho run através do argumento de palavra-chave function_invocation_kwargs.
class MyWorkflow(Workflow):
async def run(
self,
*,
message=None,
responses=None,
stream: bool = False,
function_invocation_kwargs: dict | None = None,
):
forwarded_props = (function_invocation_kwargs or {}).get("forwarded_props", {})
# Use forwarded_props for custom routing, feature flags, etc.
...
Detalhes principais:
- Tanto
forwarded_propscomoforwardedPropssão aceites na carga útil de entrada; internamente são normalizados paraforwarded_props. - Nas propriedades reencaminhadas,
checkpoint_idecheckpointIdestão reservados para a retoma de um ponto de controlo do fluxo de trabalho. - Se
workflow.run()não aceitarfunction_invocation_kwargs(ou**kwargs), as props são silenciosamente descartadas — os fluxos de trabalho existentes não são afetados. - Os props encaminhados também são armazenados nos metadados da sessão, mas são filtrados a partir dos metadados ligados ao LLM, para não serem infiltrados nos pedidos do cliente de chat.
Passos seguintes
Recursos adicionais
Go consegue disponibilizar fluxos de trabalho ao AG-UI ao encapsular um workflow.Workflow como agente com workflow/agentworkflow e, em seguida, alojar esse agente com provider/aguiprovider.
workflowAgent, err := agentworkflow.New(wf, agentworkflow.AgentConfig{
IncludeOutputsInResponse: true,
Config: agent.Config{
Name: "WorkflowAgent",
},
})
if err != nil {
panic(err)
}
mux := http.NewServeMux()
mux.Handle("/", aguiprovider.NewJSONHTTPHandler(workflowAgent, aguiprovider.HandlerConfig{}))
Tip
Veja o workflow como exemplo de agente e o exemplo de servidor AG-UI para exemplos completos e executáveis.