Source code for autogen_ext.tools.http._http_tool
import re
from typing import Any, Literal, Optional, Type
import httpx
from autogen_core import CancellationToken, Component
from autogen_core.tools import BaseTool
from json_schema_to_pydantic import create_model
from pydantic import BaseModel, Field
from typing_extensions import Self
class HttpToolConfig(BaseModel):
name: str
"""
The name of the tool.
"""
description: Optional[str]
"""
A description of the tool.
"""
scheme: Literal["http", "https"] = "http"
"""
The scheme to use for the request.
"""
host: str
"""
The URL to send the request to.
"""
port: int
"""
The port to send the request to.
"""
path: str = Field(default="/")
"""
The path to send the request to. defaults to "/"
The path can accept parameters, e.g. "/{param1}/{param2}".
These parameters will be templated from the inputs args, any additional parameters will be added as query parameters or the body of the request.
"""
method: Optional[Literal["GET", "POST", "PUT", "DELETE", "PATCH"]] = "POST"
"""
The HTTP method to use, will default to POST if not provided.
"""
headers: Optional[dict[str, Any]]
"""
A dictionary of headers to send with the request.
"""
json_schema: dict[str, Any]
"""
A JSON Schema object defining the expected parameters for the tool.
Path parameters MUST also be included in the json_schema. They must also MUST be set to string
"""
return_type: Optional[Literal["text", "json"]] = "text"
"""
The type of response to return from the tool.
"""
[docs]
class HttpTool(BaseTool[BaseModel, Any], Component[HttpToolConfig]):
"""A wrapper for using an HTTP server as a tool.
Args:
name (str): The name of the tool.
description (str, optional): A description of the tool.
scheme (str): The scheme to use for the request. Must be either "http" or "https".
host (str): The host to send the request to.
port (int): The port to send the request to.
path (str, optional): The path to send the request to. Defaults to "/".
Can include path parameters like "/{param1}/{param2}" which will be templated from input args.
method (str, optional): The HTTP method to use, will default to POST if not provided.
Must be one of "GET", "POST", "PUT", "DELETE", "PATCH".
headers (dict[str, Any], optional): A dictionary of headers to send with the request.
json_schema (dict[str, Any]): A JSON Schema object defining the expected parameters for the tool.
Path parameters must also be included in the schema and must be strings.
return_type (Literal["text", "json"], optional): The type of response to return from the tool.
Defaults to "text".
.. note::
This tool requires the :code:`http-tool` extra for the :code:`autogen-ext` package.
To install:
.. code-block:: bash
pip install -U "autogen-agentchat" "autogen-ext[http-tool]"
Example:
Simple use case::
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.http import HttpTool
# Define a JSON schema for a base64 decode tool
base64_schema = {
"type": "object",
"properties": {
"value": {"type": "string", "description": "The base64 value to decode"},
},
"required": ["value"],
}
# Create an HTTP tool for the httpbin API
base64_tool = HttpTool(
name="base64_decode",
description="base64 decode a value",
scheme="https",
host="httpbin.org",
port=443,
path="/base64/{value}",
method="GET",
json_schema=base64_schema,
)
async def main():
# Create an assistant with the base64 tool
model = OpenAIChatCompletionClient(model="gpt-4")
assistant = AssistantAgent("base64_assistant", model_client=model, tools=[base64_tool])
# The assistant can now use the base64 tool to decode the string
response = await assistant.on_messages(
[TextMessage(content="Can you base64 decode the value 'YWJjZGU=', please?", source="user")],
CancellationToken(),
)
print(response.chat_message.content)
asyncio.run(main())
"""
component_type = "tool"
component_provider_override = "autogen_ext.tools.http.HttpTool"
component_config_schema = HttpToolConfig
def __init__(
self,
name: str,
host: str,
port: int,
json_schema: dict[str, Any],
headers: Optional[dict[str, Any]] = None,
description: str = "HTTP tool",
path: str = "/",
scheme: Literal["http", "https"] = "http",
method: Literal["GET", "POST", "PUT", "DELETE", "PATCH"] = "POST",
return_type: Literal["text", "json"] = "text",
) -> None:
self.server_params = HttpToolConfig(
name=name,
description=description,
host=host,
port=port,
path=path,
scheme=scheme,
method=method,
headers=headers,
json_schema=json_schema,
return_type=return_type,
)
# Use regex to find all path parameters, we will need those later to template the path
path_params = {match.group(1) for match in re.finditer(r"{([^}]*)}", path)}
self._path_params = path_params
# Create the input model from the modified schema
input_model = create_model(json_schema)
# Use Any as return type since HTTP responses can vary
base_return_type: Type[Any] = object
super().__init__(input_model, base_return_type, name, description)
[docs]
def _to_config(self) -> HttpToolConfig:
copied_config = self.server_params.model_copy()
return copied_config
[docs]
@classmethod
def _from_config(cls, config: HttpToolConfig) -> Self:
copied_config = config.model_copy().model_dump()
return cls(**copied_config)
[docs]
async def run(self, args: BaseModel, cancellation_token: CancellationToken) -> Any:
"""Execute the HTTP tool with the given arguments.
Args:
args: The validated input arguments
cancellation_token: Token for cancelling the operation
Returns:
The response body from the HTTP call in JSON format
Raises:
Exception: If tool execution fails
"""
model_dump = args.model_dump()
path_params = {k: v for k, v in model_dump.items() if k in self._path_params}
# Remove path params from the model dump
for k in self._path_params:
model_dump.pop(k)
path = self.server_params.path.format(**path_params)
url = httpx.URL(
scheme=self.server_params.scheme,
host=self.server_params.host,
port=self.server_params.port,
path=path,
)
async with httpx.AsyncClient() as client:
match self.server_params.method:
case "GET":
response = await client.get(url, headers=self.server_params.headers, params=model_dump)
case "PUT":
response = await client.put(url, headers=self.server_params.headers, json=model_dump)
case "DELETE":
response = await client.delete(url, headers=self.server_params.headers, params=model_dump)
case "PATCH":
response = await client.patch(url, headers=self.server_params.headers, json=model_dump)
case _: # Default case POST
response = await client.post(url, headers=self.server_params.headers, json=model_dump)
match self.server_params.return_type:
case "text":
return response.text
case "json":
return response.json()
case _:
raise ValueError(f"Invalid return type: {self.server_params.return_type}")