diff --git a/agentic_ai/agents/agent_framework/STATE_MANAGEMENT.md b/agentic_ai/agents/agent_framework/STATE_MANAGEMENT.md index f58c4be8b..c4b1d2923 100644 --- a/agentic_ai/agents/agent_framework/STATE_MANAGEMENT.md +++ b/agentic_ai/agents/agent_framework/STATE_MANAGEMENT.md @@ -408,7 +408,7 @@ class SessionMemoryCheckpointStorage(CheckpointStorage): 2. **Team agent** - `MagenticOrchestratorExecutor` automatically snapshots each participant’s `chat_history`. - - Checkpoints include outstanding tool requests (`RequestInfoExecutor` state). + - Checkpoints include outstanding tool requests and plan-review state managed by the orchestrator via `WorkflowEvent(type="request_info")`. - Ensure all custom executors implement `restore_state` to interpret snapshots after schema changes. 3. **Human-in-the-loop** diff --git a/agentic_ai/agents/agent_framework/multi_agent/MAGENTIC_README.md b/agentic_ai/agents/agent_framework/multi_agent/MAGENTIC_README.md index a6641d92c..5f997c725 100644 --- a/agentic_ai/agents/agent_framework/multi_agent/MAGENTIC_README.md +++ b/agentic_ai/agents/agent_framework/multi_agent/MAGENTIC_README.md @@ -128,7 +128,7 @@ When stalling, the manager calls `replan()`, which uses [`ORCHESTRATOR_TASK_LEDG 1. Registers **participants** (`participants()`), each either a `BaseAgent` or another `Executor`. 2. Configures the **manager** (`with_standard_manager()`). 3. Optionally enables **plan review**, **checkpointing**, and **unified callbacks**. -4. Builds a [`Workflow`](reference/agent-framework/python/packages/main/agent_framework/_workflow/_workflow.py) graph: orchestrator (start node), optional `RequestInfoExecutor` for plan review, and bidirectional edges to each agent executor. +4. Builds a [`Workflow`](reference/agent-framework/python/packages/main/agent_framework/_workflow/_workflow.py) graph: orchestrator (start node) with optional plan review enabled via `enable_plan_review=True`, and bidirectional edges to each agent executor. Plan review is handled internally by the orchestrator, which emits `WorkflowEvent(type="request_info")` events containing `MagenticPlanReviewRequest` data. ### 4.2 Workflow Context & State diff --git a/agentic_ai/agents/agent_framework/multi_agent/handoff_multi_domain_agent.py b/agentic_ai/agents/agent_framework/multi_agent/handoff_multi_domain_agent.py index 320d634de..fd242bcb5 100644 --- a/agentic_ai/agents/agent_framework/multi_agent/handoff_multi_domain_agent.py +++ b/agentic_ai/agents/agent_framework/multi_agent/handoff_multi_domain_agent.py @@ -286,10 +286,10 @@ async def _setup(self) -> None: has_api_key = bool(self.azure_openai_key) has_credential = bool(self.azure_credential) - if not all([self.azure_deployment, self.azure_openai_endpoint, self.api_version]): + if not all([self.azure_deployment, self.azure_openai_endpoint]): raise RuntimeError( "Azure OpenAI configuration is incomplete. Ensure " - "AZURE_OPENAI_CHAT_DEPLOYMENT, AZURE_OPENAI_ENDPOINT, and AZURE_OPENAI_API_VERSION are set." + "AZURE_OPENAI_CHAT_DEPLOYMENT and AZURE_OPENAI_ENDPOINT are set." ) if not has_api_key and not has_credential: raise RuntimeError( @@ -311,7 +311,6 @@ async def _setup(self) -> None: api_key=self.azure_openai_key, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) logger.info("[HANDOFF] Using API key authentication for Azure OpenAI") else: @@ -319,7 +318,6 @@ async def _setup(self) -> None: credential=self.azure_credential, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) logger.info("[HANDOFF] Using managed identity authentication for Azure OpenAI") @@ -340,7 +338,7 @@ async def _setup(self) -> None: description=cfg["description"], instructions=cfg["instructions"], tools=domain_tools, - default_options=ChatOptions(model_id=self.openai_model_name), + default_options=ChatOptions(model=self.openai_model_name), require_per_service_call_history_persistence=True, ) await agent.__aenter__() diff --git a/agentic_ai/agents/agent_framework/multi_agent/magentic_group.py b/agentic_ai/agents/agent_framework/multi_agent/magentic_group.py index 33e2c679d..e6e08dacb 100644 --- a/agentic_ai/agents/agent_framework/multi_agent/magentic_group.py +++ b/agentic_ai/agents/agent_framework/multi_agent/magentic_group.py @@ -295,10 +295,15 @@ async def chat_async(self, prompt: str) -> str: return cleaned_answer def _validate_configuration(self) -> None: - if not all([self.azure_openai_key, self.azure_deployment, self.azure_openai_endpoint, self.api_version]): + if not all([self.azure_deployment, self.azure_openai_endpoint]): raise RuntimeError( - "Azure OpenAI configuration is incomplete. Ensure AZURE_OPENAI_API_KEY, " - "AZURE_OPENAI_CHAT_DEPLOYMENT, AZURE_OPENAI_ENDPOINT, and AZURE_OPENAI_API_VERSION are set." + "Azure OpenAI configuration is incomplete. Ensure AZURE_OPENAI_CHAT_DEPLOYMENT " + "and AZURE_OPENAI_ENDPOINT are set." + ) + if not self.azure_openai_key and not getattr(self, "azure_credential", None): + raise RuntimeError( + "Azure OpenAI authentication is not configured. Set AZURE_OPENAI_API_KEY " + "or provide a managed-identity credential." ) def _build_headers(self) -> Dict[str, str]: @@ -376,7 +381,6 @@ def _build_chat_client(self) -> OpenAIChatClient: api_key=self.azure_openai_key, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) elif self.azure_credential: logger.info("[AgentFramework-Magentic] Using managed identity authentication for Azure OpenAI") @@ -384,7 +388,6 @@ def _build_chat_client(self) -> OpenAIChatClient: credential=self.azure_credential, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) else: raise RuntimeError( @@ -579,7 +582,7 @@ async def _create_participants( agent_kwargs: Dict[str, Any] = { **defaults, "client": participant_client, - "default_options": ChatOptions(model_id=self.openai_model_name), + "default_options": ChatOptions(model=self.openai_model_name), } # Apply tool filtering for this participant's domain diff --git a/agentic_ai/agents/agent_framework/multi_agent/reflection_agent.py b/agentic_ai/agents/agent_framework/multi_agent/reflection_agent.py index 394e199db..e7cb1a773 100644 --- a/agentic_ai/agents/agent_framework/multi_agent/reflection_agent.py +++ b/agentic_ai/agents/agent_framework/multi_agent/reflection_agent.py @@ -80,7 +80,7 @@ async def _setup_agents(self) -> None: return # Validate configuration - if not all([self.azure_deployment, self.azure_openai_endpoint, self.api_version]): + if not all([self.azure_deployment, self.azure_openai_endpoint]): raise RuntimeError("Azure OpenAI configuration incomplete.") if not self.azure_openai_key and not self.azure_credential: @@ -90,7 +90,6 @@ async def _setup_agents(self) -> None: client_kwargs = { "model": self.azure_deployment, "azure_endpoint": self.azure_openai_endpoint, - "api_version": self.api_version, } if self.azure_openai_key: client_kwargs["api_key"] = self.azure_openai_key @@ -108,7 +107,7 @@ async def _setup_agents(self) -> None: name="PrimaryAgent", instructions=PRIMARY_AGENT_INSTRUCTIONS, tools=tools, - default_options=ChatOptions(model_id=self.openai_model_name), + default_options=ChatOptions(model=self.openai_model_name), ) self._reviewer = FrameworkAgent( @@ -116,7 +115,7 @@ async def _setup_agents(self) -> None: name="Reviewer", instructions=REVIEWER_INSTRUCTIONS, tools=tools, - default_options=ChatOptions(model_id=self.openai_model_name), + default_options=ChatOptions(model=self.openai_model_name), ) # Initialize agents diff --git a/agentic_ai/agents/agent_framework/single_agent.py b/agentic_ai/agents/agent_framework/single_agent.py index a9917754c..0076a1f81 100644 --- a/agentic_ai/agents/agent_framework/single_agent.py +++ b/agentic_ai/agents/agent_framework/single_agent.py @@ -38,10 +38,10 @@ async def _setup_single_agent(self) -> None: has_api_key = bool(self.azure_openai_key) has_credential = bool(self.azure_credential) - if not all([self.azure_deployment, self.azure_openai_endpoint, self.api_version]): + if not all([self.azure_deployment, self.azure_openai_endpoint]): raise RuntimeError( "Azure OpenAI configuration is incomplete. Ensure " - "AZURE_OPENAI_CHAT_DEPLOYMENT, AZURE_OPENAI_ENDPOINT, and AZURE_OPENAI_API_VERSION are set." + "AZURE_OPENAI_CHAT_DEPLOYMENT and AZURE_OPENAI_ENDPOINT are set." ) if not has_api_key and not has_credential: @@ -59,7 +59,6 @@ async def _setup_single_agent(self) -> None: api_key=self.azure_openai_key, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) logger.info("[AgentFramework] Using API key authentication for Azure OpenAI") else: @@ -67,7 +66,6 @@ async def _setup_single_agent(self) -> None: credential=self.azure_credential, model=self.azure_deployment, azure_endpoint=self.azure_openai_endpoint, - api_version=self.api_version, ) logger.info("[AgentFramework] Using managed identity authentication for Azure OpenAI") @@ -85,7 +83,7 @@ async def _setup_single_agent(self) -> None: name="ai_assistant", instructions=instructions, tools=tools, - default_options=ChatOptions(model_id=self.openai_model_name), + default_options=ChatOptions(model=self.openai_model_name), ) try: diff --git a/infra/terraform/_aca-be.tf b/infra/terraform/_aca-be.tf index 641d36d9b..6375d0bc9 100644 --- a/infra/terraform/_aca-be.tf +++ b/infra/terraform/_aca-be.tf @@ -85,11 +85,6 @@ resource "azurerm_container_app" "backend" { value = local.openai_endpoint } - env { - name = "AZURE_OPENAI_API_VERSION" - value = var.openai_api_version - } - env { name = "AZURE_OPENAI_EMBEDDING_DEPLOYMENT" value = var.openai_embedding_deployment_name diff --git a/infra/terraform/dev.tfvars b/infra/terraform/dev.tfvars index 48046bccc..93f1ccfbd 100644 --- a/infra/terraform/dev.tfvars +++ b/infra/terraform/dev.tfvars @@ -14,7 +14,6 @@ create_openai_deployment = true openai_deployment_name = "gpt-5.2-chat" openai_model_name = "gpt-5.2-chat" openai_model_version = "2025-12-11" -openai_api_version ="2025-04-01-preview" openai_deployment_capacity = 200 # 200k tokens/minute - needed for agent evaluation # OpenAI embedding deployment configuration diff --git a/infra/terraform/prod.tfvars b/infra/terraform/prod.tfvars index 8ee8b17d5..61f201161 100644 --- a/infra/terraform/prod.tfvars +++ b/infra/terraform/prod.tfvars @@ -14,7 +14,6 @@ create_openai_deployment = true openai_deployment_name = "gpt-5.2-chat" openai_model_name = "gpt-5.2-chat" openai_model_version = "2025-12-11" -openai_api_version = "2025-04-01-preview" openai_deployment_capacity = 200 # 200k tokens/minute # OpenAI embedding deployment configuration diff --git a/infra/terraform/variables.tf b/infra/terraform/variables.tf index 31c8aca54..880095ea6 100644 --- a/infra/terraform/variables.tf +++ b/infra/terraform/variables.tf @@ -41,11 +41,6 @@ variable "openai_model_version" { type = string default = "2025-12-11" } -variable "openai_api_version" { - description = "OpenAI API version" - type = string - default = "2025-04-01-preview" -} variable "openai_deployment_capacity" { description = "Capacity (TPM in thousands) for OpenAI deployment" type = number diff --git a/tests/test_agent_framework_1_2_1_regression.py b/tests/test_agent_framework_1_2_1_regression.py index 2b1af5111..491341321 100644 --- a/tests/test_agent_framework_1_2_1_regression.py +++ b/tests/test_agent_framework_1_2_1_regression.py @@ -149,11 +149,25 @@ def test_framework_agent_constructor_signature(self): # description was wired through in 1.2.x and is consumed by HandoffBuilder assert 'description' in params - def test_chat_options_model_id(self): - """ChatOptions accepts model_id for specifying the model.""" + def test_chat_options_model(self): + """ChatOptions exposes ``model`` (not ``model_id``) in 1.2.x. + + Regression for the CI failure where agents constructed + ``ChatOptions(model_id=...)``. ``ChatOptions`` is a ``TypedDict`` with + ``total=False``, so unknown keys are silently accepted at construction + time and only blow up later when forwarded as kwargs to the OpenAI + ``responses.create`` call (``TypeError: unexpected keyword argument + 'model_id'``). Assert against ``__annotations__`` so the test fails + loudly if the field name changes again. + """ from agent_framework import ChatOptions - opts = ChatOptions(model_id="gpt-4o") - assert opts["model_id"] == "gpt-4o" + opts = ChatOptions(model="gpt-4o") + assert opts["model"] == "gpt-4o" + assert "model" in ChatOptions.__annotations__ + assert "model_id" not in ChatOptions.__annotations__, ( + "ChatOptions field is `model` in agent-framework 1.2.x; " + "passing model_id= silently constructs a bad dict that fails downstream." + ) def test_openai_client_constructor_supports_azure_kwargs(self): """OpenAIChatClient accepts model, api_key, credential, azure_endpoint, api_version."""