Repository navigation
Description
Observed Behavior
A declarative workflow that uses FileCheckpointStorage (or any storage that decodes through the restricted checkpoint unpickler, such as CosmosCheckpointStorage) saves only its first checkpoint. Every later checkpoint fails with:
Failed to create checkpoint at iteration 1: Failed to decode pickled checkpoint data: Checkpoint deserialization blocked for type 'agent_framework_declarative._workflows._declarative_base:ActionComplete'. ...
Note that this does not fail the workflow run.
The run itself continues, so nothing raises. But the checkpoint taken while the workflow waits for input is never stored, so a paused workflow can't be resumed from storage. Restoring the latest checkpoint returns the iteration-0 one, and sending the response then fails with ValueError: Response provided for unknown request ID.
The cause is the same one #8258 fixed for orchestrations. The restricted unpickler trusts the agent_framework. and agent_framework_orchestrations. prefixes, but not agent_framework_declarative. Every declarative executor sends ActionComplete / ActionTrigger envelopes, and pauses checkpoint ExternalInputRequest, ToolApprovalRequest and the other request types from this package.
The only workaround today is to pass framework-internal module paths in allowed_checkpoint_types. test_workflow_run_kwargs_survive_file_checkpoint_restore in packages/declarative/tests/test_graph_executors.py does exactly that. samples/03-workflows/declarative/function_tools/main.py uses FileCheckpointStorage(TEMP_DIR) without that workaround and hits this. The WorkflowFactory docstring's checkpointing example ("With checkpointing for pause/resume support") does too, and it also passes path=, which FileCheckpointStorage doesn't accept.
Expected Behavior
Declarative workflows checkpoint and resume with FileCheckpointStorage without a user-maintained allowlist, the same way orchestrations do after #8258.
Steps to Reproduce
- Build a declarative workflow with a
RequestExternalInputaction andWorkflowFactory(checkpoint_storage=FileCheckpointStorage(dir)). - Run it until it pauses.
- Count the checkpoint files and restore the latest one into a fresh workflow.
- Send the response for the pending request.
Minimal Reproduction
import asyncio, os, tempfile
from agent_framework import FileCheckpointStorage
from agent_framework.declarative import ExternalInputResponse, WorkflowFactory
YAML = """
name: approval-flow
actions:
- kind: SetValue
path: Local.greeting
value: Hello
- kind: RequestExternalInput
id: ask
prompt: Approve?
variable: Local.answer
- kind: SendActivity
activity:
text: '=Concatenate(Local.greeting, " - answer ", Local.answer)'
"""
async def main():
with tempfile.TemporaryDirectory() as d:
storage = FileCheckpointStorage(d)
wf = WorkflowFactory(checkpoint_storage=storage).create_workflow_from_yaml(YAML)
request = (await wf.run({})).get_request_info_events()[0]
print("checkpoint files:", len([f for f in os.listdir(d) if f.endswith(".json")]))
latest = await storage.get_latest(workflow_name=wf.name)
restored = WorkflowFactory(checkpoint_storage=storage).create_workflow_from_yaml(YAML)
await restored.run(checkpoint_id=latest.checkpoint_id)
result = await restored.run(responses={request.request_id: ExternalInputResponse(user_input="yes")})
print(result.get_outputs())
asyncio.run(main())Error Messages and Stack Traces
WARNING Failed to create checkpoint at iteration 1: Failed to decode pickled checkpoint data: Checkpoint deserialization blocked for type 'agent_framework_declarative._workflows._declarative_base:ActionComplete'. ...
WARNING Failed to create checkpoint at iteration 2: ...
WARNING Failed to create checkpoint at iteration 3: ...
checkpoint files: 1
ValueError: Response provided for unknown request ID: cc60e75d-...
With the declarative types allowed, the same script writes 4 checkpoints and prints ['Hello - answer yes'].
Package Versions
agent-framework-declarative: 1.4.1; main at dc6617a
Python Version
Python 3.13
Operating System
macOS
Regression
Unknown
Additional Context
Proposed fix, mirroring #8258: register the framework-owned declarative types that cross a checkpoint boundary through the public register_checkpoint_type when agent_framework_declarative is imported. These are the executor message envelopes (ActionTrigger, ActionComplete, ConditionResult, LoopIterationResult, LoopControl); the request_info payloads and responses (ExternalInputRequest/Response, AgentExternalInputRequest/Response, ToolApprovalRequest/Response, MCPToolApprovalRequest); and ExternalLoopState, which is kept in workflow state while an agent's external input loop is paused. This keeps the core prefix allowlist unchanged. I have a PR ready and will link it here.
Metadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
1aifanatic commentedon Nov 4, 2026
PR with the proposed fix and tests: #10076
github-actions commentedon Nov 4, 2026
🤖 Automated triage reproduction notes (agent-authored — trust but verify)
Agent analysis
Repro: declarative checkpoint integration in
python/packages/declarative/agent_framework_declarative/_workflows/__init__.pydoes not register its framework-owned payload types, so_RestrictedUnpickler.find_classinpython/packages/core/agent_framework/_workflows/_checkpoint_encoding.py:328rejectsActionCompleteandExternalInputRequest. Triggering a declarativeRequestExternalInputworkflow withFileCheckpointStorageleaves only iteration 0, and restoring it causes the original response ID to be rejected. Minimal repro: create a checkpointed YAML workflow containingSetValuefollowed byRequestExternalInput, run until paused, restoreget_latest()into a fresh workflow, and submit the originalExternalInputResponse.python/packages/declarative/tests/test_issue_10074.py1.4.11.4.1