A flexible toolkit for managing Pipecat function tools with OpenAI-style metadata
Project description
SpaceStep Tools
A flexible toolkit for managing Pipecat function tools with OpenAI-style metadata. This library provides utilities for managing function tools and handlers for Pipecat AI applications, with support for dynamic tool loading and custom tool registration.
Features
- Built-in Tools: Comes with pre-configured tools for call management and scheduling
- Dynamic Tool Loading: Register custom tools from Python files and YAML configurations
- OpenAI-Compatible: Generate OpenAI-style function metadata automatically
- Type Safety: Full type hints and validation
- CLI Interface: Command-line tools for managing and validating tools
- Extensible Architecture: Easy to add new tools and modify existing ones
Installation
pip install spacestep-tools
For development:
pip install spacestep-tools[dev]
Quick Start
Basic Usage
from pipecat_tools import ToolManager
# Initialize the tool manager
manager = ToolManager()
# Get available tools
available_tools = manager.get_supported_function_names()
print(f"Available tools: {available_tools}")
# Get OpenAI-compatible schema for specific tools
tools_schema = manager.get_tools_schema(["transfer_call", "end_call"])
# Get function handlers
handlers = manager.get_handlers(["transfer_call", "end_call"])
Using Built-in Tools
The library comes with several built-in tools:
Call Management Tools
transfer_call: Transfer the call to a licensed agentawait_call_transfer: Handle call transfer statesend_call: End the current callget_weekday: Get the day of the week for a given date
Scheduling Tools
get_available_time_slots: Get available appointment slots for datesbook_appointment: Book an appointment for a client
from pipecat_tools import get_functions_meta, get_function_handlers
# Get schema for scheduling tools
schema = get_functions_meta(["get_available_time_slots", "book_appointment"])
# Get handlers
handlers = get_function_handlers(["get_available_time_slots", "book_appointment"])
Adding Custom Tools
Method 1: Directory-based Registration
Create a directory with Python files containing your custom tool functions:
File: my_tools/weather.py
from pipecat.services.llm_service import FunctionCallParams
from pipecat.frames.frames import FunctionCallResultProperties
import httpx
async def get_weather(params: FunctionCallParams):
"""
Get current weather for a city.
Args:
params: Pipecat function call parameters containing:
- city (str): Name of the city
"""
city = params.arguments["city"]
# Your weather API integration here
try:
# Example API call
async with httpx.AsyncClient() as client:
response = await client.get(f"https://api.weather.com/current?city={city}")
weather_data = response.json()
result = f"Current weather in {city}: {weather_data['description']}, {weather_data['temp']}°C"
except Exception as e:
result = f"Failed to get weather for {city}: {str(e)}"
properties = FunctionCallResultProperties(run_llm=True)
await params.result_callback(result, properties=properties)
async def get_forecast(params: FunctionCallParams):
"""
Get weather forecast for a city.
Args:
params: Pipecat function call parameters containing:
- city (str): Name of the city
- days (int): Number of days to forecast (default: 3)
"""
city = params.arguments["city"]
days = params.arguments.get("days", 3)
# Your forecast API integration here
result = f"Weather forecast for {city} for the next {days} days: [forecast data]"
properties = FunctionCallResultProperties(run_llm=True)
await params.result_callback(result, properties=properties)
File: my_tools_config.yaml
get_weather:
description: "Get current weather information for a specified city"
parameters:
type: object
properties:
city:
type: string
description: "Name of the city to get weather for"
required:
- city
get_forecast:
description: "Get weather forecast for a specified city"
parameters:
type: object
properties:
city:
type: string
description: "Name of the city to get forecast for"
days:
type: integer
description: "Number of days to forecast (1-7)"
minimum: 1
maximum: 7
required:
- city
Registration:
from pipecat_tools import ToolManager
manager = ToolManager()
# Register custom tools
manager.register_tools_from_directory(
handlers_dir="./my_tools",
config_file="./my_tools_config.yaml"
)
# Now you can use your custom tools
schema = manager.get_tools_schema(["get_weather", "get_forecast"])
handlers = manager.get_handlers(["get_weather", "get_forecast"])
Method 2: YAML-only Configuration
If you only need to modify metadata for existing tools:
manager = ToolManager()
manager.register_tools_from_config("./custom_config.yaml")
Method 3: Using the Functional API
from pipecat_tools import register_custom_tools
# Register tools globally
register_custom_tools(
handlers="./my_tools",
function_configurations="./my_tools_config.yaml"
)
# Now use the global functions
from pipecat_tools import get_functions_meta, get_function_handlers
schema = get_functions_meta(["get_weather"])
handlers = get_function_handlers(["get_weather"])
Tool Function Requirements
When creating custom tools, follow these requirements:
1. Function Signature
async def your_tool_name(params: FunctionCallParams):
"""
Your tool description.
Args:
params: Pipecat function call parameters containing:
- param1 (type): Description
- param2 (type): Description
"""
# Extract parameters
param1 = params.arguments["param1"]
param2 = params.arguments.get("param2", "default_value")
# Your logic here
result = "Your result"
# Send result back
properties = FunctionCallResultProperties(run_llm=True)
await params.result_callback(result, properties=properties)
2. YAML Configuration Schema
your_tool_name:
description: "Clear description of what the tool does"
parameters:
type: object
properties:
param1:
type: string # or number, integer, boolean, array, object
description: "Description of parameter"
param2:
type: integer
description: "Description of optional parameter"
minimum: 1
maximum: 100
required:
- param1
3. Parameter Types
Supported parameter types:
string: Text valuesnumber: Floating-point numbersinteger: Whole numbersboolean: True/false valuesarray: Lists of valuesobject: Complex nested objects
4. Parameter Validation
Add validation constraints:
parameters:
type: object
properties:
email:
type: string
format: email
age:
type: integer
minimum: 0
maximum: 120
options:
type: array
items:
type: string
minItems: 1
maxItems: 5
Environment Variables
Managing Per‑Function Constants
Some tools (such as get_available_time_slots and
book_appointment) need non‑public configuration values—typically webhook
URLs. Rather than hard‑coding those strings or passing them as user‑visible
parameters, SpaceStep Tools ships a lightweight helper module
spacestep_tools.consts that keeps an in‑memory registry keyed by
function → constant → value.
Loading constants at startup
from pipecat_tools import (
set_constants,
get_required_constants,
)
# Load all *.json files from the ./constants directory
set_constants("./custom/tools/constants")
# Optionally verify that every constant has been provided
missing = get_required_constants(
["get_available_time_slots", "book_appointment"]
)
if missing:
raise RuntimeError(f"Unset constants: {missing}")
Each JSON file should be named after the function and contain a flat object whose keys are constant names. Example:
constants/book_appointment.json
{
"webhook_url": "https://api.example.com/appointments"
}
Accessing constants inside your tool
import inspect
from pipecat_tools import get_constant
from pipecat.services.llm_service import FunctionCallParams
async def book_appointment(params: FunctionCallParams):
# Retrieve the constant for this function
func_name = inspect.currentframe().f_code.co_name
webhook_url = get_constant(func_name, "webhook_url")
# ... use webhook_url to call downstream service ...
Additional helper functions:
get_all_set_constants()– returns every constant that already has a value.get_constant(fn, name)– fetch a single constant value or raiseKeyErrorif the pair is not registered.
Note
These constants are strictly internal implementation details; they never appear in the tool's public parameter schema nor can end‑users override them at runtime.
CLI Usage
The library includes a command-line interface:
# List all available tools
pipecat-tools list
# Get detailed info about a specific tool
pipecat-tools info transfer_call
# Validate tools
pipecat-tools validate transfer_call end_call
# Register custom tools
pipecat-tools register --handlers-dir ./my_tools --config-file ./config.yaml
Advanced Usage
Custom Tool Manager
import logging
from pipecat_tools import ToolManager
# Custom logger
logger = logging.getLogger("my_app")
manager = ToolManager(logger=logger)
# Get tool information
tool_info = manager.get_tool_info("transfer_call")
print(f"Tool: {tool_info['name']}")
print(f"Description: {tool_info['description']}")
# List all tools with details
all_tools = manager.list_tools()
for tool in all_tools:
print(f"{tool['name']}: {tool['description']}")
# Validate multiple tools
validation_results = manager.validate_tools(["tool1", "tool2", "nonexistent"])
for name, is_valid in validation_results.items():
print(f"{name}: {'✓' if is_valid else '✗'}")
Error Handling
from pipecat_tools import ToolManager
manager = ToolManager()
try:
manager.register_tools_from_directory("./nonexistent_dir")
except ValueError as e:
print(f"Registration failed: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
Integration with Pipecat
from pipecat.pipeline.pipeline import Pipeline
from pipecat.services.llm_service import LLMService
from pipecat_tools import ToolManager
# Initialize tool manager
tool_manager = ToolManager()
tool_manager.register_tools_from_directory("./my_tools", "./tools_config.yaml")
# Get tools for your pipeline
available_tools = ["transfer_call", "get_weather", "book_appointment"]
schema = tool_manager.get_tools_schema(available_tools)
handlers = tool_manager.get_handlers(available_tools)
# Configure your LLM service with tools
llm_service = LLMService(
model="gpt-4",
tools=schema,
tool_handlers=handlers
)
# Add to your pipeline
pipeline = Pipeline([
# ... other services
llm_service,
# ... other services
])
Best Practices
1. Tool Naming
- Use descriptive, action-oriented names:
get_weather,book_appointment,send_email - Use snake_case for function names
- Avoid generic names like
processorhandle
2. Documentation
- Always provide clear docstrings
- Document all parameters and their types
- Include usage examples in docstrings
3. Error Handling
- Handle errors gracefully in your tool functions
- Return meaningful error messages
- Log errors for debugging
4. Configuration
- Use environment variables for API keys and URLs
- Provide sensible defaults
- Validate configuration at startup
5. Testing
- Write unit tests for your custom tools
- Test both success and error scenarios
- Mock external API calls
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Changelog
v0.1.0
- Initial release
- Built-in call management and scheduling tools
- Dynamic tool loading support
- CLI interface
- Comprehensive documentation
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spacestep_tools-0.1.3.tar.gz.
File metadata
- Download URL: spacestep_tools-0.1.3.tar.gz
- Upload date:
- Size: 24.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
469044472383d23e8814cfbd26242d4bc6e44d467d5017eda496daf0d7ec58cf
|
|
| MD5 |
86ca4d409a727d437c4d61bf67e427b0
|
|
| BLAKE2b-256 |
2165048bf32a9857e28757b8d0c603c21663429027cefd5d8738740c4bb300ba
|
File details
Details for the file spacestep_tools-0.1.3-py3-none-any.whl.
File metadata
- Download URL: spacestep_tools-0.1.3-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b6f3ef60972141fe980e14109d311ce742c4add15e4565aea377ffb12d1a974
|
|
| MD5 |
8a6f9f8cd02508c405cc5bd39c44d832
|
|
| BLAKE2b-256 |
79e7da86b6c6b9b772572f6d9223938c604e814be75397ea638da7cbfbf86906
|