### Quickstart: Tool-Calling Loop with openai-resptools Source: https://github.com/hoopengo/openai-resptools/blob/master/README.md Demonstrates a basic tool-calling loop using openai-resptools. It defines 'write' and 'read' tools, sets up a ToolRunner, and executes a prompt that utilizes these tools. ```python import os from typing import Dict from openai import OpenAI from openai_resptools import ToolRegistry, ToolRunner store: Dict[str, str] = {} registry = ToolRegistry() @registry.tool() def write(key: str, text: str) -> dict: """Save text under a key and return a small status payload.""" store[key] = text return {"ok": True, "key": key, "length": len(text)} @registry.tool() def read(key: str) -> dict: """Read text by key. Returns null text if missing.""" return {"key": key, "text": store.get(key)} client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) model = os.getenv("OPENAI_MODEL", "gpt-4o-mini") runner = ToolRunner( client, model=model, registry=registry, max_iters=6, parallel_tool_calls=False, ) prompt = ( "Do the following steps using tools:\n" "1) Call write to save the text 'Hello from tools!' under key 'greeting'.\n" "2) Call read for key 'greeting'.\n" "3) Reply with ONLY the value of the text you read.\n" ) result = runner.run(prompt) print(result.text) ``` -------------------------------- ### Development Installation and Checks Source: https://github.com/hoopengo/openai-resptools/blob/master/README.md Commands for setting up the development environment, running tests, and checking code quality with Ruff. These are essential for contributing to the project. ```bash pip install -e ".[dev]" pytest ruff check . ``` -------------------------------- ### Install openai-resptools Source: https://github.com/hoopengo/openai-resptools/blob/master/README.md Installs the openai-resptools library using pip. This is the primary method for adding the library to your Python environment. ```bash pip install openai-resptools ``` -------------------------------- ### End-to-end Tool Calling Loop with Python Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/examples.md Demonstrates defining tools using @registry.tool(), running ToolRunner.run() until the model returns final text, and returning tool results as JSON strings via function_call_output. It requires the OPENAI_API_KEY environment variable to be set. ```python import os from typing import Dict from openai import OpenAI from openai_resptools import ToolRegistry, ToolRunner store: Dict[str, str] = {} registry = ToolRegistry() @registry.tool() def write(key: str, text: str) -> dict: store[key] = text return {"ok": True, "key": key, "length": len(text)} @registry.tool() def read(key: str) -> dict: return {"key": key, "text": store.get(key)} client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) runner = ToolRunner( client, model=os.getenv("OPENAI_MODEL", "gpt-4o-mini"), registry=registry, max_iters=6, parallel_tool_calls=False, ) result = runner.run( "Do the following steps using tools:\n" "1) Call write to save the text 'Hello from tools!' under key 'greeting'.\n" "2) Call read for key 'greeting'.\n" "3) Reply with ONLY the value of the text you read.\n" ) print(result.text) ``` -------------------------------- ### Registry Patterns: Class-based Auto-registration with Python Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/examples.md Shows how to use ToolRegistry as a class, automatically registering public methods as tools. This pattern simplifies tool definition when tools are part of a service class. It requires the openai-resptools library. ```python from openai_resptools import ToolRegistry class MyServiceTools(ToolRegistry): def __init__(self, db_conn: str) -> None: super().__init__() self.db_conn = db_conn def get_user_status(self, user_id: int) -> str: return f"User {user_id} is active (DB: {self.db_conn})" service = MyServiceTools(db_conn="postgres://localhost:5432") print(service.names()) ``` -------------------------------- ### Registry Patterns: Manual Dispatch without ToolRunner in Python Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/examples.md Demonstrates manual tool dispatch using ToolRegistry without involving ToolRunner. This is useful for testing or scenarios where direct control over tool execution is needed. It requires the openai-resptools and json libraries. ```python import json from openai_resptools import ToolRegistry registry = ToolRegistry() @registry.tool() def calculator(a: int, b: int, op: str) -> int: if op == "+": return a + b if op == "-": return a - b raise ValueError(f"Unsupported operation: {op!r}") mock_call = {"name": "calculator", "arguments": '{"a": 10, "b": 5, "op": "+"}'} args = json.loads(mock_call["arguments"]) output = registry.get(mock_call["name"]).call(args) print(output) ``` -------------------------------- ### Convenience run() function Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md A convenience function that simplifies the process of running the tool interaction loop without explicitly instantiating ToolRunner. ```APIDOC ## run(...) ### Description A convenience function to run the tool interaction loop. ### Signature - **`run(client, model, registry, prompt, tool_choice=None, instructions=None, max_iters=8, max_retry=0) -> RunnerResult`** - `client`: The OpenAI client instance. - `model` (str): The name of the model to use. - `registry` (ToolRegistry): An instance of `ToolRegistry` containing available tools. - `prompt` (str): The initial prompt. - `tool_choice` (any, optional): Tool choice configuration passed to the Responses API. - `instructions` (str, optional): Instructions passed to the Responses API. - `max_iters` (int, optional): Maximum number of iterations for the loop (defaults to 8). - `max_retry` (int, optional): Maximum number of retries for tool calls (defaults to 0). - Returns: A `RunnerResult` object. ``` -------------------------------- ### Execute OpenAI Tool Calls with ToolRunner in Python Source: https://context7.com/hoopengo/openai-resptools/llms.txt Shows how to use the `ToolRunner` class to manage the complete tool-calling loop with OpenAI models. It covers setting up the client, registry, defining tools, configuring the runner, and executing runs with different prompts and options like `instructions` and `tool_choice`. ```python import os from typing import Dict from openai import OpenAI from openai_resptools import ToolRegistry, ToolRunner # Set up client and registry client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) registry = ToolRegistry() # In-memory data store notes: Dict[str, str] = {} @registry.tool() def save_note(title: str, content: str) -> dict: """Save a note with a title.""" notes[title] = content return {"saved": True, "title": title, "length": len(content)} @registry.tool() def get_note(title: str) -> dict: """Retrieve a note by title.""" content = notes.get(title) return {"title": title, "content": content, "found": content is not None} @registry.tool() def list_notes() -> dict: """List all saved note titles.""" return {"titles": list(notes.keys()), "count": len(notes)} # Create runner with configuration runner = ToolRunner( client, model="gpt-4o-mini", registry=registry, max_iters=8, # Maximum tool-calling iterations max_retry=2, # Retry on tool errors before raising parallel_tool_calls=False, # Disable parallel tool execution ) # Run with a simple prompt result = runner.run( "Save a note titled 'Meeting' with content 'Discuss Q4 goals'. " "Then list all notes and tell me what you saved." ) print(result.text) # Model's final response print(len(result.input_items)) # Number of conversation items accumulated # Run with custom input items custom_input = [ {"role": "user", "content": "What notes do I have?"}, ] result = runner.run(custom_input) # Run with system instructions and tool_choice result = runner.run( "Get the Meeting note", instructions="You are a helpful assistant. Always be concise.", tool_choice={"type": "function", "name": "get_note"}, ) ``` -------------------------------- ### Tool Definition and Execution (Python) Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/overview.md Illustrates the `ToolDef` class, which is responsible for creating a Pydantic model from a callable's signature, validating incoming arguments, executing the callable, and serializing the results. This is fundamental for how individual tools are defined and run. ```python from openai_resptools import ToolDef def multiply(a: int, b: int) -> int: return a * b tool_def = ToolDef(multiply) # Example of validating and executing args = {"a": 5, "b": 3} result = tool_def.execute(args) print(result) # Output: 15 ``` -------------------------------- ### Implement Event Callbacks for ToolRunner in Python Source: https://context7.com/hoopengo/openai-resptools/llms.txt Demonstrates how to use the `on_event` callback in `ToolRunner` for monitoring and logging the tool-calling process. It defines a callback function to handle events like `llm.request`, `llm.response`, `tool.call`, and `tool.output`, showing how to attach it during runner initialization. ```python import os from openai import OpenAI from openai_resptools import ToolRegistry, ToolRunner client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) registry = ToolRegistry() @registry.tool() def add_numbers(a: int, b: int) -> int: """Add two numbers together.""" return a + b # Event callback for logging/monitoring def on_event(event_name: str, payload: dict) -> None: if event_name == "llm.request": print(f"[Request] Iteration {payload['iteration']}") elif event_name == "llm.response": print(f"[Response] Iteration {payload['iteration']}, tool_calls: {payload['tool_calls']}") elif event_name == "tool.call": print(f"[Tool Call] {payload['name']}({payload['arguments']})") elif event_name == "tool.output": print(f"[Tool Output] {payload['name']} -> {payload['output']}") runner = ToolRunner( client, model="gpt-4o-mini", registry=registry, max_iters=5, on_event=on_event, # Attach event callback ) result = runner.run("What is 15 + 27?") # Output: # [Request] Iteration 0 # [Response] Iteration 0, tool_calls: 1 # [Tool Call] add_numbers({"a": 15, "b": 27}) # [Tool Output] add_numbers -> 42 # [Request] Iteration 1 # [Response] Iteration 1, tool_calls: 0 print(result.text) # "42" or "The sum of 15 and 27 is 42." ``` -------------------------------- ### Pattern: Manual Dispatch (No Runner) Source: https://github.com/hoopengo/openai-resptools/blob/master/README.md Illustrates how to manually generate tool schemas and dispatch tool calls without using the ToolRunner. This provides more control over the tool-calling process. ```python import json from openai_resptools import ToolRegistry registry = ToolRegistry() @registry.tool() def calculator(a: int, b: int, op: str) -> int: if op == "+": return a + b if op == "-": return a - b raise ValueError(f"Unsupported operation: {op!r}") tools_payload = registry.as_openai_tools() mock_call = {"name": "calculator", "arguments": '{"a": 10, "b": 5, "op": "+"}'} args = json.loads(mock_call["arguments"]) output = registry.get(mock_call["name"]).call(args) print(output) ``` -------------------------------- ### Register Tool with Decorator (Python) Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/overview.md Demonstrates how to register a Python function as an OpenAI tool using the `@registry.tool()` decorator. This is the primary method for adding callable functions to the tool registry. ```python from openai_resptools import ToolRegistry registry = ToolRegistry() @registry.tool() def get_weather(city: str, state: str) -> str: """Get the current weather in a given location""" return f"The weather in {city}, {state} is sunny." ``` -------------------------------- ### Create and Use ToolDef from Callable in Python Source: https://context7.com/hoopengo/openai-resptools/llms.txt Demonstrates how to create a ToolDef object from a Python callable function using `ToolDef.from_callable`. It shows how to access tool properties like name, description, and parameters, and how to validate arguments and execute the tool, including serialization to JSON. ```python from openai_resptools import ToolDef, ToolArgumentsError, ToolExecutionError def calculate(a: int, b: int, operation: str) -> int: if operation == "add": return a + b elif operation == "subtract": return a - b elif operation == "multiply": return a * b elif operation == "divide": if b == 0: raise ToolExecutionError("Cannot divide by zero") return a / b else: raise ValueError(f"Unknown operation: {operation}") # Create ToolDef from callable tool = ToolDef.from_callable( calculate, name="calculator", # Optional: override function name description="Perform basic arithmetic", # Optional: override docstring strict=True # Default: enforce strict JSON schema ) print(tool.name) # "calculator" print(tool.description) # "Perform basic arithmetic" print(tool.parameters) # {"type": "object", "properties": {...}, "required": [...]} # Validate arguments (returns clean dict) raw_args = {"a": 10, "b": 5, "operation": "add"} validated = tool.validate_args(raw_args) print(validated) # {"a": 10, "b": 5, "operation": "add"} # Execute with validation result = tool.call({"a": 10, "b": 5, "operation": "multiply"}) print(result) # 50 # Execute and serialize to JSON string (for function_call_output) json_output = tool.call_and_serialize({"a": 20, "b": 4, "operation": "divide"}) print(json_output) # "5" # Error handling try: tool.validate_args({"a": "not_an_int", "b": 5, "operation": "add"}) except ToolArgumentsError as e: print(f"Validation failed: {e}") try: tool.call({"a": 10, "b": 0, "operation": "divide"}) except ToolExecutionError as e: print(f"Execution failed: {e}") # "Tool 'calculator' failed: Cannot divide by zero" ``` -------------------------------- ### Run Convenience Function for Tool-Calling Workflows (Python) Source: https://context7.com/hoopengo/openai-resptools/llms.txt The `run()` function simplifies tool-calling by providing a one-liner interface, eliminating the need for manual `ToolRunner` instantiation. It takes an OpenAI client, model name, tool registry, prompt, and iteration/retry limits as input, returning a `RunnerResult` object containing the final text output and conversation history. ```python import os from openai import OpenAI from openai_resptools import ToolRegistry, run client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) registry = ToolRegistry() @registry.tool() def get_time(timezone: str = "UTC") -> str: """Get current time in the specified timezone.""" from datetime import datetime return f"Current time in {timezone}: {datetime.now().isoformat()}" # One-liner execution result = run( client, model="gpt-4o-mini", registry=registry, prompt="What time is it in UTC?", max_iters=4, max_retry=1, ) print(result.text) print(result.input_items) # Full conversation history ``` -------------------------------- ### Auto-Register Public Methods - ToolRegistry Class Source: https://context7.com/hoopengo/openai-resptools/llms.txt Illustrates subclassing ToolRegistry to automatically register all public methods as tools. This pattern supports dependency injection and encapsulated service classes, excluding private methods. It shows instantiation with dependencies and direct tool execution. ```python from openai_resptools import ToolRegistry class DatabaseTools(ToolRegistry): """Service class with auto-registered tool methods.""" def __init__(self, connection_string: str) -> None: super().__init__() self.conn = connection_string self._cache = {} def get_user(self, user_id: int) -> dict: """Fetch user by ID from the database.""" # Simulated database lookup return {"id": user_id, "name": "John Doe", "db": self.conn} def create_user(self, name: str, email: str) -> dict: """Create a new user in the database.""" return {"id": 123, "name": name, "email": email, "created": True} def _internal_helper(self) -> None: """Private method - NOT registered as a tool.""" pass # Instantiate with dependencies db_tools = DatabaseTools(connection_string="postgres://localhost:5432/mydb") # Public methods are auto-registered print(db_tools.names()) # ['get_user', 'create_user'] # Execute tool directly result = db_tools.get("get_user").call({"user_id": 42}) print(result) # {"id": 42, "name": "John Doe", "db": "postgres://localhost:5432/mydb"} # Get OpenAI-compatible schemas schemas = db_tools.as_openai_tools() ``` -------------------------------- ### Tool Calling Loop Execution (Python) Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/overview.md Shows how the `ToolRunner` class manages the complete Responses API tool-calling loop. It handles sending requests, processing tool calls, validating arguments, executing tools, and appending outputs until a final text response is generated. ```python from openai_resptools import ToolRunner, ToolRegistry # Assume registry is set up with tools registry = ToolRegistry() @registry.tool() def add(a: int, b: int) -> int: return a + b runner = ToolRunner(client=None, registry=registry) # Example of running the loop (client would be an actual OpenAI client) # final_output = runner.run("What is 2 + 2?") # print(final_output) ``` -------------------------------- ### Register Tools with Decorator - ToolRegistry Source: https://context7.com/hoopengo/openai-resptools/llms.txt Demonstrates how to use the @tool() decorator from ToolRegistry to register Python functions as OpenAI-compatible tools. It shows how to define tools with default arguments, custom names, descriptions, and how to generate OpenAI tool payloads and tool_choice payloads. ```python import os from openai import OpenAI from openai_resptools import ToolRegistry, ToolRunner # Create a registry and register tools with the decorator registry = ToolRegistry() @registry.tool() def get_weather(city: str, units: str = "celsius") -> dict: """Get current weather for a city.""" # Simulated weather data return {"city": city, "temperature": 22, "units": units, "condition": "sunny"} @registry.tool(name="search_db", description="Search the database for records") def search_database(query: str, limit: int = 10) -> dict: """Custom name and description override.""" return {"query": query, "results": [], "count": 0} # List registered tools print(registry.names()) # ['get_weather', 'search_db'] # Generate OpenAI tools payload tools_payload = registry.as_openai_tools() # Output: [{"type": "function", "name": "get_weather", "description": "Get current weather...", "parameters": {...}, "strict": True}, ...] # Generate tool_choice payload for allowed tools tool_choice = registry.allowed_tools_choice(names=["get_weather"], mode="auto") # Output: {"type": "allowed_tools", "mode": "auto", "tools": [{"type": "function", "name": "get_weather"}]} # Get a specific tool tool = registry.get("get_weather") print(tool.name, tool.description) # Check if tool exists if "get_weather" in registry: print("Tool found!") ``` -------------------------------- ### Manual Tool Dispatch with ToolRegistry (Python) Source: https://context7.com/hoopengo/openai-resptools/llms.txt For custom API integrations requiring direct control over the tool-calling flow, `ToolRegistry` can generate schemas and facilitate manual dispatch. This involves defining tools, generating an OpenAI-compatible tools payload, making a direct API call, and then processing the response to invoke the appropriate tool function. ```python import json from openai import OpenAI from openai_resptools import ToolRegistry registry = ToolRegistry() @registry.tool() def search(query: str, max_results: int = 5) -> dict: """Search for documents matching the query.""" return {"query": query, "results": ["doc1", "doc2"], "total": 2} @registry.tool() def summarize(text: str) -> str: """Summarize the given text.""" return f"Summary of: {text[:50]}..." # Generate tools payload for API call tools_payload = registry.as_openai_tools() # Make your own API call client = OpenAI() response = client.responses.create( model="gpt-4o-mini", input=[{"role": "user", "content": "Search for Python tutorials"}], tools=tools_payload, ) ``` -------------------------------- ### ToolDef API Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md The ToolDef class binds a callable to an OpenAI tool schema and a Pydantic argument validator. It handles argument validation and output serialization. ```APIDOC ## ToolDef ### Description Binds a callable to an OpenAI tool schema and a Pydantic args validator. Handles argument validation and output serialization. ### Key Methods - **`from_callable(func, name=None, description=None, parameters=None, strict=True)`**: Creates a `ToolDef` from a callable function. - `func` (callable): The function to wrap as a tool. - `name` (str, optional): Override tool name. - `description` (str, optional): Override tool description. - `parameters` (dict, optional): Override JSON schema parameters. - `strict` (bool, optional): Use strict mode for schema validation (defaults to True). - **`validate_args(raw_args: dict) -> dict`**: Validates raw arguments against the tool's schema using Pydantic. - `raw_args` (dict): The dictionary of arguments to validate. - Returns: A dictionary of validated arguments. - **`call(raw_args: dict) -> Any`**: Calls the underlying function with validated arguments. - `raw_args` (dict): The dictionary of arguments to pass to the function. - Returns: The result of the function call. - **`call_and_serialize(raw_args: dict) -> str`**: Calls the function and serializes the output to a JSON string. - `raw_args` (dict): The dictionary of arguments to pass to the function. - Returns: A JSON string representing the function's output. ### Behavior Notes - Argument validation uses Pydantic (`model_validate`). - Output serialization uses `json_dumps(...)`. ``` -------------------------------- ### Define Tool with Pydantic Validation - ToolDef Source: https://context7.com/hoopengo/openai-resptools/llms.txt Shows the definition of a single tool using the ToolDef class, which binds a Python callable to an OpenAI schema with Pydantic-based argument validation. It handles schema generation, argument validation, execution, and JSON serialization of results. ```python from openai_resptools import ToolDef from openai_resptools.errors import ToolArgumentsError, ToolExecutionError def calculate(a: int, b: int, operation: str) -> int: """Perform arithmetic on two numbers.""" if operation == "add": return a + b elif operation == "subtract": return a - b elif operation == "multiply": return a * b elif operation == "divide": if b == 0: raise ValueError("Cannot divide by zero") return a // b raise ValueError(f"Unknown operation: {operation}") ``` -------------------------------- ### ToolRunner API Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md The ToolRunner orchestrates the interaction loop: calling the model, executing tools, feeding tool outputs back, and stopping on a final text response. It can be configured with various parameters for controlling the loop. ```APIDOC ## ToolRunner ### Description Runs the interaction loop: call model → execute tools → feed tool outputs back → stop on final text. ### Constructor - **`ToolRunner(client, model, registry, max_iters=8, max_retry=0, parallel_tool_calls=None, on_event=None)`** - `client`: The OpenAI client instance. - `model` (str): The name of the model to use. - `registry` (ToolRegistry): An instance of `ToolRegistry` containing available tools. - `max_iters` (int, optional): Maximum number of iterations for the loop (defaults to 8). - `max_retry` (int, optional): Maximum number of retries for tool calls (defaults to 0). - `parallel_tool_calls` (bool, optional): Whether to allow parallel tool calls. - `on_event` (callable, optional): A callback function to handle events during the run. ### `run(...)` Method - **`run(prompt_or_input, tool_choice=None, instructions=None, extra=None) -> RunnerResult`** - `prompt_or_input` (str | list[dict]): The initial prompt or input items. - `tool_choice` (any, optional): Tool choice configuration passed to the Responses API. - `instructions` (str, optional): Instructions passed to the Responses API. - `extra` (dict, optional): Additional keyword arguments to merge into the request. - Returns: A `RunnerResult` object containing the final text and other details. ### Events (via `on_event`) - `llm.request` - `llm.response` - `tool.call` - `tool.output ``` -------------------------------- ### Set OpenAI API Key Source: https://github.com/hoopengo/openai-resptools/blob/master/README.md Sets the OpenAI API key as an environment variable. This is required for the OpenAI client to authenticate requests. ```bash export OPENAI_API_KEY="..." ``` -------------------------------- ### Process Function Calls from OpenAI Response (Python) Source: https://context7.com/hoopengo/openai-resptools/llms.txt Iterates through a response, identifies function calls, parses arguments, executes the corresponding tool from a registry, and serializes the result. It then constructs an output item for subsequent requests. ```python import json # Assuming 'response' is the OpenAI API response object # Assuming 'registry' is a tool registry object with a 'get' method for item in response.output: if getattr(item, "type", None) == "function_call": tool_name = item.name arguments_json = item.arguments call_id = item.call_id # Parse and validate arguments args = json.loads(arguments_json) # Execute tool tool = registry.get(tool_name) result = tool.call_and_serialize(args) print(f"Tool: {tool_name}") print(f"Args: {args}") print(f"Result: {result}") # Build function_call_output item for next request output_item = { "type": "function_call_output", "call_id": call_id, "output": result, } ``` -------------------------------- ### ToolRegistry API Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md The ToolRegistry is used to store tool definitions and build the necessary payloads for OpenAI's Responses API. It allows for registering tools via decorators or directly adding ToolDef objects. ```APIDOC ## ToolRegistry ### Description Stores tool definitions (`ToolDef`) by name and builds the `tools=[...]` payload for `client.responses.create(...)`. ### Key Methods - **`tool(...)`**: Decorator to register a callable as a tool. - `name` (str, optional): Override tool name (defaults to function name). - `description` (str, optional): Override description (defaults to docstring). - `parameters` (dict, optional): Override JSON schema parameters. - `strict` (bool, optional): If true, schema uses strict mode. - `overwrite` (bool, optional): Allow overwriting an existing tool name. - **`add(tool_def, overwrite=False)`**: Register an existing `ToolDef` object. - `tool_def` (ToolDef): The tool definition to add. - `overwrite` (bool, optional): Allow overwriting an existing tool name. - **`get(name)`**: Get a tool definition by name. Raises `ToolNotFoundError` if not found. - `name` (str): The name of the tool to retrieve. - **`maybe_get(name)`**: Get a tool definition by name, or return `None` if not found. - `name` (str): The name of the tool to retrieve. - **`names()`**: Returns a list of all registered tool names. - **`as_openai_tools()`**: Returns a list of tool payloads formatted for the OpenAI API. - **`allowed_tools_choice(names=None, mode="auto", validate=True)`**: Builds the `tool_choice` payload for the OpenAI API. - `names` (list[str], optional): A list of tool names to allow. If None, all registered tools are considered. - `mode` (str, optional): The mode for tool choice selection (e.g., "auto"). - `validate` (bool, optional): Whether to validate the tool choice against the registered tools. ### Behavior Notes - When instantiated as a subclass, `ToolRegistry` auto-scans itself for public methods. ``` -------------------------------- ### RunnerResult Type Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md Represents the result of a `ToolRunner.run()` or `run()` call, containing the final text output and other relevant information. ```APIDOC ## RunnerResult ### Description Represents the result of a tool running operation. ### Fields - **`text`** (str): The final output text when the model stops calling tools. - **`input_items`** (Sequence[dict]): The full accumulated input items used in the interaction. - **`last_response`** (Any): The SDK response object from the last API call. ``` -------------------------------- ### Error Handling Hierarchy for Tool Operations (Python) Source: https://context7.com/hoopengo/openai-resptools/llms.txt The library defines a hierarchy of exceptions to manage errors during tool registration, validation, execution, and runner operations. This includes `ToolNotFoundError`, `ToolArgumentsError`, `ToolExecutionError`, `RunnerError`, and `RunnerMaxIterationsError`, allowing for robust error handling in tool-calling workflows. ```python from openai_resptools import ToolRegistry from openai_resptools.errors import ( ToolNotFoundError, ToolArgumentsError, ToolExecutionError, RunnerError, RunnerMaxIterationsError, ) registry = ToolRegistry() @registry.tool() def divide(a: int, b: int) -> float: """Divide a by b.""" if b == 0: raise ValueError("Division by zero") return a / b # ToolNotFoundError: Tool name not in registry try: registry.get("nonexistent_tool") except ToolNotFoundError as e: print(f"Tool not found: {e}") # ToolArgumentsError: Invalid or malformed arguments try: tool = registry.get("divide") tool.validate_args({"a": "not_a_number", "b": 5}) except ToolArgumentsError as e: print(f"Invalid arguments: {e}") # ToolExecutionError: Tool function raised an exception try: tool = registry.get("divide") tool.call({"a": 10, "b": 0}) except ToolExecutionError as e: print(f"Execution error: {e}") print(f"Tool name: {e.tool_name}") # RunnerMaxIterationsError: Tool loop exceeded max_iters # This occurs when the model keeps calling tools without producing final text # try: # runner = ToolRunner(client, model="gpt-4o-mini", registry=registry, max_iters=2) # result = runner.run("Keep calling tools forever") # except RunnerMaxIterationsError as e: # print(f"Max iterations reached: {e}") ``` -------------------------------- ### Responses API Function Call Output Format (JSON) Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/overview.md Defines the expected JSON structure for a `function_call_output` item returned by the Responses API. This format is crucial for correctly responding to tool calls made by the model. ```json { "type": "function_call_output", "call_id": "the-call-id-from-the-model", "output": "a JSON string" } ``` -------------------------------- ### RunnerResult Dataclass for Tool-Calling Outputs (Python) Source: https://context7.com/hoopengo/openai-resptools/llms.txt The `RunnerResult` dataclass encapsulates the outcome of a tool-calling operation. It stores the final text response from the model, the complete history of input items exchanged during the conversation, and the last API response object received. This structure is useful for debugging and for continuing conversational flows. ```python from openai_resptools.types import RunnerResult # RunnerResult is returned by runner.run() and run() # result = runner.run("...") # Access final text output # print(result.text) # Access full conversation history (useful for debugging or continuation) # for item in result.input_items: # print(item) # Access the raw OpenAI response object # print(result.last_response.id) # print(result.last_response.usage) # Example structure: # RunnerResult( # text="The answer is 42.", # input_items=[ # {"role": "user", "content": "What is 6 * 7?"}, # {"type": "function_call", "call_id": "call_abc123", "name": "multiply", "arguments": '{"a": 6, "b": 7}'}, # {"type": "function_call_output", "call_id": "call_abc123", "output": "42"}, # ], # last_response= # ) ``` -------------------------------- ### Error Types Source: https://github.com/hoopengo/openai-resptools/blob/master/context7/api.md Defines the custom error types raised by the OpenAI Resptools library to handle specific failure scenarios during tool registration, validation, execution, or the runner loop. ```APIDOC ## Errors ### Description Custom error types used within the OpenAI Resptools library. ### Error List - **`ToolNotFoundError`**: Raised when a requested tool is not found in the registry. - **`ToolArgumentsError`**: Raised when there is an issue with the arguments provided for a tool call (e.g., validation errors). - **`ToolExecutionError`**: Raised when an error occurs during the execution of a tool. - **`RunnerError`**: A base error class for issues related to the `ToolRunner`. - **`RunnerMaxIterationsError`**: Raised when the `ToolRunner` exceeds the maximum number of allowed iterations. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.