Skip to content

Python: Built-in group chat message types are rejected during checkpoint restore #7789

Closed

Description

Description

When a workflow uses GroupChatBuilder with checkpoint persistence, checkpoint restore can fail because built-in group-chat envelope types are not included in the default checkpoint deserialization allowlist.

The affected types include:

  • agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatRequestMessage
  • agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatParticipantMessage
  • agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatResponseMessage

These are framework-owned types emitted and routed by the group-chat orchestration implementation, but users currently need to manually add them to FileCheckpointStorage(allowed_checkpoint_types=...).

Error

Failed to decode pickled checkpoint data: Checkpoint deserialization blocked for type 'agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatParticipantMessage'. To allow this type, either include its 'module:qualname' key in the 'allowed_types' set passed to 'decode_checkpoint_value', or add it to 'allowed_checkpoint_types' on your checkpoint storage.

Reproduction

from agent_framework._workflows._checkpoint import FileCheckpointStorage
from agent_framework_orchestrations import GroupChatBuilder

storage = FileCheckpointStorage("./checkpoints")

workflow = GroupChatBuilder(
    participants=[...],
    orchestrator_agent=...,
    checkpoint_storage=storage,
).build()

# Run until a checkpoint contains a group-chat envelope, then restore it.

Expected behavior

Framework-owned orchestration message types should be included in the framework's trusted checkpoint type registry by default, or the orchestration package should provide a documented helper that registers all of its checkpoint-safe types.

Users should not need to maintain an internal module-path allowlist for built-in MAF orchestration envelopes.

Workaround

storage = FileCheckpointStorage(
    "./checkpoints",
    allowed_checkpoint_types=[
        "agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatRequestMessage",
        "agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatParticipantMessage",
        "agent_framework_orchestrations._base_group_chat_orchestrator:GroupChatResponseMessage",
    ],
)

Additional context

The same consideration may apply to other framework-owned orchestration payloads, such as handoff and Magentic orchestration event/request types. It would be useful to audit all built-in types that can cross a checkpoint boundary and ensure they are registered consistently.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Aug 20, 2026
  2. z2Ace0107 commented on Aug 20, 2026

    @z2Ace0107

    I can investigate this issue and prepare a focused regression fix, subject to maintainer guidance on the registration boundary.

    From the current main branch, FileCheckpointStorage passes an allowlist to the restricted checkpoint decoder, while the GroupChat envelope types live under the agent_framework_orchestrations.* namespace. The decoder currently auto-allows agent_framework.* types, which appears to explain why these framework-owned messages are rejected during restore.

    My initial plan would be:

    • Add a deterministic file-checkpoint save/load regression test for the three GroupChat envelope types.
    • Keep user-provided allowed_checkpoint_types behavior unchanged.
    • If appropriate, register the framework-owned GroupChat checkpoint types through the existing register_checkpoint_type mechanism when the orchestration package is loaded.

    Before I start, could you confirm whether the orchestration package should register these checkpoint-safe types, or whether you prefer another mechanism? Should Handoff and Magentic checkpoint payloads be handled separately?

    I’m happy to take this issue if that direction is acceptable.

  3. atty57 commented on Aug 20, 2026

    @atty57
    Contributor

    Confirmed on main and opened a draft PR for this: #7791. Ace (@z2Ace0107) — apologies, I had this branched before your comment landed; happy to close mine if you'd rather take it, and either way the notes below should be useful.

    The cause is the module-prefix rule in the restricted checkpoint unpickler. _checkpoint_encoding.py auto-allows anything under _FRAMEWORK_MODULE_PREFIX = "agent_framework." (with the trailing dot), so agent_framework_orchestrations — a sibling distribution, not a submodule — falls through to the generic "blocked type" branch, which is why these read as user types.

    Minimal repro without a workflow or storage backend:

    from agent_framework import Message
    from agent_framework._workflows._checkpoint_encoding import decode_checkpoint_value, encode_checkpoint_value
    from agent_framework_orchestrations._base_group_chat_orchestrator import GroupChatParticipantMessage
    
    msg = GroupChatParticipantMessage(messages=[Message(role="user", contents=[])])
    decode_checkpoint_value(encode_checkpoint_value(msg), allowed_types=frozenset())

    On the audit point: alongside the three group chat envelopes, the other orchestration types that cross a checkpoint boundary are the request_info payloads and responses — HandoffAgentUserRequest (_handoff.py:439), AgentRequestInfoResponse (_orchestration_request_info.py:101), MagenticPlanReviewRequest/MagenticPlanReviewResponse (_magentic.py:1048) along with the ledger types nested in the request, and MagenticResetSignal (_magentic.py:1271). GroupChatState, OrchestrationState, and MagenticContext are not affected — they persist through to_dict/from_dict rather than pickle.

    The PR registers that set via the existing register_checkpoint_type API at package import, so nothing in core's prefix rule changes and no other package becomes trusted. The alternative — broadening the core prefix to cover the whole agent_framework_* family — would fix every first-party package at once but also auto-trusts any installed distribution using that module name, so it seemed like a maintainer call rather than something to fold into this fix.

  4. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Aug 21, 2026
  5. github-actions commented on Aug 21, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: restricted restore fails in python/packages/core/agent_framework/_workflows/_checkpoint_encoding.py::_RestrictedUnpickler.find_class for the three envelope classes defined in python/packages/orchestrations/agent_framework_orchestrations/_base_group_chat_orchestrator.py. Minimal repro: encode each group-chat envelope and call decode_checkpoint_value(encoded, allowed_types=frozenset()); all three raise WorkflowCheckpointException because their agent_framework_orchestrations.* types are blocked.

    • Failing test: python/packages/orchestrations/tests/test_group_chat_checkpoint_restore.py
    • Files examined: python/packages/core/agent_framework/_workflows/_checkpoint_encoding.py, python/packages/orchestrations/agent_framework_orchestrations/_base_group_chat_orchestrator.py, python/packages/orchestrations/agent_framework_orchestrations/init.py, python/packages/core/tests/workflow/test_checkpoint_unrestricted_pickle.py, python/packages/orchestrations/pyproject.toml
    • Tests run: python/packages/orchestrations/tests/test_group_chat_checkpoint_restore.py
    • Current version: 1.1.0
  6. added
    orchestrationUsage: [Issues, PRs], Target: multi-agent orchestration (high-level patterns)
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Aug 21, 2026
  7. manjunathshiva commented on Sep 10, 2026

    @manjunathshiva
    Contributor

    Opened #8258 for this. It follows the shape Atharva Vichare (@atty57) used in #7791 — registering the
    framework-owned types via the public register_checkpoint_type — which was closed on 2026-09-04 as
    a stale draft rather than on approach, and it addresses the Copilot comment left open there.
    Ace (@z2Ace0107), you offered on this first on 08-20: if you have work in progress, say so and I will
    stand down rather than duplicate it.

    Two things the end-to-end repro turned up that refine the issue, regardless of whose fix lands:

    • Narrower trigger. The envelopes are only used for participants that are not agents
      (_base_group_chat_orchestrator.py:434,467) — agent participants get a core
      AgentExecutorRequest, already trusted. So you need at least one custom Executor participant.
      That, plus the existing checkpoint tests using InMemoryCheckpointStorage (which deepcopys and
      never reaches the unpickler), is why this went unnoticed.
    • Worse symptom. list_checkpoints logs and skips what it cannot decode. A two-round group
      chat writes six checkpoints, lists two, and get_latest returns a stale one — quiet data loss,
      not the loud UnpicklingError above, which only surfaces on a direct load(). Same invisibility
      Oleg Solozobov (@dev404ai) reports in Python: [Bug]: get_latest returns a stale checkpoint when the newest one cannot be decoded #7831.

    The PR registers ten types, each verified against a call site, including
    MagenticProgressLedger/Item which are nested in MagenticPlanReviewRequest.current_progress.
    I deliberately did not broaden _FRAMEWORK_MODULE_PREFIX to the undotted agent_framework:
    it would fix the whole class in one line, but on a pickle allowlist it auto-trusts any installed
    distribution merely named agent_framework_*, which felt like a maintainer's security call.

    Sequencing note: once #8214 adds save-time validation this stops being silent and starts failing on
    the first checkpoint, so affected users go from degraded to blocked — may be worth landing the
    registration first.

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: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions