API Reference
This section contains the complete API reference for python-agents.
Client
LLM client with tool calling capabilities.
This module provides the LLMClient class, which wraps the OpenAI API to provide a simple interface for interacting with Large Language Models. It supports automatic tool calling, where Python functions are converted to tool schemas and executed when the LLM requests them.
- class python_agents.client.LLMClient(model_name, base_url='https://openrouter.ai/api/v1')[source]
Bases:
BaseLLMClientClient for interacting with Large Language Models with tool calling support.
LLMClient provides a high-level interface for calling LLMs through the OpenAI API. It automatically handles tool registration, schema generation from Python functions, and tool execution when requested by the LLM. By default, it uses OpenRouter as the API endpoint, but can be configured for any OpenAI-compatible service.
- client
Underlying async OpenAI client.
- Type:
AsyncOpenAI
Example
Basic usage without tools:
client = LLMClient("openai/gpt-4.1-mini") response = await client.invoke("What is 2+2?") print(response.message.content)
Using tools with automatic function calling:
def calculator(operation: str, a: int, b: int) -> int: '''Perform arithmetic operations. Args: operation: The operation ('+', '-', '*', '/') a: First number b: Second number Returns: Result of the operation ''' if operation == "+": return a + b # ... more operations client = LLMClient("openai/gpt-4-turbo") client.add_tool(calculator) response = await client.invoke("What is 15 + 27?") # LLM will automatically call calculator tool
- __init__(model_name, base_url='https://openrouter.ai/api/v1')[source]
Initialize the LLM client.
- Parameters:
model_name (str, optional) – Default model name to use for requests. Can be overridden per request. Format depends on the API provider (e.g., “openai/gpt-4-turbo” for OpenRouter). Defaults to None.
base_url (str, optional) – Base URL for the OpenAI-compatible API. Defaults to “https://openrouter.ai/api/v1”.
Note
Requires OPENAI_API_KEY environment variable to be set for authentication. When using OpenRouter, this should be your OpenRouter API key.
- add_mcp_server(mcp_client)[source]
Register an MCPClient as a tool provider.
The tools available from the MCPClient will be made available to the LLM for function calling.
- Parameters:
mcp_client (MCPClient) – An instance of MCPClient connected to an MCP server.
- add_tool(func)[source]
Register a Python function as a tool that the LLM can call.
The function is automatically converted to an OpenAI function schema using introspection of the function signature, type hints, and docstring. The LLM can then request to call this tool during conversation.
- Parameters:
func (callable) – A Python function to register as a tool. The function should have: - Type hints for all parameters - A clear docstring describing what it does - A descriptive name All parameters must be JSON-serializable types (str, int, float, bool).
Example:
def get_weather(location: str, units: str = "celsius") -> str: '''Get the weather for a location. Args: location: City name units: Temperature units (celsius or fahrenheit) ''' # Implementation return f"Weather in {location}: 20°{units[0].upper()}" client.add_tool(get_weather)
Note
The function will be called synchronously when the LLM requests it, and the result will be stringified before being returned to the LLM.
- async invoke(query, model_name=None, verbose=False)[source]
Send a query to the LLM and handle any tool calls.
This is the main method for interacting with the LLM. It accepts various input formats, calls the LLM, automatically executes any requested tool calls, and returns the final response. The method handles one round of tool calling - if the LLM requests tools, they are all executed, and then a final LLM call is made with the tool results.
- Parameters:
query (list[Message] | Message | str) – The input to send to the LLM. Can be: - str: Converted to a single user message - Message: Single message to send - list[Message]: Full conversation history
model_name (str, optional) – Model to use for this request. Overrides the default model_name set during initialization. Defaults to None.
verbose (bool, optional) – If True, prints response content to stdout when no tools are called. Defaults to False.
- Returns:
- The LLM’s response containing the message content.
Access the text response via response.message.content.
- Return type:
ChatCompletionChoice
- Raises:
ValueError – If query is not a str, Message, or list[Message].
RuntimeError – If the LLM requests an unregistered tool.
Example:
# String query response = await client.invoke("Hello!") # With message history messages = [ Message(role="system", content="You are helpful"), Message(role="user", content="Hi") ] response = await client.invoke(messages) # Override model response = await client.invoke("Quick question", model_name="openai/gpt-3.5-turbo")
Note
This method only handles ONE round of tool calling. For multi-step reasoning with multiple tool call rounds, use ReactAgent instead.
Agents
REACT agent implementation for step-by-step reasoning and acting.
This module provides the ReactAgent class, which implements the REACT (Reasoning and Acting) pattern for AI agents. REACT agents combine reasoning about problems with taking actions (via tool calls) in an iterative loop, continuing until a task is completed or a maximum number of iterations is reached.
- class python_agents.agents.ReactAgent(client, max_iterations=10)[source]
Bases:
objectAgent that uses iterative reasoning and acting (REACT) to solve tasks.
ReactAgent implements the REACT pattern where the agent follows a loop of: 1. Reasoning about what to do next 2. Acting by calling tools to gather information or perform actions 3. Observing the results 4. Repeating until the task is complete
The agent uses a system prompt that guides it to think step-by-step, call tools when needed, and provide a final answer when done. The loop continues until the agent includes “Final Answer:” in its response or max_iterations is reached.
- client
The LLM client used to interact with the language model. Should have any required tools already registered via add_tool().
- Type:
Example
Basic usage with tools:
def search_web(query: str) -> str: '''Search the web for information. Args: query: Search query string Returns: Search results as text ''' # Implementation return "Search results..." client = LLMClient("openai/gpt-4-turbo") client.add_tool(search_web) agent = ReactAgent(client, max_iterations=5) result = await agent.run("What is the capital of France?", verbose=True) print(result) # Will include "Final Answer: Paris"
With multiple tools and complex reasoning:
agent = ReactAgent(client, max_iterations=10) result = await agent.run( "Find the weather in Tokyo and calculate the temperature in Fahrenheit", verbose=True ) # Agent will: # 1. Think about what tools to use # 2. Call weather tool for Tokyo # 3. Observe the celsius result # 4. Call calculator to convert to Fahrenheit # 5. Provide final answer with both values
- async run(task, verbose=False)[source]
Run the agent on a task using iterative reasoning and acting.
This method executes the REACT loop: the agent reasons about the task, calls tools as needed, observes results, and repeats until it provides a final answer or reaches max_iterations. The conversation history is maintained across iterations, with the REACT system prompt prepended to guide the agent’s behavior.
- Parameters:
- Returns:
- The final response from the agent, which should include “Final Answer:”
followed by the result. If max_iterations is reached before completion, returns the last response received.
- Return type:
Example:
# Simple task agent = ReactAgent(client) result = await agent.run("What is 25 * 4?") # Complex task with verbose output result = await agent.run( "Research the population of New York City and compare it to Los Angeles", verbose=True ) # Prints iteration progress and all agent reasoning steps
Note
The agent’s iteration_count and task_completed attributes are set during execution
If the agent doesn’t complete within max_iterations, task_completed will be False
All conversation history (including tool calls and results) is maintained throughout
The REACT system prompt is automatically added as the first message
Tools
Tool schema generation and conversion utilities.
This module provides utilities for converting Python functions and MCP tools into OpenAI-compatible tool schemas. It handles automatic schema generation through function introspection, extracting type information from annotations and documentation from docstrings.
- class python_agents.tools.ToolSchema[source]
Bases:
TypedDict-
function:
ToolFunctionSchema
-
function:
- python_agents.tools.create_tool_schema(func)[source]
Generate an OpenAI tool schema from a Python function.
This function uses introspection to automatically create a tool schema in OpenAI’s function calling format. It extracts parameter information from the function signature, including type hints and default values, and uses the function’s docstring as the tool description.
- Type mapping:
int → “integer”
float → “number”
str → “string”
bool → “boolean”
Other types → “string” (default)
Parameters without default values are marked as required in the schema.
- Parameters:
func (callable) – A Python function to convert into a tool schema. Should have type hints for parameters and a descriptive docstring.
- Returns:
A tool schema in OpenAI format with structure:
{ "type": "function", "function": { "name": str, "description": str, "parameters": { "type": "object", "properties": dict, "required": list[str] } } }
- Return type:
Example
Converting a simple function to a tool schema:
def add_numbers(a: int, b: int) -> int: '''Add two numbers together.''' return a + b schema = create_tool_schema(add_numbers) # Returns: # { # "type": "function", # "function": { # "name": "add_numbers", # "description": "Add two numbers together.", # "parameters": { # "type": "object", # "properties": { # "a": {"type": "integer"}, # "b": {"type": "integer"} # }, # "required": ["a", "b"] # } # } # }
With optional parameters:
def greet(name: str, greeting: str = "Hello") -> str: '''Greet someone with a custom message.''' return f"{greeting}, {name}!" schema = create_tool_schema(greet) # required list will only contain ["name"]
- python_agents.tools.convert_tool_format(tool)[source]
Convert an MCP tool to OpenAI tool format.
This function transforms tools from the Model Context Protocol (MCP) format into OpenAI’s function calling schema format. It maps the MCP tool’s inputSchema directly to OpenAI’s parameters structure.
- Parameters:
tool –
An MCP tool object with the following attributes:
name (str): The tool’s name
description (str): Description of what the tool does
inputSchema (dict): JSON schema for the tool’s input parameters, containing “properties” and optionally “required” fields
- Returns:
A tool schema in OpenAI format with structure:
{ "type": "function", "function": { "name": str, "description": str, "parameters": { "type": "object", "properties": dict, "required": list[str] } } }
- Return type:
Example
Converting an MCP tool:
from types import SimpleNamespace mcp_tool = SimpleNamespace( name="search_database", description="Search the database for records", inputSchema={ "properties": { "query": {"type": "string"}, "limit": {"type": "integer"} }, "required": ["query"] } ) openai_tool = convert_tool_format(mcp_tool) # Returns OpenAI-compatible tool schema
Note
If the MCP tool’s inputSchema doesn’t specify a “required” field, an empty list is used for the required parameters.
Message
Message structure for LLM conversations.
This module defines the Message TypedDict, which represents individual messages in conversations with Large Language Models. Messages can represent user input, assistant responses, system instructions, or tool call results.
- class python_agents.message.Message[source]
Bases:
TypedDictTypedDict representing a message in an LLM conversation.
Message defines the structure for all messages exchanged in conversations with language models. It supports different message roles (user, assistant, system, tool) and includes optional fields for tool calling functionality. This structure is compatible with the OpenAI chat completions API format.
- role
The role of the message sender. Valid values are: - “user”: Messages from the user/human - “assistant”: Responses from the LLM - “system”: System instructions that guide the LLM’s behavior - “tool”: Results returned from tool function calls
- Type:
- content
The text content of the message. For tool messages, this contains the stringified result of the tool execution.
- Type:
- tool_call_id
The ID of the tool call this message is responding to. Required for role=”tool” messages, links the tool result back to the original tool call request.
- Type:
NotRequired[str]
- name
The name of the tool that was called. Used with role=”tool” to identify which tool produced this result.
- Type:
NotRequired[str]
- tool_calls
List of tool calls requested by the assistant. Present when role=”assistant” and the LLM wants to call one or more tools. Each tool call contains the function name, arguments, and a unique ID.
- Type:
NotRequired[list[Any]]
Example
Creating different message types:
# User message user_msg = Message(role="user", content="What is the weather in Paris?") # Assistant message without tools assistant_msg = Message(role="assistant", content="Let me check that for you.") # System message system_msg = Message( role="system", content="You are a helpful weather assistant." ) # Tool result message tool_msg = Message( role="tool", content="Temperature: 18°C, Conditions: Partly cloudy", tool_call_id="call_abc123", name="get_weather" ) # Assistant message with tool calls (typically created by LLM response) assistant_with_tools = Message( role="assistant", content="I'll check the weather for you.", tool_calls=[{ "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": '{"location": "Paris"}' } }] )
Note
NotRequired fields are optional and may be omitted when not needed
Tool-related fields (tool_call_id, name, tool_calls) are only used in specific contexts: tool_call_id and name for tool messages, tool_calls for assistant messages
This structure is passed to and returned from LLMClient.invoke() and used throughout the conversation history in ReactAgent
Memory
Memory management for conversation history in agents.
This module provides abstract and concrete implementations for storing and managing conversation history (messages) in AI agents. Memory classes handle message storage, retrieval, and manipulation for maintaining context across agent interactions.
- class python_agents.memory.BaseMemory[source]
Bases:
ABCAbstract base class for memory implementations.
BaseMemory defines the interface that all memory implementations must follow. It provides methods for adding messages, clearing history, and managing system messages. Subclasses must implement all abstract methods to provide specific storage strategies.
- abstractmethod add_message(message)[source]
Add a message to the conversation history.
- Parameters:
message (Message) – The message to add to memory. Should contain role, content, and optionally tool call information.
- abstractmethod clear()[source]
Clear all messages from memory.
Removes all stored messages, resetting the conversation history to empty state.
- abstractmethod insert_system_message(message)[source]
Insert or replace a system message at the beginning of conversation history.
System messages provide instructions or context to the LLM and should always appear first in the message list. This method either inserts a new system message or replaces an existing one.
- Parameters:
message (Message) – The system message to insert. Should have role=”system”.
- class python_agents.memory.SimpleMemory[source]
Bases:
BaseMemorySimple in-memory storage for conversation history.
SimpleMemory provides a basic list-based implementation of conversation history storage. Messages are stored in chronological order in a Python list, with no size limits or special processing. This implementation is suitable for most use cases where conversation history fits in memory.
Example
Basic usage with message storage:
memory = SimpleMemory() memory.add_message(Message(role="user", content="Hello")) memory.add_message(Message(role="assistant", content="Hi there!")) print(len(memory.messages)) # 2 memory.clear() print(len(memory.messages)) # 0
- add_message(message)[source]
Add a message to the end of the conversation history.
Messages are appended in the order they are added, maintaining chronological order.
- Parameters:
message (Message) – The message to add. Can be user, assistant, system, or tool message.
- insert_system_message(message)[source]
Insert or replace the system message at the beginning of the conversation.
This method ensures the system message is always first in the message list. If a system message already exists at position 0, it is replaced. Otherwise, the new system message is inserted at the beginning.
- Parameters:
message (Message) – The system message to insert. Should have role=”system”.
Note
System messages provide instructions or context to the LLM and must appear before any user or assistant messages to be effective.
Utilities
Utility functions for the python-agents library.
This module provides helper functions for common tasks like formatting and displaying data structures in a human-readable format.
- python_agents.utils.pretty_print(data)[source]
Print a dictionary in a formatted, human-readable JSON format.
This utility function converts a dictionary to JSON and prints it with sorted keys and 4-space indentation, making it easier to read complex nested data structures. Commonly used for debugging or displaying API responses, message histories, and tool call results.
- Parameters:
data (dict) – The dictionary to print. Can contain nested dictionaries, lists, strings, numbers, booleans, and None values - any JSON-serializable types.
Example
Displaying simple data:
data = {"name": "Alice", "age": 30, "city": "Paris"} pretty_print(data) # Output: # { # "age": 30, # "city": "Paris", # "name": "Alice" # }
Displaying nested conversation messages:
message = { "role": "assistant", "content": "Hello!", "metadata": { "model": "gpt-4", "tokens": 5 } } pretty_print(message) # Output: # { # "content": "Hello!", # "metadata": { # "model": "gpt-4", # "tokens": 5 # }, # "role": "assistant" # }
Displaying tool call information:
tool_call = { "id": "call_abc123", "function": { "name": "get_weather", "arguments": {"location": "Tokyo"} } } pretty_print(tool_call)
Note
Keys are automatically sorted alphabetically for consistent output
Uses 4-space indentation for readability
Non-JSON-serializable objects will raise a TypeError
Output is printed directly to stdout, not returned