Skip to content

Python: Autonomous handoff re-invokes downstream orchestrations (Magentic/Concurrent) and can fail with already completed runtime error #6240

Closed

Description

@BharathRajR

When using HandoffBuilder in autonomous mode as a non-terminal orchestration and chaining it to another orchestration, I see repeated downstream invocations.

Observed behavior

  • In handoff + magentic, downstream gets invoked multiple times.
  • In handoff + concurrent, I see multiple agent_started events, suggesting repeated invocations.
  • This appears to happen because autonomous handoff emits multiple outputs, and downstream gets triggered for each output.

Exact error seen (handoff + magentic)

  • Workflow execution failed: RuntimeError: This Magentic workflow has already been completed. No further messages can be processed. Use the builder to create a new workflow instance to handle additional tasks.

Expected behaviour or clarification needed

  • Please confirm whether this is expected by design for autonomous handoff when chained to downstream orchestrations.
  • If expected, please share the recommended composition pattern so downstream executes once per logical handoff completion.
  • If not expected, please confirm if this should be treated as a bug.
  • Clarification on whether the turn limit should be 50 for it to work in autonomous mode, if not how to set a valid turn limit

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Jun 1, 2026
  2. added
    workflowsUsage: [Issues, PRs], Target: Workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Jun 2, 2026
  3. moonbox3 commented on Jun 2, 2026

    @moonbox3
    Contributor

    Thanks for the report. I looked through the Python orchestration path, and this is consistent with the current Handoff output contract, although it is an easy composition trap.

    Handoff differs from Sequential/Concurrent/Magentic: by default it does not emit one synthetic final/terminal output. Each participant response is workflow output as it speaks. In autonomous mode an agent may therefore emit multiple outputs before it hands off, reaches a termination condition, or hits its autonomous turn limit.

    When Handoff is wrapped as a non-terminal sub-workflow, WorkflowExecutor forwards each Handoff output to the parent as a separate message. A downstream Concurrent or Magentic workflow will therefore be invoked once per forwarded Handoff output. For Magentic specifically, the wrapped workflow instance is stateful and marks itself completed after processing a task, so a second forwarded Handoff output can produce the “already completed” error.

    Some recommended patterns:

    • If only one handoff participant should trigger the downstream workflow, configure Handoff with output_from=[that_agent] and optionally use intermediate_output_from="all_other" for progress visibility.
    • If the terminal participant is dynamic, do not chain raw Handoff outputs directly into Magentic/Concurrent. Instead, run Handoff to completion and collapse/select one logical output before invoking the downstream workflow, or add an adapter/finalizer step that emits exactly one downstream message.
    • If Magentic needs to process multiple logical tasks, create a fresh Magentic workflow from the builder per task rather than reusing a completed workflow instance.

    The autonomous turn limit does not need to be 50. 50 is just the default. You can set per-agent limits with with_autonomous_mode, for example:

    workflow = (
        HandoffBuilder(participants=[triage, worker], output_from=[worker])
        .with_start_agent(triage)
        .with_autonomous_mode(
            agents=[worker],
            turn_limits={resolve_agent_id(worker): 10},
        )
        .build()
    )

    The repeated downstream invocation are expected with the current output semantics.

  4. BharathRajR commented on Jun 3, 2026

    @BharathRajR
    Author

    Evan Mattson (@moonbox3)
    Hi team, reopening this issue because I am still seeing inconsistent autonomous-mode behavior for the same workflow and same prompt when only the turn limit changes.

    Based on prior guidance, I understood that any valid autonomous turn limit should work consistently, not that 50 is a special case.

    Test setup

    • Orchestration type: Handoff
    • Agents: 2 total (1 start agent + 1 additional agent)
    • Agent description: This agent assists developers with coding tasks and technical queries
    • Agent instruction: You are an expert programming assistant. Help users write, debug, and optimize code. Provide clear explanations and best practices
    • Prompt: same in all runs
    • Variable changed per run: autonomous turn limit only
    • Providers tested:
      1. Azure OpenAI Chat Completion Agents
      2. Foundry Chat Client

    Autonomous prompts tested
    1. "User did not respond. Continue assisting autonomously"
    2. "Continue autonomously because the user is temporarily unavailable. Do not pause or ask for clarification. Assume reasonable defaults, state assumptions briefly, and keep progressing step by step toward task completion."

    Primary prompt used in all comparisons
    "Build a computational genomics workflow for variant calling at scale with strict reproducibility, checkpointed execution, provenance metadata, and quality-control gates. Include algorithmic stages, data contracts, failure-retry semantics, and statistical validation framework."

    Observed behavior

    • Turn limit = 49: consistently received awaiting_user_response
    • Turn limit = 50: receives complete (or downstream completion behavior) instead of awaiting_user_response
    • Turn limit = 0 (default limit of 50 applied): receives complete

    Important note
    Even with a stronger autonomous prompt that explicitly says to continue and not pause, behavior at 50 is still inconsistent.
    This suggests a limit-boundary behavior difference between 49 and 50 for the same flow.

    Need help to get a clarity on whether this is an expected behaviour or not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

orchestrationUsage: [Issues, PRs], Target: multi-agent orchestration (high-level patterns)pythonUsage: [Issues, PRs], Target: PythonworkflowsUsage: [Issues, PRs], Target: Workflows

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions