Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3234c6e
Prototype: Add request_info API and @response_handler
TaoChenOSU Oct 14, 2025
309ceb4
Add original_request as a parameter to the response handler
TaoChenOSU Oct 15, 2025
334016f
Prototype: request interception in sub workflows
TaoChenOSU Oct 15, 2025
a4b928d
Prototype: request interception in sub workflows 2
TaoChenOSU Oct 16, 2025
598830c
WIP: Make checkpointing work
TaoChenOSU Oct 17, 2025
62e07d7
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 20, 2025
2c5f595
checkpointing with sub workflow
TaoChenOSU Oct 21, 2025
4939e46
Fix function executor
TaoChenOSU Oct 21, 2025
2767ee5
Allow sub-workflow to output directly
TaoChenOSU Oct 22, 2025
bd82c02
Remove ReqeustInfoExecutor and related classes; Debugging checkpoint_…
TaoChenOSU Oct 22, 2025
ae5463a
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 23, 2025
e5361b4
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 24, 2025
d3e8343
Fix Handoff and sample
TaoChenOSU Oct 24, 2025
dc24afa
fix pending requests in checkpoint
TaoChenOSU Oct 24, 2025
042f610
Fix unit tests
TaoChenOSU Oct 24, 2025
fdfe83d
Fix formatting
TaoChenOSU Oct 25, 2025
cf8866d
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 27, 2025
ad19795
Resolve comments
TaoChenOSU Oct 27, 2025
26c2acc
Address comment
TaoChenOSU Oct 27, 2025
6dde167
Add checkpoint tests
TaoChenOSU Oct 27, 2025
82ec03b
Add tests
TaoChenOSU Oct 27, 2025
968577f
misc
TaoChenOSU Oct 27, 2025
28d2811
fix mypy
TaoChenOSU Oct 27, 2025
ccb18c6
fix mypy
TaoChenOSU Oct 27, 2025
9830724
Use request type as part of the key
TaoChenOSU Oct 28, 2025
9caa7aa
Log warning if there is not response handler for a request
TaoChenOSU Oct 28, 2025
f6a1ccb
Update Internal edge group comments
TaoChenOSU Oct 28, 2025
4635c4d
REcord message type in executor processing span
TaoChenOSU Oct 28, 2025
b1d4b1a
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 28, 2025
476b0c7
Update sample
TaoChenOSU Oct 28, 2025
3d99a86
Merge branch 'main' into local-branch-python-request-response-redesign
TaoChenOSU Oct 29, 2025
8cd0770
Improve tests
TaoChenOSU Oct 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions python/packages/core/agent_framework/_workflows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,7 @@
StandardMagenticManager,
)
from ._orchestration_state import OrchestrationState
from ._request_info_executor import (
PendingRequestDetails,
RequestInfoExecutor,
RequestInfoMessage,
RequestResponse,
)
from ._request_info_mixin import response_handler
from ._runner import Runner
from ._runner_context import (
InProcRunnerContext,
Expand All @@ -91,7 +86,6 @@
from ._shared_state import SharedState
from ._validation import (
EdgeDuplicationError,
ExecutorDuplicationError,
GraphConnectivityError,
TypeCompatibilityError,
ValidationTypeEnum,
Expand All @@ -102,7 +96,7 @@
from ._workflow import Workflow, WorkflowRunResult
from ._workflow_builder import WorkflowBuilder
from ._workflow_context import WorkflowContext
from ._workflow_executor import WorkflowExecutor
from ._workflow_executor import SubWorkflowRequestMessage, SubWorkflowResponseMessage, WorkflowExecutor

__all__ = [
"DEFAULT_MANAGER_INSTRUCTIONS",
Expand All @@ -121,7 +115,6 @@
"EdgeDuplicationError",
"Executor",
"ExecutorCompletedEvent",
"ExecutorDuplicationError",
"ExecutorEvent",
"ExecutorFailedEvent",
"ExecutorInvokedEvent",
Expand Down Expand Up @@ -150,17 +143,15 @@
"ManagerDirectiveModel",
"Message",
"OrchestrationState",
"PendingRequestDetails",
"RequestInfoEvent",
"RequestInfoExecutor",
"RequestInfoMessage",
"RequestResponse",
"Runner",
"RunnerContext",
"SequentialBuilder",
"SharedState",
"SingleEdgeGroup",
"StandardMagenticManager",
"SubWorkflowRequestMessage",
"SubWorkflowResponseMessage",
"SwitchCaseEdgeGroup",
"SwitchCaseEdgeGroupCase",
"SwitchCaseEdgeGroupDefault",
Expand Down Expand Up @@ -189,5 +180,6 @@
"executor",
"get_checkpoint_summary",
"handler",
"response_handler",
"validate_workflow_graph",
]
18 changes: 5 additions & 13 deletions python/packages/core/agent_framework/_workflows/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,7 @@ from ._magentic import (
StandardMagenticManager,
)
from ._orchestration_state import OrchestrationState
from ._request_info_executor import (
PendingRequestDetails,
RequestInfoExecutor,
RequestInfoMessage,
RequestResponse,
)
from ._request_info_mixin import response_handler
from ._runner import Runner
from ._runner_context import (
InProcRunnerContext,
Expand All @@ -88,7 +83,6 @@ from ._sequential import SequentialBuilder
from ._shared_state import SharedState
from ._validation import (
EdgeDuplicationError,
ExecutorDuplicationError,
GraphConnectivityError,
TypeCompatibilityError,
ValidationTypeEnum,
Expand All @@ -99,7 +93,7 @@ from ._viz import WorkflowViz
from ._workflow import Workflow, WorkflowRunResult
from ._workflow_builder import WorkflowBuilder
from ._workflow_context import WorkflowContext
from ._workflow_executor import WorkflowExecutor
from ._workflow_executor import SubWorkflowRequestMessage, SubWorkflowResponseMessage, WorkflowExecutor

__all__ = [
"DEFAULT_MANAGER_INSTRUCTIONS",
Expand All @@ -118,7 +112,6 @@ __all__ = [
"EdgeDuplicationError",
"Executor",
"ExecutorCompletedEvent",
"ExecutorDuplicationError",
"ExecutorEvent",
"ExecutorFailedEvent",
"ExecutorInvokedEvent",
Expand Down Expand Up @@ -146,17 +139,15 @@ __all__ = [
"MagenticPlanReviewRequest",
"Message",
"OrchestrationState",
"PendingRequestDetails",
"RequestInfoEvent",
"RequestInfoExecutor",
"RequestInfoMessage",
"RequestResponse",
"Runner",
"RunnerContext",
"SequentialBuilder",
"SharedState",
"SingleEdgeGroup",
"StandardMagenticManager",
"SubWorkflowRequestMessage",
"SubWorkflowResponseMessage",
"SwitchCaseEdgeGroup",
"SwitchCaseEdgeGroupCase",
"SwitchCaseEdgeGroupDefault",
Expand Down Expand Up @@ -185,5 +176,6 @@ __all__ = [
"executor",
"get_checkpoint_summary",
"handler",
"response_handler",
"validate_workflow_graph",
]
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class WorkflowCheckpoint:
# Core workflow state
messages: dict[str, list[dict[str, Any]]] = field(default_factory=dict) # type: ignore[misc]
shared_state: dict[str, Any] = field(default_factory=dict) # type: ignore[misc]
pending_request_info_events: dict[str, dict[str, Any]] = field(default_factory=dict) # type: ignore[misc]

# Runtime state
iteration_count: int = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
_MAX_ENCODE_DEPTH = 100
_CYCLE_SENTINEL = "<cycle>"


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -75,7 +74,7 @@ def _enc(v: Any, stack: set[int], depth: int) -> Any:
# type(v) already narrows sufficiently; cast was redundant
dc_cls: type[Any] = type(v)
field_values: dict[str, Any] = {}
for f in fields(v): # type: ignore[arg-type]
for f in fields(v):
field_values[f.name] = _enc(getattr(v, f.name), stack, depth + 1)
return {
DATACLASS_MARKER: f"{dc_cls.__module__}:{dc_cls.__name__}",
Expand Down Expand Up @@ -189,6 +188,35 @@ def decode_checkpoint_value(value: Any) -> Any:
return value


def _supports_model_protocol(obj: object) -> bool:
"""Detect objects that expose dictionary serialization hooks."""
try:
obj_type: type[Any] = type(obj)
except Exception:
return False

has_to_dict = hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict", None)) # type: ignore[arg-type]
has_from_dict = hasattr(obj_type, "from_dict") and callable(getattr(obj_type, "from_dict", None))

has_to_json = hasattr(obj, "to_json") and callable(getattr(obj, "to_json", None)) # type: ignore[arg-type]
has_from_json = hasattr(obj_type, "from_json") and callable(getattr(obj_type, "from_json", None))

return (has_to_dict and has_from_dict) or (has_to_json and has_from_json)


def _import_qualified_name(qualname: str) -> type[Any] | None:
if ":" not in qualname:
return None
module_name, class_name = qualname.split(":", 1)
module = sys.modules.get(module_name)
if module is None:
module = importlib.import_module(module_name)
attr: Any = module
for part in class_name.split("."):
attr = getattr(attr, part)
return attr if isinstance(attr, type) else None


def _instantiate_checkpoint_dataclass(cls: type[Any], payload: Any) -> Any | None:
if not isinstance(cls, type):
logger.debug(f"Checkpoint decoder received non-type dataclass reference: {cls!r}")
Expand Down Expand Up @@ -220,32 +248,3 @@ def _instantiate_checkpoint_dataclass(cls: type[Any], payload: Any) -> Any | Non
except Exception as exc:
logger.warning(f"Checkpoint decoder encountered unexpected error calling {cls.__name__}({payload!r}): {exc}")
return None


def _supports_model_protocol(obj: object) -> bool:
"""Detect objects that expose dictionary serialization hooks."""
try:
obj_type: type[Any] = type(obj)
except Exception:
return False

has_to_dict = hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict", None)) # type: ignore[arg-type]
has_from_dict = hasattr(obj_type, "from_dict") and callable(getattr(obj_type, "from_dict", None))

has_to_json = hasattr(obj, "to_json") and callable(getattr(obj, "to_json", None)) # type: ignore[arg-type]
has_from_json = hasattr(obj_type, "from_json") and callable(getattr(obj_type, "from_json", None))

return (has_to_dict and has_from_dict) or (has_to_json and has_from_json)


def _import_qualified_name(qualname: str) -> type[Any] | None:
if ":" not in qualname:
return None
module_name, class_name = qualname.split(":", 1)
module = sys.modules.get(module_name)
if module is None:
module = importlib.import_module(module_name)
attr: Any = module
for part in class_name.split("."):
attr = getattr(attr, part)
return attr if isinstance(attr, type) else None
Loading