agent-framework-core 1.1.1__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/PKG-INFO +1 -1
  2. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/__init__.py +16 -0
  3. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_feature_stage.py +1 -0
  4. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_telemetry.py +57 -22
  5. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_events.py +7 -0
  6. agent_framework_core-1.2.0/agent_framework/_workflows/_functional.py +1551 -0
  7. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_workflow.py +5 -5
  8. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/a2a/__init__.py +2 -1
  9. agent_framework_core-1.2.0/agent_framework/a2a/__init__.pyi +5 -0
  10. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/foundry/__init__.py +1 -0
  11. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/github/__init__.py +2 -0
  12. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/github/__init__.pyi +2 -0
  13. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/pyproject.toml +1 -1
  14. agent_framework_core-1.1.1/agent_framework/a2a/__init__.pyi +0 -9
  15. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/LICENSE +0 -0
  16. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/README.md +0 -0
  17. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_agents.py +0 -0
  18. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_clients.py +0 -0
  19. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_compaction.py +0 -0
  20. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_docstrings.py +0 -0
  21. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_evaluation.py +0 -0
  22. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_mcp.py +0 -0
  23. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_middleware.py +0 -0
  24. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_serialization.py +0 -0
  25. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_sessions.py +0 -0
  26. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_settings.py +0 -0
  27. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_skills.py +0 -0
  28. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_tools.py +0 -0
  29. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_types.py +0 -0
  30. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/__init__.py +0 -0
  31. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_agent.py +0 -0
  32. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_agent_executor.py +0 -0
  33. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_agent_utils.py +0 -0
  34. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_checkpoint.py +0 -0
  35. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_checkpoint_encoding.py +0 -0
  36. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_const.py +0 -0
  37. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_conversation_history.py +0 -0
  38. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_edge.py +0 -0
  39. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_edge_runner.py +0 -0
  40. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_executor.py +0 -0
  41. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_function_executor.py +0 -0
  42. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_message_utils.py +0 -0
  43. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_model_utils.py +0 -0
  44. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_request_info_mixin.py +0 -0
  45. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_runner.py +0 -0
  46. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_runner_context.py +0 -0
  47. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_state.py +0 -0
  48. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_typing_utils.py +0 -0
  49. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_validation.py +0 -0
  50. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_viz.py +0 -0
  51. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_workflow_builder.py +0 -0
  52. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_workflow_context.py +0 -0
  53. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/_workflows/_workflow_executor.py +0 -0
  54. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/ag_ui/__init__.py +0 -0
  55. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/ag_ui/__init__.pyi +0 -0
  56. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/amazon/__init__.py +0 -0
  57. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/amazon/__init__.pyi +0 -0
  58. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/anthropic/__init__.py +0 -0
  59. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/anthropic/__init__.pyi +0 -0
  60. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/azure/__init__.py +0 -0
  61. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/azure/__init__.pyi +0 -0
  62. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/chatkit/__init__.py +0 -0
  63. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/chatkit/__init__.pyi +0 -0
  64. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/declarative/__init__.py +0 -0
  65. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/declarative/__init__.pyi +0 -0
  66. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/devui/__init__.py +0 -0
  67. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/devui/__init__.pyi +0 -0
  68. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/exceptions.py +0 -0
  69. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/foundry/__init__.pyi +0 -0
  70. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/google/__init__.py +0 -0
  71. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/google/__init__.pyi +0 -0
  72. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/lab/__init__.py +0 -0
  73. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/mem0/__init__.py +0 -0
  74. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/mem0/__init__.pyi +0 -0
  75. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/microsoft/__init__.py +0 -0
  76. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/microsoft/__init__.pyi +0 -0
  77. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/observability.py +0 -0
  78. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/ollama/__init__.py +0 -0
  79. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/ollama/__init__.pyi +0 -0
  80. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/openai/__init__.py +0 -0
  81. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/openai/__init__.pyi +0 -0
  82. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/orchestrations/__init__.py +0 -0
  83. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/orchestrations/__init__.pyi +0 -0
  84. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/py.typed +0 -0
  85. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/redis/__init__.py +0 -0
  86. {agent_framework_core-1.1.1 → agent_framework_core-1.2.0}/agent_framework/redis/__init__.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-framework-core
3
- Version: 1.1.1
3
+ Version: 1.2.0
4
4
  Summary: Microsoft Agent Framework for building AI Agents with Python. This is the core package that has all the core abstractions and implementations.
5
5
  Author-email: Microsoft <af-support@microsoft.com>
6
6
  Requires-Python: >=3.10
@@ -213,6 +213,15 @@ from ._workflows._executor import (
213
213
  handler,
214
214
  )
215
215
  from ._workflows._function_executor import FunctionExecutor, executor
216
+ from ._workflows._functional import (
217
+ FunctionalWorkflow,
218
+ FunctionalWorkflowAgent,
219
+ RunContext,
220
+ StepWrapper,
221
+ get_run_context,
222
+ step,
223
+ workflow,
224
+ )
216
225
  from ._workflows._request_info_mixin import response_handler
217
226
  from ._workflows._runner import Runner
218
227
  from ._workflows._runner_context import (
@@ -332,6 +341,8 @@ __all__ = [
332
341
  "FunctionMiddleware",
333
342
  "FunctionMiddlewareTypes",
334
343
  "FunctionTool",
344
+ "FunctionalWorkflow",
345
+ "FunctionalWorkflowAgent",
335
346
  "GeneratedEmbeddings",
336
347
  "GraphConnectivityError",
337
348
  "HistoryProvider",
@@ -354,6 +365,7 @@ __all__ = [
354
365
  "ResponseStream",
355
366
  "Role",
356
367
  "RoleLiteral",
368
+ "RunContext",
357
369
  "Runner",
358
370
  "RunnerContext",
359
371
  "SecretString",
@@ -366,6 +378,7 @@ __all__ = [
366
378
  "SkillScriptRunner",
367
379
  "SkillsProvider",
368
380
  "SlidingWindowStrategy",
381
+ "StepWrapper",
369
382
  "SubWorkflowRequestMessage",
370
383
  "SubWorkflowResponseMessage",
371
384
  "SummarizationStrategy",
@@ -424,6 +437,7 @@ __all__ = [
424
437
  "evaluator",
425
438
  "executor",
426
439
  "function_middleware",
440
+ "get_run_context",
427
441
  "handler",
428
442
  "included_messages",
429
443
  "included_token_count",
@@ -439,6 +453,7 @@ __all__ = [
439
453
  "register_state_type",
440
454
  "resolve_agent_id",
441
455
  "response_handler",
456
+ "step",
442
457
  "tool",
443
458
  "tool_call_args_match",
444
459
  "tool_called_check",
@@ -447,4 +462,5 @@ __all__ = [
447
462
  "validate_tool_mode",
448
463
  "validate_tools",
449
464
  "validate_workflow_graph",
465
+ "workflow",
450
466
  ]
@@ -48,6 +48,7 @@ class ExperimentalFeature(str, Enum):
48
48
 
49
49
  EVALS = "EVALS"
50
50
  FILE_HISTORY = "FILE_HISTORY"
51
+ FUNCTIONAL_WORKFLOWS = "FUNCTIONAL_WORKFLOWS"
51
52
  SKILLS = "SKILLS"
52
53
  TOOLBOXES = "TOOLBOXES"
53
54
 
@@ -2,11 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import contextlib
5
6
  import logging
6
7
  import os
7
- from collections.abc import Generator
8
- from contextlib import contextmanager
9
- from contextvars import ContextVar
10
8
  from typing import Any, Final
11
9
 
12
10
  from . import __version__ as version_info
@@ -29,34 +27,71 @@ USER_AGENT_KEY: Final[str] = "User-Agent"
29
27
  HTTP_USER_AGENT: Final[str] = "agent-framework-python"
30
28
  AGENT_FRAMEWORK_USER_AGENT = f"{HTTP_USER_AGENT}/{version_info}" # type: ignore[has-type]
31
29
 
32
- _user_agent_prefixes: ContextVar[tuple[str, ...]] = ContextVar("_user_agent_prefixes", default=())
30
+ # This environment variable is reserved by the Foundry hosting environment to
31
+ # indicate that the agent is running in a hosted environment.
32
+ _FOUNDRY_HOSTING_ENV_VAR = "FOUNDRY_HOSTING_ENVIRONMENT"
33
+ # This prefix is added to the user agent string when the agent is running in a hosted environment.
34
+ _HOSTED_USER_AGENT_PREFIX = "foundry-hosting"
33
35
 
36
+ _user_agent_prefixes: set[str] = set()
37
+ _hosted_env_detected: bool = False
34
38
 
35
- @contextmanager
36
- def user_agent_prefix(prefix: str) -> Generator[None]:
37
- """Context manager that adds a prefix to the user agent string for the current scope.
38
39
 
39
- This is useful for upstream layers that want to identify themselves in telemetry
40
- for the duration of a request without permanently mutating global state.
40
+ def _add_user_agent_prefix(prefix: str) -> None:
41
+ """Permanently add a prefix to the user agent string.
42
+
43
+ This is used by hosting layers to identify themselves in telemetry.
44
+ Once added, the prefix applies to all subsequent user agent strings.
41
45
 
42
46
  Args:
43
47
  prefix: The prefix to add (e.g. "foundry-hosting").
44
48
  """
45
- current = _user_agent_prefixes.get()
46
- token = _user_agent_prefixes.set((*current, prefix)) if prefix and prefix not in current else None
47
- try:
48
- yield
49
- finally:
50
- if token is not None:
51
- _user_agent_prefixes.reset(token)
49
+ if prefix:
50
+ _user_agent_prefixes.add(prefix)
51
+
52
+
53
+ def _detect_hosted_environment() -> None:
54
+ """Detect if running in a hosted environment and add the user agent prefix.
52
55
 
56
+ Checks the ``FOUNDRY_HOSTING_ENVIRONMENT`` env var first, then falls back
57
+ to checking whether the agent server SDK is installed (via
58
+ ``importlib.util.find_spec``) before importing it, to avoid unnecessary
59
+ import overhead for non-hosted scenarios.
60
+ """
61
+ global _hosted_env_detected
62
+ if _hosted_env_detected:
63
+ return
64
+
65
+ if (env_value := os.environ.get(_FOUNDRY_HOSTING_ENV_VAR)) is not None:
66
+ # Env var exists — trust its value and skip the fallback.
67
+ if env_value:
68
+ _add_user_agent_prefix(_HOSTED_USER_AGENT_PREFIX)
69
+ _hosted_env_detected = True
70
+ return
53
71
 
54
- def _get_user_agent() -> str:
55
- """Return the full user agent string including any context-scoped prefixes."""
56
- prefixes = _user_agent_prefixes.get()
57
- if not prefixes:
72
+ # Env var not set — fall back to AgentConfig as a second layer of defense.
73
+ # Use find_spec to avoid the cost of a full import when the SDK is not installed.
74
+ import importlib.util
75
+
76
+ try:
77
+ if importlib.util.find_spec("azure.ai.agentserver.core") is None:
78
+ return
79
+ except (ModuleNotFoundError, ValueError):
80
+ return
81
+ with contextlib.suppress(ImportError, AttributeError):
82
+ from azure.ai.agentserver.core import AgentConfig # pyright: ignore[reportMissingImports]
83
+
84
+ if AgentConfig.from_env().is_hosted:
85
+ _add_user_agent_prefix(_HOSTED_USER_AGENT_PREFIX)
86
+ _hosted_env_detected = True
87
+
88
+
89
+ def get_user_agent() -> str:
90
+ """Return the full user agent string including any registered prefixes."""
91
+ _detect_hosted_environment()
92
+ if not _user_agent_prefixes:
58
93
  return AGENT_FRAMEWORK_USER_AGENT
59
- return f"{'/'.join(prefixes)}/{AGENT_FRAMEWORK_USER_AGENT}"
94
+ return f"{'/'.join(sorted(_user_agent_prefixes))}/{AGENT_FRAMEWORK_USER_AGENT}"
60
95
 
61
96
 
62
97
  def prepend_agent_framework_to_user_agent(headers: dict[str, Any] | None = None) -> dict[str, Any]:
@@ -89,7 +124,7 @@ def prepend_agent_framework_to_user_agent(headers: dict[str, Any] | None = None)
89
124
  """
90
125
  if not IS_TELEMETRY_ENABLED:
91
126
  return headers or {}
92
- user_agent = _get_user_agent()
127
+ user_agent = get_user_agent()
93
128
  if not headers:
94
129
  return {USER_AGENT_KEY: user_agent}
95
130
  headers[USER_AGENT_KEY] = f"{user_agent} {headers[USER_AGENT_KEY]}" if USER_AGENT_KEY in headers else user_agent
@@ -120,6 +120,7 @@ WorkflowEventType = Literal[
120
120
  "executor_invoked", # Executor handler was called (use .executor_id, .data)
121
121
  "executor_completed", # Executor handler completed (use .executor_id, .data)
122
122
  "executor_failed", # Executor handler raised error (use .executor_id, .details)
123
+ "executor_bypassed", # Executor skipped via cache hit during replay (use .executor_id, .data)
123
124
  # Orchestration event types (use .data for typed payload)
124
125
  "group_chat", # Group chat orchestrator events (use .data as GroupChatRequestSentEvent | GroupChatResponseReceivedEvent) # noqa: E501
125
126
  "handoff_sent", # Handoff routing events (use .data as HandoffSentEvent)
@@ -148,6 +149,7 @@ class WorkflowEvent(Generic[DataT]):
148
149
  - `WorkflowEvent.executor_invoked(executor_id)` - executor handler called
149
150
  - `WorkflowEvent.executor_completed(executor_id)` - executor handler completed
150
151
  - `WorkflowEvent.executor_failed(executor_id, details)` - executor handler failed
152
+ - `WorkflowEvent.executor_bypassed(executor_id)` - executor skipped via cache hit
151
153
 
152
154
  The generic parameter DataT represents the type of the event's data payload:
153
155
  - Lifecycle events: `WorkflowEvent[None]` (data is None)
@@ -318,6 +320,11 @@ class WorkflowEvent(Generic[DataT]):
318
320
  """Create an 'executor_failed' event when an executor handler raises an error."""
319
321
  return WorkflowEvent("executor_failed", executor_id=executor_id, data=details, details=details)
320
322
 
323
+ @classmethod
324
+ def executor_bypassed(cls, executor_id: str, data: DataT | None = None) -> WorkflowEvent[DataT]:
325
+ """Create an 'executor_bypassed' event when a step is skipped via cache hit during replay."""
326
+ return cls("executor_bypassed", executor_id=executor_id, data=data)
327
+
321
328
  # ==========================================================================
322
329
  # Property for type-safe access
323
330
  # ==========================================================================