Files
agent-framework/python/samples/03-workflows
T
Evan Mattson 3bbc81554b Python: Improve the handling of intermediate outputs for workflows and orchestrations (#5623)
* Improve the handling of intermediate outputs for workflows and orchestrations

* Address PR review feedback on intermediate output forwarding

- Switch workflow.as_agent() forwarding to an explicit allowlist of {output,
  intermediate, data, request_info} so orchestration-internal events
  (group_chat, handoff_sent, magentic_orchestrator) stay inside the workflow
  instead of leaking into agent responses via str(data) coercion.
- Stop raising on intermediate AgentResponseUpdate in non-streaming run();
  surface the partial as a Message with text_reasoning content. The defensive
  raise still applies to terminal output events, where Update payloads would
  corrupt message ordering.
- Extend the DevUI workflow-event mapper so intermediate yields wrapping
  plain strings, Messages, and list[Message] render as visible output items
  instead of generic completed-trace events.
- Add orchestration coverage for GroupChat, Handoff, and Magentic builders
  (default vs intermediate_outputs=True; structural where end-to-end is heavy).

* Lift output-designation policy into a value type

Replace the ``Workflow._output_executors`` list and the
``RunnerContext.should_label_as_intermediate`` Protocol method with a single
immutable ``OutputDesignation`` value type owned by ``Workflow``. Thread the
designation as a parameter through the existing call chain (Runner ->
EdgeRunner -> Executor -> WorkflowContext) so ``yield_output`` consults the
threaded snapshot directly rather than calling back into the runner context.

Removes the ``InProcRunnerContext._workflow`` back-reference and the
``WorkflowBuilder.build()`` assignment that wired it up. Adds the public
predicate ``Workflow.is_terminal_executor(executor_id)`` for external
observers; ``OutputDesignation`` itself stays package-internal.

Key decisions
- ``OutputDesignation.designated`` is ``frozenset[str] | None`` -- ``None``
  preserves legacy "every yield is type='output'" behavior, any frozenset
  (including empty) opts into strict mode. The ``DeprecationWarning`` for
  legacy mode at build time is unchanged.
- ``output_designation`` is an optional parameter on ``Runner``,
  ``EdgeRunner.send_message``, ``EdgeRunner._execute_on_target``,
  ``Executor.execute``, ``Executor._create_context_for_handler``, and
  ``WorkflowContext.__init__``. Each defaults to legacy ``OutputDesignation()``
  so direct callers (Azure Functions ``CapturingRunnerContext``,
  ``test_runner`` recording fixtures) keep working without ceremony.
- The workflow-level filter in ``_run_core`` reads ``self._output_designation``
  live, preserving today's semantics where mutating the designation after
  build still affects subsequent runs (used by two existing tests).
- ``Workflow.to_dict()`` continues to emit ``"output_executors":
  list[str] | None`` (sorted from the frozenset). Checkpoint format unchanged.

Files changed
- _workflow.py: add ``OutputDesignation`` dataclass; replace
  ``_output_executors`` with ``_output_designation``; add
  ``is_terminal_executor``; delete ``_should_yield_output_event``.
- _runner_context.py: drop ``should_label_as_intermediate`` Protocol method
  and ``InProcRunnerContext`` impl; drop ``_workflow`` back-reference.
- _workflow_builder.py: remove ``context._workflow = workflow`` assignment.
- _runner.py, _edge_runner.py, _executor.py, _workflow_context.py: thread
  ``output_designation`` parameter through the call chain.
- tests/workflow/test_output_designation.py (new): three-state coverage of
  the value type plus the public predicate delegation.
- tests/workflow/test_workflow_builder.py, test_validation.py,
  test_workflow.py, test_runner.py and
  orchestrations/tests/test_orchestration_intermediate_vs_terminal.py:
  switch probes from ``_output_executors`` set checks to
  ``get_output_executors`` / ``is_terminal_executor``; update two
  post-build mutation tests to set ``_output_designation`` instead.

Verification
- core/tests/workflow/, orchestrations/tests/, azurefunctions/tests/:
  1119 passed, 42 skipped, 2 xfailed.
- ``uv run poe lint``: clean.
- ``uv run poe typing``: only the pre-existing
  ``_AGENT_FORWARDED_EVENT_TYPES`` pyright warning from 394bcd607 remains.

Notes for next iteration
- The builder's own ``_output_executors`` attribute (``list[Executor |
  SupportsAgentRun]``) is intentionally untouched; the issue scoped the
  rename to the workflow attribute.
- Adjacent review candidates (twin ``WorkflowAgent`` translators,
  ``_AGENT_FORWARDED_EVENT_TYPES`` kind classifier,
  ``_event_origin_context`` ContextVar removal, ``WorkflowEvent`` ADT
  split, legacy-mode removal) remain out of scope.

* Add explicit workflow output designation

Key decisions

- Extend the internal OutputDesignation value type from terminal-only membership to output/intermediate/hidden classification. Legacy mode remains outputs=None, so workflows built without output_executors or intermediate_executors still label every yield_output as type='output'.

- WorkflowBuilder now accepts intermediate_executors. Providing either designation enters explicit mode; output executors emit output, intermediate executors emit intermediate, and unlisted yield_output payloads are hidden from caller-facing events while remaining in executor_completed data.

- Empty explicit designation, duplicate entries, overlaps, unknown executors, and designated executors without workflow output annotations fail build validation. Existing orchestration builders pass intermediate-capable participants through intermediate_executors to preserve current intermediate_outputs behavior until participant-oriented designation lands.

Files changed

- packages/core/agent_framework/_workflows/_workflow.py, _workflow_builder.py, _workflow_context.py, _validation.py, _events.py

- packages/core/tests/workflow/test_output_designation.py, test_output_executors_contract.py, test_strict_mode_event_labeling.py, test_validation.py, test_workflow.py, test_workflow_agent_intermediate.py

- packages/orchestrations/agent_framework_orchestrations/_sequential.py, _concurrent.py, _group_chat.py, _magentic.py

- packages/core/AGENTS.md

Verification

- uv run pytest packages/core/tests/workflow packages/orchestrations/tests packages/devui/tests/devui/test_mapper.py -q

- uv run pytest packages/azurefunctions/tests -q

- uv run poe lint

- uv run poe typing fails only on pre-existing packages/core/agent_framework/_workflows/_agent.py _AGENT_FORWARDED_EVENT_TYPES private-use pyright error.

Notes for next iteration

- issues/03-core-workflow-explicit-designation.md was moved to issues/done but issues/ remains untracked and intentionally excluded from this commit.

- Slice 4 should tighten workflow.as_agent() mapping for hidden emissions and streaming-only update payloads; Slice 5 should replace orchestration intermediate_outputs with participant-oriented designation.

* Tighten workflow-as-agent output mapping

Key decisions

- Treat AgentResponseUpdate as a streaming-only payload across the workflow.as_agent() adapter, so non-streaming agent runs now reject both terminal output and intermediate workflow events carrying updates.
- Keep streaming classification behavior explicit: terminal update payloads remain normal text content, while intermediate update payloads are rewritten to text_reasoning content.
- Add explicit-mode coverage proving hidden yield_output emissions do not appear in non-streaming AgentResponse messages or streaming AgentResponseUpdate chunks.

Files changed

- packages/core/agent_framework/_workflows/_agent.py
- packages/core/tests/workflow/test_workflow_agent_intermediate.py

Verification

- uv run pytest packages/core/tests/workflow/test_workflow_agent_intermediate.py -q
- uv run pytest packages/core/tests/workflow/test_workflow_agent.py packages/core/tests/workflow/test_workflow_agent_intermediate.py -q
- uv run pytest packages/core/tests/workflow packages/orchestrations/tests packages/devui/tests/devui/test_mapper.py -q
- uv run poe lint
- uv run poe typing fails only on the pre-existing packages/core/agent_framework/_workflows/_agent.py _AGENT_FORWARDED_EVENT_TYPES private-use pyright error.

Blockers or notes for next iteration

- issues/04-workflow-as-agent-output-mapping.md was moved to issues/done/ but issues/ remains untracked and intentionally excluded from this commit.
- Slice 5 should replace orchestration intermediate_outputs with participant-oriented designation.

* Add orchestration participant output designation

Key decisions

- Replace orchestration intermediate_outputs with participant-oriented output_participants and intermediate_participants across Sequential, Concurrent, GroupChat, Magentic, and Handoff builders.
- Keep synthetic final executors terminal by default for Concurrent, GroupChat, and Magentic; keep Sequential's final participant terminal by default; keep Handoff participants terminal by default.
- Centralize participant designation validation for empty explicit designation, duplicates, overlaps, and unknown participants, then map validated participants to workflow output/intermediate executors.

Files changed

- packages/orchestrations/agent_framework_orchestrations/_participant_designation.py
- packages/orchestrations/agent_framework_orchestrations/_sequential.py
- packages/orchestrations/agent_framework_orchestrations/_concurrent.py
- packages/orchestrations/agent_framework_orchestrations/_group_chat.py
- packages/orchestrations/agent_framework_orchestrations/_magentic.py
- packages/orchestrations/agent_framework_orchestrations/_handoff.py
- packages/orchestrations/tests/test_orchestration_intermediate_vs_terminal.py
- packages/orchestrations/tests/test_magentic.py

Blockers or notes for next iteration

- issues/05-orchestration-participant-designation.md was moved to issues/done/ but issues/ remains untracked and intentionally excluded from this commit.
- Slice 7 should migrate samples and docs away from intermediate_outputs to the new participant designation API.
- uv run poe typing still fails only on the pre-existing packages/core/agent_framework/_workflows/_agent.py _AGENT_FORWARDED_EVENT_TYPES private-use pyright error.

* Migrate samples to explicit output designation

Key decisions

- Replace sample usage of the removed orchestration intermediate_outputs boolean with participant-oriented intermediate_participants designation.
- Update raw workflow guidance to show output_executors together with intermediate_executors, and document that unlisted yields are hidden in explicit designation mode.
- Keep orchestration final outputs terminal while streaming designated participant responses as intermediate progress, including workflow.as_agent() samples where intermediates map to text_reasoning content.
- Refresh workflow and orchestration README guidance plus the changelog reference so public docs no longer point users at intermediate_outputs.

Files changed

- CHANGELOG.md
- packages/orchestrations/README.md
- samples/README.md
- samples/03-workflows/README.md
- samples/03-workflows/control-flow/intermediate_vs_terminal_outputs.py
- samples/03-workflows/orchestrations/README.md
- samples/03-workflows/orchestrations/group_chat_agent_manager.py
- samples/03-workflows/orchestrations/group_chat_philosophical_debate.py
- samples/03-workflows/orchestrations/group_chat_simple_selector.py
- samples/03-workflows/orchestrations/magentic.py
- samples/03-workflows/orchestrations/magentic_human_plan_review.py
- samples/03-workflows/orchestrations/sequential_chain_only_agent_responses.py
- samples/03-workflows/agents/group_chat_workflow_as_agent.py
- samples/03-workflows/agents/magentic_workflow_as_agent.py
- samples/03-workflows/agents/sequential_workflow_as_agent.py
- samples/semantic-kernel-migration/orchestrations/group_chat.py
- samples/semantic-kernel-migration/orchestrations/magentic.py

Blockers or notes for next iteration

- issues/07-samples-and-docs-explicit-output-designation.md was moved to issues/done/ but issues/ remains untracked and intentionally excluded from this commit.
- issues/06-devui-intermediate-event-rendering.md remains present and appears already satisfied by existing DevUI mapper/tests from the prior implementation slice.
- PRD-explicit-workflow-output-designation.md remains untracked and intentionally excluded from this commit.

* Render DevUI intermediate workflow outputs

Key decisions

- Preserve workflow output designation metadata on visible DevUI output messages and text deltas so intermediate/data emissions remain distinguishable from terminal output.
- Render intermediate workflow message items in the execution timeline using executor metadata, while excluding them from the final workflow result aggregation.
- Keep terminal output message rendering unchanged and retain legacy data events on the intermediate compatibility path.

Files changed

- packages/devui/agent_framework_devui/_mapper.py
- packages/devui/frontend/src/components/features/workflow/execution-timeline.tsx
- packages/devui/frontend/src/components/features/workflow/workflow-view.tsx
- packages/devui/frontend/src/types/openai.ts
- packages/devui/tests/devui/test_mapper.py

Blockers or notes for next iteration

- issues/06-devui-intermediate-event-rendering.md was moved to issues/done/ but issues/ remains untracked and intentionally excluded from this commit.
- PRD-explicit-workflow-output-designation.md remains untracked and intentionally excluded from this commit.
- uv run poe typing still fails only on the pre-existing packages/core/agent_framework/_workflows/_agent.py _AGENT_FORWARDED_EVENT_TYPES private-use pyright error.

* Fix mypy

* Clarify orchestration participant output config

* Rename participant output kwargs for clarity

output_participants -> final_output_from, intermediate_participants ->
intermediate_output_from. The old names read like categories of
participant; the new names make it clear the kwarg designates which
participants' outputs surface as final vs. intermediate events.

* Rename core workflow output kwargs with deprecation shim

Adds final_output_from / intermediate_output_from as canonical kwargs on
Workflow and WorkflowBuilder. Old output_executors / intermediate_executors
kwargs continue to work but emit DeprecationWarning via a shared coalesce
helper that also rejects supplying both. Wire-format keys in to_dict()
stay as output_executors / intermediate_executors so checkpoint
compatibility is preserved.

Internal call sites in orchestrations and samples updated to the new
names so users following sample code learn the canonical vocabulary;
legacy callers still work with a one-shot warning.

* Suppress pyright reportPrivateUsage on cross-module sentinel import

* Update docstrings

* Propagate sub-workflow intermediate outputs, fix handoff/sequential intermediate-only designation, and shore up tests, sample, and docstrings around the intermediate output contract.

* Add canonical workflow output_from selection

Key decisions:\n- Make output_from the canonical workflow-output allow-list and keep output_executors/final_output_from as deprecated compatibility aliases.\n- Treat empty output_from/intermediate_output_from lists as explicit selections and keep validation responsible for empty, duplicate, overlap, and unknown selections.\n- Remove the branch-only public intermediate_executors WorkflowBuilder kwarg while preserving legacy wire keys in to_dict().\n\nFiles changed:\n- packages/core/agent_framework/_workflows/_workflow.py\n- packages/core/agent_framework/_workflows/_workflow_builder.py\n- packages/core/agent_framework/_workflows/_workflow_context.py\n- packages/core/agent_framework/_workflows/_agent.py\n- packages/core/agent_framework/_workflows/_agent_executor.py\n- packages/core/tests/workflow/* output-selection coverage updates\n- packages/core/AGENTS.md\n- issues/done/001-canonical-list-based-output-selection.md\n\nBlockers/notes:\n- Orchestration builders still pass final_output_from internally; follow-up issue 004 should migrate them to output_from.\n- Legacy omitted-selection behavior and explicit all/all_other literals are left for issues 002 and 003.

* Add explicit all workflow output selection

Key decisions:
- Treat output_from='all' as an explicit workflow-output selection sentinel and expand it at build time to executors with declared workflow output types.
- Keep omitted output selections in legacy all-output mode with a deprecation warning that names output_from and intermediate_output_from and points to output_from='all'.
- Reject intermediate_output_from='all' at construction because the all-output literal is output-only for this issue.

Files changed:
- packages/core/agent_framework/_workflows/_workflow_builder.py
- packages/core/tests/workflow/test_output_executors_contract.py
- issues/done/002-explicit-all-output-and-legacy-migration.md

Blockers/notes:
- all_other intermediate-output selection remains for issue 003.
- Workflow-as-agent/orchestration parity remains for issue 004.

* Add all-other intermediate output selection

Key decisions:
- Treat intermediate_output_from='all_other' as an explicit intermediate-output selection sentinel and expand it at build time after the workflow graph is complete.
- Expand all_other to output-capable executors not selected by output_from; omitted or empty output_from selects no workflow outputs, while output_from='all' leaves an empty intermediate selection.
- Keep output_from='all_other' invalid so all_other remains intermediate-output-only and runtime classification still receives concrete executor-id sets.

Files changed:
- packages/core/agent_framework/_workflows/_workflow_builder.py
- packages/core/tests/workflow/test_output_executors_contract.py
- issues/done/003-all-other-intermediate-output-selection.md

Blockers/notes:
- Workflow-as-agent and orchestration parity remains for issue 004.
- Full documentation updates remain for issue 005.

* Add orchestration output selection parity

Key decisions:
- Expose output_from on sequential, concurrent, group chat, handoff, and magentic builders while keeping final_output_from as a deprecated compatibility alias.
- Resolve orchestration participant selections through the same explicit rules as workflows: output_from='all', intermediate_output_from='all_other', hidden unselected participant payloads, and overlap/duplicate/unknown/invalid-literal validation.
- Continue preserving documented orchestration defaults by always designating each pattern's terminal internal executor where applicable.

Files changed:
- packages/orchestrations/agent_framework_orchestrations/_participant_output_config.py
- packages/orchestrations/agent_framework_orchestrations/_sequential.py
- packages/orchestrations/agent_framework_orchestrations/_concurrent.py
- packages/orchestrations/agent_framework_orchestrations/_group_chat.py
- packages/orchestrations/agent_framework_orchestrations/_handoff.py
- packages/orchestrations/agent_framework_orchestrations/_magentic.py
- packages/orchestrations/agent_framework_orchestrations/_orchestration_request_info.py
- packages/orchestrations/tests/test_orchestration_intermediate_vs_terminal.py
- issues/done/004-workflow-as-agent-and-orchestration-parity.md

Blockers/notes:
- Full documentation and sample migration wording remains for issue 005.
- Existing tests that intentionally use final_output_from now emit the new deprecation warning.

* Document workflow output selection contract

Key decisions:
- Use Workflow Output and Intermediate Output as the developer-facing terms for selected caller-facing emissions.
- Document output_from and intermediate_output_from as the canonical API, with output_from as an allow-list and unselected payloads hidden unless explicitly selected as intermediate.
- Add scenario and invalid-selection tables for workflow and orchestration docs, including legacy omission warnings, output_from='all', intermediate_output_from='all_other', list selections, invalid literals, overlap, duplicates, unknown selections, and empty explicit selections.
- Migrate samples away from final_output_from and output_executors except where compatibility aliases are explicitly documented.

Files changed:
- packages/core/AGENTS.md
- packages/orchestrations/README.md
- packages/orchestrations/agent_framework_orchestrations/_handoff.py
- packages/orchestrations/agent_framework_orchestrations/_sequential.py
- samples/03-workflows/README.md
- samples/03-workflows/control-flow/intermediate_vs_terminal_outputs.py
- samples/03-workflows/human-in-the-loop/agents_with_approval_requests.py
- samples/03-workflows/orchestrations/README.md
- samples/04-hosting/foundry-hosted-agents/responses/05_workflows/main.py
- scripts/sample_validation/create_dynamic_workflow_executor.py
- issues/done/005-document-output-selection-contract.md

Blockers/notes:
- Direct full Ruff on scripts/sample_validation/create_dynamic_workflow_executor.py still reports pre-existing docstring/print/line-length issues outside this docs migration; syntax-focused checks for changed files pass.
- No remaining AFK issue files are present under issues/.

* Latest updates

* Typing fixes

* Cleanup
3bbc81554b ยท 2026-05-19 00:15:25 +00:00
History
..
2026-03-31 15:20:35 +00:00
2026-03-31 15:20:35 +00:00

Workflows Getting Started Samples

Installation

Microsoft Agent Framework Workflows support ships with the core agent-framework or agent-framework-core package, so no extra installation step is required.

To install with visualization support:

pip install agent-framework[viz] --pre

To export visualization images you also need to install GraphViz.

Samples Overview

Foundational Concepts - Start Here

Begin with the _start-here folder in order. These three samples introduce the core ideas of executors, edges, agents in workflows, and streaming.

Sample File Concepts
Executors and Edges _start-here/step1_executors_and_edges.py Minimal workflow with basic executors and edges
Agents in a Workflow _start-here/step2_agents_in_a_workflow.py Introduces adding Agents as nodes; calling agents inside a workflow
Streaming (Basics) _start-here/step3_streaming.py Extends workflows with event streaming

Once comfortable with these, explore the rest of the samples below.


Samples Overview (by directory)

functional

Write workflows as plain Python async functions โ€” no graph concepts, no executor classes, no edges. Use native control flow (if/else, loops, asyncio.gather) for branching and parallelism.

Sample File Concepts
Basic Pipeline functional/basic_pipeline.py Sequential steps as plain async functions
Basic Streaming Pipeline functional/basic_streaming_pipeline.py Stream workflow events in real time with run(stream=True)
Parallel Pipeline functional/parallel_pipeline.py Fan-out/fan-in with asyncio.gather
Steps and Checkpointing functional/steps_and_checkpointing.py @step decorator for per-step checkpointing and observability
Human-in-the-Loop Review functional/hitl_review.py HITL with ctx.request_info() and replay
Agent Integration functional/agent_integration.py Calling agents inside workflow steps
Naive Group Chat functional/naive_group_chat.py Simple round-robin group chat as a plain loop

agents

Sample File Concepts
Azure Chat Agents (Streaming) agents/azure_chat_agents_streaming.py Add Azure Chat agents as edges and handle streaming events
Azure AI Agents (Streaming) agents/azure_ai_agents_streaming.py Add Azure AI agents as edges and handle streaming events
Azure AI Agents (Shared Thread) agents/azure_ai_agents_with_shared_session.py Share a common message session between multiple Azure AI agents in a workflow
Custom Agent Executors agents/custom_agent_executors.py Create executors to handle agent run methods
Workflow as Agent (Reflection Pattern) agents/workflow_as_agent_reflection_pattern.py Wrap a workflow so it can behave like an agent (reflection pattern)
Workflow as Agent + HITL agents/workflow_as_agent_human_in_the_loop.py Extend workflow-as-agent with human-in-the-loop capability
Workflow as Agent with Session agents/workflow_as_agent_with_session.py Use AgentSession to maintain conversation history across workflow-as-agent invocations
Workflow as Agent kwargs agents/workflow_as_agent_kwargs.py Pass custom context (data, user tokens) via kwargs through workflow.as_agent() to @tool tools

checkpoint

Sample File Concepts
Checkpoint & Resume checkpoint/checkpoint_with_resume.py Create checkpoints, inspect them, and resume execution
Checkpoint & HITL Resume checkpoint/checkpoint_with_human_in_the_loop.py Combine checkpointing with human approvals and resume pending HITL requests
Checkpointed Sub-Workflow checkpoint/sub_workflow_checkpoint.py Save and resume a sub-workflow that pauses for human approval
Handoff + Tool Approval Resume orchestrations/handoff_with_tool_approval_checkpoint_resume.py Handoff workflow that captures tool-call approvals in checkpoints and resumes with human decisions
Workflow as Agent Checkpoint checkpoint/workflow_as_agent_checkpoint.py Enable checkpointing when using workflow.as_agent() with checkpoint_storage parameter
Cosmos DB Checkpoint Storage checkpoint/cosmos_workflow_checkpointing.py Use CosmosCheckpointStorage for durable workflow checkpointing backed by Azure Cosmos DB NoSQL
Cosmos DB + Foundry Checkpoint checkpoint/cosmos_workflow_checkpointing_foundry.py Multi-agent workflow using FoundryChatClient with CosmosCheckpointStorage for durable pause/resume

composition

Sample File Concepts
Sub-Workflow (Basics) composition/sub_workflow_basics.py Wrap a workflow as an executor and orchestrate sub-workflows
Sub-Workflow: Request Interception composition/sub_workflow_request_interception.py Intercept and forward sub-workflow requests using @handler for SubWorkflowRequestMessage
Sub-Workflow: Parallel Requests composition/sub_workflow_parallel_requests.py Multiple specialized interceptors handling different request types from same sub-workflow
Sub-Workflow: kwargs Propagation composition/sub_workflow_kwargs.py Pass custom context (user tokens, config) from parent workflow through to sub-workflow agents

control-flow

Sample File Concepts
Sequential Executors control-flow/sequential_executors.py Sequential workflow with explicit executor setup
Sequential (Streaming) control-flow/sequential_streaming.py Stream events from a simple sequential run
Edge Condition control-flow/edge_condition.py Conditional routing based on agent classification
Switch-Case Edge Group control-flow/switch_case_edge_group.py Switch-case branching using classifier outputs
Multi-Selection Edge Group control-flow/multi_selection_edge_group.py Select one or many targets dynamically (subset fan-out)
Simple Loop control-flow/simple_loop.py Feedback loop where an agent judges ABOVE/BELOW/MATCHED
Workflow Cancellation control-flow/workflow_cancellation.py Cancel a running workflow using asyncio tasks
Workflow and Intermediate Outputs control-flow/intermediate_vs_terminal_outputs.py Select Workflow Output and Intermediate Output executors; hide unselected yields; map Intermediate Output events to text_reasoning content via as_agent

human-in-the-loop

Sample File Concepts
Human-In-The-Loop (Guessing Game) human-in-the-loop/guessing_game_with_human_input.py Interactive request/response prompts with a human via ctx.request_info()
Agents with Approval Requests in Workflows human-in-the-loop/agents_with_approval_requests.py Agents that create approval requests during workflow execution and wait for human approval to proceed
Agents with Declaration-Only Tools human-in-the-loop/agents_with_declaration_only_tools.py Workflow pauses when agent calls a client-side tool (func=None), caller supplies the result

Builder-oriented request-info samples are maintained in the orchestration sample set (sequential, concurrent, and group-chat builder variants).

tool-approval

Builder-based tool approval samples are maintained in the orchestration sample set.

observability

Sample File Concepts
Executor I/O Observation observability/executor_io_observation.py Observe executor input/output data via executor_invoked events (type='executor_invoked') and executor_completed events (type='executor_completed') without modifying executor code

For additional observability samples in Agent Framework, see the observability concept samples. The workflow observability sample demonstrates integrating observability into workflows.

orchestration

Orchestration-focused samples (Sequential, Concurrent, Handoff, GroupChat, Magentic), including builder-based workflow.as_agent(...) variants, are documented in the orchestrations directory.

output selection

Workflow Output selection controls which ctx.yield_output(...) calls are visible to callers as type='output' events and through WorkflowRunResult.get_outputs(). The core rule is that output_from is an allow-list for Workflow Output, not a routing rule for every other executor output. Unselected executor payloads are hidden unless intermediate_output_from explicitly selects them as Intermediate Output.

Use output_from and intermediate_output_from as the canonical API:

Selection Workflow Output Intermediate Output Hidden payloads
Omit both selections Every executor yield_output; emits a deprecation warning None None
output_from="all" Every executor yield_output; no warning None None
output_from=[answerer] Only answerer None All other executor payloads
output_from=[answerer], intermediate_output_from="all_other" Only answerer Every output-capable executor not selected by output_from None
intermediate_output_from="all_other" None Every output-capable executor None
output_from=[], intermediate_output_from="all_other" None Every output-capable executor None
output_from=[answerer], intermediate_output_from=[planner, researcher] Only answerer planner and researcher Any other executor payloads

Invalid selections fail at construction or build time:

Invalid selection Why it fails
output_from="all_other" "all_other" is only valid for intermediate_output_from
intermediate_output_from="all" "all" is only valid for output_from
The same executor in both selections One payload cannot be both Workflow Output and Intermediate Output
Duplicate executor selections Duplicates are treated as configuration errors
Unknown executor selections Typos and missing participants are rejected
output_from=[], intermediate_output_from=[] Both explicit selections are empty

Compatibility aliases such as output_executors emit deprecation warnings where supported. New samples and applications should use output_from and intermediate_output_from.

When a workflow is wrapped with workflow.as_agent(), Workflow Output becomes normal agent text content. Intermediate Output becomes text_reasoning content, so AgentResponse.text remains focused on the caller-facing answer while callers can still inspect progress or supporting work from the response messages.

parallelism

Sample File Concepts
Concurrent (Fan-out/Fan-in) parallelism/fan_out_fan_in_edges.py Dispatch to multiple executors and aggregate results
Aggregate Results of Different Types parallelism/aggregate_results_of_different_types.py Handle results of different types from multiple concurrent executors
Map-Reduce with Visualization parallelism/map_reduce_and_visualization.py Fan-out/fan-in pattern with diagram export

state-management

Sample File Concepts
State with Agents state-management/state_with_agents.py Store in state once and later reuse across agents
Workflow Kwargs - Global Context state-management/workflow_kwargs_global.py Pass custom context (data, user tokens) via kwargs to @tool tools in all agents
Workflow Kwargs - Per Agent state-management/workflow_kwargs_per_agent.py Pass custom context (data, user tokens) via kwargs to @tool tools in individual agents

visualization

Sample File Concepts
Concurrent with Visualization visualization/concurrent_with_visualization.py Fan-out/fan-in workflow with diagram export

declarative

YAML-based declarative workflows allow you to define multi-agent orchestration patterns without writing Python code. See the declarative workflows README for more details on YAML workflow syntax and available actions.

Sample File Concepts
Agent to Function Tool declarative/agent_to_function_tool/ Chain agent output to InvokeFunctionTool actions
Conditional Workflow declarative/conditional_workflow/ Nested conditional branching based on user input
Customer Support declarative/customer_support/ Multi-agent customer support with routing
Deep Research declarative/deep_research/ Research workflow with planning, searching, and synthesis
Function Tools declarative/function_tools/ Invoking Python functions from declarative workflows
Human-in-Loop declarative/human_in_loop/ Interactive workflows that request user input
Invoke Function Tool declarative/invoke_function_tool/ Call registered Python functions with InvokeFunctionTool
Marketing declarative/marketing/ Marketing content generation workflow
Simple Workflow declarative/simple_workflow/ Basic workflow with variable setting, conditionals, and loops
Student Teacher declarative/student_teacher/ Student-teacher interaction pattern

resources

Notes

  • Agent-based samples use provider SDKs (Azure/OpenAI, etc.). Ensure credentials are configured, or adapt agents accordingly.

Sequential orchestration uses a few small adapter nodes for plumbing:

  • "input-conversation" normalizes input to list[Message]
  • "to-conversation:" converts agent responses into the shared conversation
  • "complete" publishes the Workflow Output event (type='output') These may appear in event streams (executor_invoked/executor_completed). They're analogous to concurrentโ€™s dispatcher and aggregator and can be ignored if you only care about agent activity.

Why FoundryChatClient?

Workflow and orchestration samples use FoundryChatClient because they create agents locally and do not need server-managed agent resources. This lightweight, project-backed chat client is a good fit for orchestration patterns such as Sequential, Concurrent, Handoff, GroupChat, and Magentic.

If you need persistent server-side agent resources, use the hosted-agent flows rather than these workflow samples.

Environment Variables

Workflow samples that use FoundryChatClient expect:

  • FOUNDRY_PROJECT_ENDPOINT (Azure AI Foundry Agent Service (V2) project endpoint)
  • FOUNDRY_MODEL (model deployment name)

These values are passed directly into the client constructor via os.getenv() in sample code.