mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] changed AIFunction to FunctionTool and @ai_function to @tool (#3413)
* changed AIFunction to FunctionTool and @ai_function to @tool * test and mypy fixes * mypy fix * switch function tool to always_require * fix noop * fix github copilot imports * test fixes * fix ollama test * fixes for tests * fix tests * reverted change to always_require and extended timeout * fix test
This commit is contained in:
committed by
GitHub
Unverified
parent
15b43f2abe
commit
a7d924a7d2
@@ -45,7 +45,7 @@ Once comfortable with these, explore the rest of the samples below.
|
||||
| Workflow as Agent (Reflection Pattern) | [agents/workflow_as_agent_reflection_pattern.py](./agents/workflow_as_agent_reflection_pattern.py) | Wrap a workflow so it can behave like an agent (reflection pattern) |
|
||||
| Workflow as Agent + HITL | [agents/workflow_as_agent_human_in_the_loop.py](./agents/workflow_as_agent_human_in_the_loop.py) | Extend workflow-as-agent with human-in-the-loop capability |
|
||||
| Workflow as Agent with Thread | [agents/workflow_as_agent_with_thread.py](./agents/workflow_as_agent_with_thread.py) | Use AgentThread to maintain conversation history across workflow-as-agent invocations |
|
||||
| Workflow as Agent kwargs | [agents/workflow_as_agent_kwargs.py](./agents/workflow_as_agent_kwargs.py) | Pass custom context (data, user tokens) via kwargs through workflow.as_agent() to @ai_function tools |
|
||||
| Workflow as Agent kwargs | [agents/workflow_as_agent_kwargs.py](./agents/workflow_as_agent_kwargs.py) | Pass custom context (data, user tokens) via kwargs through workflow.as_agent() to @tool functions |
|
||||
| Handoff Workflow as Agent | [agents/handoff_workflow_as_agent.py](./agents/handoff_workflow_as_agent.py) | Use a HandoffBuilder workflow as an agent with HITL via FunctionCallContent/FunctionResultContent |
|
||||
|
||||
### checkpoint
|
||||
@@ -91,7 +91,7 @@ Once comfortable with these, explore the rest of the samples below.
|
||||
|
||||
### tool-approval
|
||||
|
||||
Tool approval samples demonstrate using `@ai_function(approval_mode="always_require")` to gate sensitive tool executions with human approval. These work with the high-level builder APIs.
|
||||
Tool approval samples demonstrate using `@tool(approval_mode="always_require")` to gate sensitive tool executions with human approval. These work with the high-level builder APIs.
|
||||
|
||||
| Sample | File | Concepts |
|
||||
|---|---|---|
|
||||
@@ -148,7 +148,7 @@ to configure which agents can route to which others with a fluent, type-safe API
|
||||
| Sample | File | Concepts |
|
||||
|---|---|---|
|
||||
| Shared States | [state-management/shared_states_with_agents.py](./state-management/shared_states_with_agents.py) | Store in shared state once and later reuse across agents |
|
||||
| Workflow Kwargs (Custom Context) | [state-management/workflow_kwargs.py](./state-management/workflow_kwargs.py) | Pass custom context (data, user tokens) via kwargs to `@ai_function` tools |
|
||||
| Workflow Kwargs (Custom Context) | [state-management/workflow_kwargs.py](./state-management/workflow_kwargs.py) | Pass custom context (data, user tokens) via kwargs to `@tool` tools |
|
||||
|
||||
|
||||
### visualization
|
||||
|
||||
@@ -8,6 +8,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
executor,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from agent_framework import (
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework._workflows._events import WorkflowOutputEvent
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
|
||||
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
executor,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
executor,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+4
@@ -22,6 +22,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -49,6 +50,8 @@ Prerequisites:
|
||||
- Authentication via azure-identity. Run `az login` before executing.
|
||||
"""
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
|
||||
def fetch_product_brief(
|
||||
product_name: Annotated[str, Field(description="Product name to look up.")],
|
||||
@@ -65,6 +68,7 @@ def fetch_product_brief(
|
||||
}
|
||||
return briefs.get(product_name.lower(), f"No stored brief for '{product_name}'.")
|
||||
|
||||
@tool(approval_mode="never_require")
|
||||
|
||||
def get_brand_voice_profile(
|
||||
voice_name: Annotated[str, Field(description="Brand or campaign voice to emulate.")],
|
||||
|
||||
@@ -9,6 +9,7 @@ from agent_framework import (
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -13,7 +13,7 @@ from agent_framework import (
|
||||
HandoffBuilder,
|
||||
Role,
|
||||
WorkflowAgent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -38,19 +38,20 @@ Key Concepts:
|
||||
"""
|
||||
|
||||
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def process_refund(order_number: Annotated[str, "Order number to process refund for"]) -> str:
|
||||
"""Simulated function to process a refund for a given order number."""
|
||||
return f"Refund processed successfully for order {order_number}."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def check_order_status(order_number: Annotated[str, "Order number to check status for"]) -> str:
|
||||
"""Simulated function to check the status of a given order number."""
|
||||
return f"Order {order_number} is currently being processed and will ship in 2 business days."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def process_return(order_number: Annotated[str, "Order number to process return for"]) -> str:
|
||||
"""Simulated function to process a return for a given order number."""
|
||||
return f"Return initiated successfully for order {order_number}. You will receive return instructions via email."
|
||||
|
||||
@@ -6,6 +6,7 @@ from agent_framework import (
|
||||
ChatAgent,
|
||||
HostedCodeInterpreterTool,
|
||||
MagenticBuilder,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
@@ -26,6 +26,7 @@ from agent_framework import ( # noqa: E402
|
||||
WorkflowContext,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
from getting_started.workflows.agents.workflow_as_agent_reflection_pattern import ( # noqa: E402
|
||||
ReviewRequest,
|
||||
|
||||
@@ -4,22 +4,22 @@ import asyncio
|
||||
import json
|
||||
from typing import Annotated, Any
|
||||
|
||||
from agent_framework import SequentialBuilder, ai_function
|
||||
from agent_framework import SequentialBuilder, tool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Sample: Workflow as Agent with kwargs Propagation to @ai_function Tools
|
||||
Sample: Workflow as Agent with kwargs Propagation to @tool Tools
|
||||
|
||||
This sample demonstrates how to flow custom context (skill data, user tokens, etc.)
|
||||
through a workflow exposed via .as_agent() to @ai_function tools using the **kwargs pattern.
|
||||
through a workflow exposed via .as_agent() to @tool functions using the **kwargs pattern.
|
||||
|
||||
Key Concepts:
|
||||
- Build a workflow using SequentialBuilder (or any builder pattern)
|
||||
- Expose the workflow as a reusable agent via workflow.as_agent()
|
||||
- Pass custom context as kwargs when invoking workflow_agent.run() or run_stream()
|
||||
- kwargs are stored in SharedState and propagated to all agent invocations
|
||||
- @ai_function tools receive kwargs via **kwargs parameter
|
||||
- @tool functions receive kwargs via **kwargs parameter
|
||||
|
||||
When to use workflow.as_agent():
|
||||
- To treat an entire workflow orchestration as a single agent
|
||||
@@ -32,7 +32,8 @@ Prerequisites:
|
||||
|
||||
|
||||
# Define tools that accept custom context via **kwargs
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_user_data(
|
||||
query: Annotated[str, Field(description="What user data to retrieve")],
|
||||
**kwargs: Any,
|
||||
@@ -49,7 +50,7 @@ def get_user_data(
|
||||
return f"Retrieved data for user {user_name} with {access_level} access: {query}"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def call_api(
|
||||
endpoint_name: Annotated[str, Field(description="Name of the API endpoint to call")],
|
||||
**kwargs: Any,
|
||||
@@ -95,7 +96,7 @@ async def main() -> None:
|
||||
# Expose the workflow as an agent using .as_agent()
|
||||
workflow_agent = workflow.as_agent(name="WorkflowAgent")
|
||||
|
||||
# Define custom context that will flow to ai_functions via kwargs
|
||||
# Define custom context that will flow to tools via kwargs
|
||||
custom_data = {
|
||||
"api_config": {
|
||||
"base_url": "https://api.example.com",
|
||||
@@ -119,7 +120,7 @@ async def main() -> None:
|
||||
print("Workflow Agent Execution (watch for [tool_name] logs showing kwargs received):")
|
||||
print("-" * 70)
|
||||
|
||||
# Run workflow agent with kwargs - these will flow through to ai_functions
|
||||
# Run workflow agent with kwargs - these will flow through to tools
|
||||
# Note: kwargs are passed to workflow_agent.run_stream() just like workflow.run_stream()
|
||||
print("\n===== Streaming Response =====")
|
||||
async for update in workflow_agent.run_stream(
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ from agent_framework import (
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from pydantic import BaseModel
|
||||
|
||||
+1
@@ -26,6 +26,7 @@ from agent_framework import (
|
||||
get_checkpoint_summary,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -37,6 +37,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ from agent_framework import (
|
||||
Workflow,
|
||||
WorkflowOutputEvent,
|
||||
WorkflowStatusEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -51,7 +51,7 @@ CHECKPOINT_DIR = Path(__file__).parent / "tmp" / "handoff_checkpoints"
|
||||
CHECKPOINT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
def submit_refund(refund_description: str, amount: str, order_id: str) -> str:
|
||||
"""Capture a refund request for manual review before processing."""
|
||||
return f"refund recorded for order {order_id} (amount: {amount}) with details: {refund_description}"
|
||||
|
||||
@@ -24,6 +24,7 @@ from agent_framework import (
|
||||
WorkflowStatusEvent,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
|
||||
CHECKPOINT_DIR = Path(__file__).with_suffix("").parent / "tmp" / "sub_workflow_checkpoints"
|
||||
|
||||
@@ -31,6 +31,7 @@ from agent_framework import (
|
||||
ChatMessageStore,
|
||||
InMemoryCheckpointStorage,
|
||||
SequentialBuilder,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowExecutor,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from agent_framework import (
|
||||
SequentialBuilder,
|
||||
WorkflowExecutor,
|
||||
WorkflowOutputEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
@@ -32,7 +32,8 @@ Prerequisites:
|
||||
|
||||
|
||||
# Define tools that access custom context via **kwargs
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_authenticated_data(
|
||||
resource: Annotated[str, "The resource to fetch"],
|
||||
**kwargs: Any,
|
||||
@@ -48,7 +49,7 @@ def get_authenticated_data(
|
||||
return f"Fetched '{resource}' for user {user_name} ({access_level} access)"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def call_configured_service(
|
||||
service_name: Annotated[str, "Name of the service to call"],
|
||||
**kwargs: Any,
|
||||
|
||||
@@ -16,6 +16,7 @@ from agent_framework import (
|
||||
WorkflowExecutor,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
handler,
|
||||
response_handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from agent_framework import ( # Core chat primitives used to build requests
|
||||
WorkflowBuilder, # Fluent builder for wiring executors and edges
|
||||
WorkflowContext, # Per-run context and event bus
|
||||
executor, # Decorator to declare a Python function as a workflow executor
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient # Thin client wrapper for Azure OpenAI chat models
|
||||
from azure.identity import AzureCliCredential # Uses your az CLI login for credentials
|
||||
|
||||
@@ -19,6 +19,7 @@ from agent_framework import (
|
||||
WorkflowEvent,
|
||||
WorkflowOutputEvent,
|
||||
executor,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -9,6 +9,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -17,6 +17,7 @@ from agent_framework import ( # Core chat primitives used to form LLM requests
|
||||
WorkflowBuilder, # Fluent builder for assembling the graph
|
||||
WorkflowContext, # Per-run context and event bus
|
||||
executor, # Decorator to turn a function into a workflow executor
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient # Thin client for Azure OpenAI chat models
|
||||
from azure.identity import AzureCliCredential # Uses your az CLI login for credentials
|
||||
|
||||
@@ -11,6 +11,7 @@ from pathlib import Path
|
||||
from typing import Annotated, Any
|
||||
|
||||
from agent_framework import FileCheckpointStorage, RequestInfoEvent, WorkflowOutputEvent
|
||||
from agent_framework import tool
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework_declarative import ExternalInputRequest, ExternalInputResponse, WorkflowFactory
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -37,17 +38,18 @@ MENU_ITEMS = [
|
||||
MenuItem(category="Drink", name="Soda", price=1.95, is_special=False),
|
||||
]
|
||||
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_menu() -> list[dict[str, Any]]:
|
||||
"""Get all menu items."""
|
||||
return [{"category": i.category, "name": i.name, "price": i.price} for i in MENU_ITEMS]
|
||||
|
||||
|
||||
@tool(approval_mode="never_require")
|
||||
def get_specials() -> list[dict[str, Any]]:
|
||||
"""Get today's specials."""
|
||||
return [{"category": i.category, "name": i.name, "price": i.price} for i in MENU_ITEMS if i.is_special]
|
||||
|
||||
|
||||
@tool(approval_mode="never_require")
|
||||
def get_item_price(name: Annotated[str, Field(description="Menu item name")]) -> str:
|
||||
"""Get price of a menu item."""
|
||||
for item in MENU_ITEMS:
|
||||
|
||||
+7
-6
@@ -14,7 +14,7 @@ from agent_framework import (
|
||||
FunctionApprovalResponseContent,
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
ai_function,
|
||||
tool,
|
||||
executor,
|
||||
handler,
|
||||
)
|
||||
@@ -53,14 +53,15 @@ Prerequisites:
|
||||
"""
|
||||
|
||||
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_current_date() -> str:
|
||||
"""Get the current date in YYYY-MM-DD format."""
|
||||
# For demonstration purposes, we return a fixed date.
|
||||
return "2025-11-07"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def get_team_members_email_addresses() -> list[dict[str, str]]:
|
||||
"""Get the email addresses of team members."""
|
||||
# In a real implementation, this might query a database or directory service.
|
||||
@@ -92,7 +93,7 @@ def get_team_members_email_addresses() -> list[dict[str, str]]:
|
||||
]
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def get_my_information() -> dict[str, str]:
|
||||
"""Get my personal information."""
|
||||
return {
|
||||
@@ -103,7 +104,7 @@ def get_my_information() -> dict[str, str]:
|
||||
}
|
||||
|
||||
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
async def read_historical_email_data(
|
||||
email_address: Annotated[str, "The email address to read historical data from"],
|
||||
start_date: Annotated[str, "The start date in YYYY-MM-DD format"],
|
||||
@@ -165,7 +166,7 @@ async def read_historical_email_data(
|
||||
return [email for email in emails if start_date <= email["date"] <= end_date]
|
||||
|
||||
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
async def send_email(
|
||||
to: Annotated[str, "The recipient email address"],
|
||||
subject: Annotated[str, "The email subject"],
|
||||
|
||||
@@ -33,6 +33,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework._workflows._agent_executor import AgentExecutorResponse
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
|
||||
@@ -35,6 +35,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ from agent_framework import (
|
||||
WorkflowStatusEvent, # Event emitted on run state changes
|
||||
handler,
|
||||
response_handler, # Decorator to expose an Executor method as a step
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -32,6 +32,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ from agent_framework import (
|
||||
Executor,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ from agent_framework import (
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -9,6 +9,7 @@ from agent_framework import (
|
||||
GroupChatBuilder,
|
||||
Role,
|
||||
WorkflowOutputEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
GroupChatBuilder,
|
||||
Role,
|
||||
WorkflowOutputEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -9,6 +9,7 @@ from agent_framework import (
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
WorkflowOutputEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowEvent,
|
||||
WorkflowOutputEvent,
|
||||
resolve_agent_id,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+5
-4
@@ -18,7 +18,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -47,19 +47,20 @@ Key Concepts:
|
||||
"""
|
||||
|
||||
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def process_refund(order_number: Annotated[str, "Order number to process refund for"]) -> str:
|
||||
"""Simulated function to process a refund for a given order number."""
|
||||
return f"Refund processed successfully for order {order_number}."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def check_order_status(order_number: Annotated[str, "Order number to check status for"]) -> str:
|
||||
"""Simulated function to check the status of a given order number."""
|
||||
return f"Order {order_number} is currently being processed and will ship in 2 business days."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def process_return(order_number: Annotated[str, "Order number to process return for"]) -> str:
|
||||
"""Simulated function to process a return for a given order number."""
|
||||
return f"Return initiated successfully for order {order_number}. You will receive return instructions via email."
|
||||
|
||||
@@ -16,7 +16,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -38,19 +38,20 @@ Key Concepts:
|
||||
"""
|
||||
|
||||
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def process_refund(order_number: Annotated[str, "Order number to process refund for"]) -> str:
|
||||
"""Simulated function to process a refund for a given order number."""
|
||||
return f"Refund processed successfully for order {order_number}."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def check_order_status(order_number: Annotated[str, "Order number to check status for"]) -> str:
|
||||
"""Simulated function to check the status of a given order number."""
|
||||
return f"Order {order_number} is currently being processed and will ship in 2 business days."
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def process_return(order_number: Annotated[str, "Order number to process return for"]) -> str:
|
||||
"""Simulated function to process a return for a given order number."""
|
||||
return f"Return initiated successfully for order {order_number}. You will receive return instructions via email."
|
||||
|
||||
+1
@@ -41,6 +41,7 @@ from agent_framework import (
|
||||
WorkflowEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ from agent_framework import (
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticProgressLedger,
|
||||
WorkflowOutputEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity._credentials import AzureCliCredential
|
||||
|
||||
@@ -12,6 +12,7 @@ from agent_framework import (
|
||||
MagenticPlanReviewRequest,
|
||||
RequestInfoEvent,
|
||||
WorkflowOutputEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
SequentialBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ from agent_framework import (
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -16,6 +16,7 @@ from agent_framework import ( # Core chat primitives to build LLM requests
|
||||
WorkflowContext, # Per run context and event bus
|
||||
WorkflowOutputEvent, # Event emitted when workflow yields output
|
||||
handler, # Decorator to mark an Executor method as invokable
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential # Uses your az CLI login for credentials
|
||||
|
||||
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowOutputEvent, # Event emitted when workflow yields output
|
||||
WorkflowViz, # Utility to visualize a workflow graph
|
||||
handler, # Decorator to expose an Executor method as a step
|
||||
tool,
|
||||
)
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ from agent_framework import (
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
executor,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -4,20 +4,20 @@ import asyncio
|
||||
import json
|
||||
from typing import Annotated, Any
|
||||
|
||||
from agent_framework import ChatMessage, SequentialBuilder, WorkflowOutputEvent, ai_function
|
||||
from agent_framework import ChatMessage, SequentialBuilder, WorkflowOutputEvent, tool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Sample: Workflow kwargs Flow to @ai_function Tools
|
||||
Sample: Workflow kwargs Flow to @tool Tools
|
||||
|
||||
This sample demonstrates how to flow custom context (skill data, user tokens, etc.)
|
||||
through any workflow pattern to @ai_function tools using the **kwargs pattern.
|
||||
through any workflow pattern to @tool functions using the **kwargs pattern.
|
||||
|
||||
Key Concepts:
|
||||
- Pass custom context as kwargs when invoking workflow.run_stream() or workflow.run()
|
||||
- kwargs are stored in SharedState and passed to all agent invocations
|
||||
- @ai_function tools receive kwargs via **kwargs parameter
|
||||
- @tool functions receive kwargs via **kwargs parameter
|
||||
- Works with Sequential, Concurrent, GroupChat, Handoff, and Magentic patterns
|
||||
|
||||
Prerequisites:
|
||||
@@ -26,7 +26,8 @@ Prerequisites:
|
||||
|
||||
|
||||
# Define tools that accept custom context via **kwargs
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_user_data(
|
||||
query: Annotated[str, Field(description="What user data to retrieve")],
|
||||
**kwargs: Any,
|
||||
@@ -43,7 +44,7 @@ def get_user_data(
|
||||
return f"Retrieved data for user {user_name} with {access_level} access: {query}"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def call_api(
|
||||
endpoint_name: Annotated[str, Field(description="Name of the API endpoint to call")],
|
||||
**kwargs: Any,
|
||||
@@ -86,7 +87,7 @@ async def main() -> None:
|
||||
# Build a simple sequential workflow
|
||||
workflow = SequentialBuilder().participants([agent]).build()
|
||||
|
||||
# Define custom context that will flow to ai_functions via kwargs
|
||||
# Define custom context that will flow to tools via kwargs
|
||||
custom_data = {
|
||||
"api_config": {
|
||||
"base_url": "https://api.example.com",
|
||||
@@ -110,7 +111,7 @@ async def main() -> None:
|
||||
print("Workflow Execution (watch for [tool_name] logs showing kwargs received):")
|
||||
print("-" * 70)
|
||||
|
||||
# Run workflow with kwargs - these will flow through to ai_functions
|
||||
# Run workflow with kwargs - these will flow through to tools
|
||||
async for event in workflow.run_stream(
|
||||
"Please get my user data and then call the users API endpoint.",
|
||||
custom_data=custom_data,
|
||||
|
||||
+6
-5
@@ -10,7 +10,7 @@ from agent_framework import (
|
||||
FunctionApprovalResponseContent,
|
||||
RequestInfoEvent,
|
||||
WorkflowOutputEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
@@ -45,7 +45,8 @@ Prerequisites:
|
||||
|
||||
|
||||
# 1. Define market data tools (no approval required)
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_stock_price(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
|
||||
"""Get the current stock price for a given symbol."""
|
||||
# Mock data for demonstration
|
||||
@@ -54,7 +55,7 @@ def get_stock_price(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
|
||||
return f"{symbol.upper()}: ${price:.2f}"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def get_market_sentiment(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
|
||||
"""Get market sentiment analysis for a stock."""
|
||||
# Mock sentiment data
|
||||
@@ -68,7 +69,7 @@ def get_market_sentiment(symbol: Annotated[str, "The stock ticker symbol"]) -> s
|
||||
|
||||
|
||||
# 2. Define trading tools (approval required)
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
def execute_trade(
|
||||
symbol: Annotated[str, "The stock ticker symbol"],
|
||||
action: Annotated[str, "Either 'buy' or 'sell'"],
|
||||
@@ -78,7 +79,7 @@ def execute_trade(
|
||||
return f"Trade executed: {action.upper()} {quantity} shares of {symbol.upper()}"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def get_portfolio_balance() -> str:
|
||||
"""Get current portfolio balance and available funds."""
|
||||
return "Portfolio: $50,000 invested, $10,000 cash available. Holdings: AAPL, GOOGL, MSFT."
|
||||
|
||||
+6
-5
@@ -10,7 +10,7 @@ from agent_framework import (
|
||||
GroupChatRequestSentEvent,
|
||||
GroupChatState,
|
||||
RequestInfoEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
@@ -44,19 +44,20 @@ Prerequisites:
|
||||
|
||||
|
||||
# 1. Define tools for different agents
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def run_tests(test_suite: Annotated[str, "Name of the test suite to run"]) -> str:
|
||||
"""Run automated tests for the application."""
|
||||
return f"Test suite '{test_suite}' completed: 47 passed, 0 failed, 0 skipped"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def check_staging_status() -> str:
|
||||
"""Check the current status of the staging environment."""
|
||||
return "Staging environment: Healthy, Version 2.3.0 deployed, All services running"
|
||||
|
||||
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
def deploy_to_production(
|
||||
version: Annotated[str, "The version to deploy"],
|
||||
components: Annotated[str, "Comma-separated list of components to deploy"],
|
||||
@@ -65,7 +66,7 @@ def deploy_to_production(
|
||||
return f"Production deployment complete: Version {version}, Components: {components}"
|
||||
|
||||
|
||||
@ai_function
|
||||
@tool(approval_mode="never_require")
|
||||
def create_rollback_plan(version: Annotated[str, "The version being deployed"]) -> str:
|
||||
"""Create a rollback plan for the deployment."""
|
||||
return (
|
||||
|
||||
+6
-5
@@ -9,7 +9,7 @@ from agent_framework import (
|
||||
RequestInfoEvent,
|
||||
SequentialBuilder,
|
||||
WorkflowOutputEvent,
|
||||
ai_function,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
@@ -17,7 +17,7 @@ from agent_framework.openai import OpenAIChatClient
|
||||
Sample: Sequential Workflow with Tool Approval Requests
|
||||
|
||||
This sample demonstrates how to use SequentialBuilder with tools that require human
|
||||
approval before execution. The approval flow uses the existing @ai_function decorator
|
||||
approval before execution. The approval flow uses the existing @tool decorator
|
||||
with approval_mode="always_require" to trigger human-in-the-loop interactions.
|
||||
|
||||
This sample works as follows:
|
||||
@@ -33,7 +33,7 @@ Show how tool call approvals integrate seamlessly with SequentialBuilder without
|
||||
requiring any additional builder configuration.
|
||||
|
||||
Demonstrate:
|
||||
- Using @ai_function(approval_mode="always_require") for sensitive operations.
|
||||
- Using @tool(approval_mode="always_require") for sensitive operations.
|
||||
- Handling RequestInfoEvent with FunctionApprovalRequestContent in sequential workflows.
|
||||
- Resuming workflow execution after approval via send_responses_streaming.
|
||||
|
||||
@@ -44,7 +44,7 @@ Prerequisites:
|
||||
|
||||
|
||||
# 1. Define tools - one requiring approval, one that doesn't
|
||||
@ai_function(approval_mode="always_require")
|
||||
@tool(approval_mode="always_require")
|
||||
def execute_database_query(
|
||||
query: Annotated[str, "The SQL query to execute against the production database"],
|
||||
) -> str:
|
||||
@@ -53,7 +53,8 @@ def execute_database_query(
|
||||
return f"Query executed successfully. Results: 3 rows affected by '{query}'"
|
||||
|
||||
|
||||
@ai_function
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@tool(approval_mode="never_require")
|
||||
def get_database_schema() -> str:
|
||||
"""Get the current database schema. Does not require approval."""
|
||||
return """
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ from agent_framework import (
|
||||
WorkflowContext,
|
||||
WorkflowViz,
|
||||
handler,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
Reference in New Issue
Block a user