mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
fd819c6c02
* support for local function approval * small fix * fix mypy * added bigger test scenario's for function calling and approvals * updated lock * updated return message for rejection * fix test * updated function result content handling
104 lines
3.8 KiB
Python
104 lines
3.8 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
||
|
||
import asyncio
|
||
from typing import Annotated
|
||
|
||
from agent_framework import FunctionCallContent, FunctionResultContent
|
||
from agent_framework.openai import OpenAIResponsesClient
|
||
|
||
"""
|
||
Tool exceptions handled by returning the error for the agent to recover from.
|
||
|
||
Shows how a tool that throws an exception creates gracefull recovery and can keep going.
|
||
The LLM decides whether to retry the call or to respond with something else, based on the exception.
|
||
"""
|
||
|
||
|
||
def greet(name: Annotated[str, "Name to greet"]) -> str:
|
||
"""Greet someone."""
|
||
return f"Hello, {name}!"
|
||
|
||
|
||
# we trick the AI into calling this function with 0 as denominator to trigger the exception
|
||
def safe_divide(
|
||
a: Annotated[int, "Numerator"],
|
||
b: Annotated[int, "Denominator"],
|
||
) -> str:
|
||
"""Divide two numbers can be used with 0 as denominator."""
|
||
try:
|
||
result = a / b # Will raise ZeroDivisionError
|
||
except ZeroDivisionError as exc:
|
||
print(f" Tool failed: with error: {exc}")
|
||
raise
|
||
|
||
return f"{a} / {b} = {result}"
|
||
|
||
|
||
async def main():
|
||
# tools = Tools()
|
||
agent = OpenAIResponsesClient().create_agent(
|
||
name="ToolAgent",
|
||
instructions="Use the provided tools.",
|
||
tools=[greet, safe_divide],
|
||
)
|
||
thread = agent.get_new_thread()
|
||
print("=" * 60)
|
||
print("Step 1: Call divide(10, 0) - tool raises exception")
|
||
response = await agent.run("Divide 10 by 0", thread=thread)
|
||
print(f"Response: {response.text}")
|
||
print("=" * 60)
|
||
print("Step 2: Call greet('Bob') - conversation can keep going.")
|
||
response = await agent.run("Greet Bob", thread=thread)
|
||
print(f"Response: {response.text}")
|
||
print("=" * 60)
|
||
print("Replay the conversation:")
|
||
assert thread.message_store
|
||
assert thread.message_store.list_messages
|
||
for idx, msg in enumerate(await thread.message_store.list_messages()):
|
||
if msg.text:
|
||
print(f"{idx + 1} {msg.author_name or msg.role}: {msg.text} ")
|
||
for content in msg.contents:
|
||
if isinstance(content, FunctionCallContent):
|
||
print(
|
||
f"{idx + 1} {msg.author_name}: calling function: {content.name} with arguments: {content.arguments}"
|
||
)
|
||
if isinstance(content, FunctionResultContent):
|
||
print(f"{idx + 1} {msg.role}: {content.result if content.result else content.exception}")
|
||
|
||
|
||
"""
|
||
Expected Output:
|
||
============================================================
|
||
Step 1: Call divide(10, 0) - tool raises exception
|
||
Tool failed: with error: division by zero
|
||
Response: Division by zero is undefined in standard arithmetic, so 10 ÷ 0 has no meaning.
|
||
|
||
If you’re curious about limits: as x approaches 0 from the positive side, 10/x tends to +∞; from the negative side,
|
||
10/x tends to -∞.
|
||
|
||
If you want a finite result, try dividing by a nonzero number, e.g., 10 ÷ 2 = 5 or 10 ÷ 0.1 = 100. Want me to compute
|
||
something else?
|
||
============================================================
|
||
Step 2: Call greet('Bob') - conversation can keep going.
|
||
Response: Hello, Bob!
|
||
============================================================
|
||
Replay the conversation:
|
||
1 user: Divide 10 by 0
|
||
2 ToolAgent: calling function: safe_divide with arguments: {"a":10,"b":0}
|
||
3 tool: division by zero
|
||
4 ToolAgent: Division by zero is undefined in standard arithmetic, so 10 ÷ 0 has no meaning.
|
||
|
||
If you’re curious about limits: as x approaches 0 from the positive side, 10/x tends to +∞; from the negative side,
|
||
10/x tends to -∞.
|
||
|
||
If you want a finite result, try dividing by a nonzero number, e.g., 10 ÷ 2 = 5 or 10 ÷ 0.1 = 100. Want me to compute
|
||
something else?
|
||
5 user: Greet Bob
|
||
6 ToolAgent: calling function: greet with arguments: {"name":"Bob"}
|
||
7 tool: Hello, Bob!
|
||
8 ToolAgent: Hello, Bob!
|
||
"""
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(main())
|