Tools¶
Tools let agents access external data and perform specialized tasks.
Most users don't need custom tools. Built-in tools handle common needs.
Built-in tools¶
Lumen includes tools automatically:
- TableLookup - Finds relevant tables in your data (see Vector Stores)
- DocumentLookup - Searches uploaded documents (see Vector Stores)
- IterativeTableLookup - Advanced table discovery with embeddings (see Embeddings)
- DbtslLookup - Queries dbt Semantic Layer metrics
You don't need to configure these. Agents use them when needed.
Create a simple tool¶
Turn any function into a tool:
import lumen.ai as lmai
def calculate_average(numbers: list[float]) -> float:
"""
Calculate the average of a list of numbers.
Parameters
----------
numbers : list[float]
Numbers to average
Returns
-------
float
The average
"""
return sum(numbers) / len(numbers)
ui = lmai.ExplorerUI(
data='penguins.csv',
tools=[calculate_average] # (1)!
)
ui.servable()
- Function automatically becomes a tool - the LLM uses your docstring and type hints
Tool that accesses context¶
Tools can read data from context (memory):
from lumen.ai.tools import FunctionTool
def filter_penguins(table) -> dict:
"""
Filter penguins by bill length.
Parameters
----------
table : pd.DataFrame
The penguin data
Returns
-------
dict
Filtered data and summary
"""
filtered = table[table['bill_length_mm'] > 40]
return {
"filtered_table": filtered,
"summary": f"Found {len(filtered)} penguins with bill length > 40mm"
}
tool = FunctionTool(
function=filter_penguins,
requires=["table"], # (1)!
provides=["filtered_table", "summary"], # (2)!
purpose="Filter penguins by bill length"
)
ui = lmai.ExplorerUI(
data='penguins.csv',
tools=[tool]
)
ui.servable()
- Tool reads
tablefrom context - Tool adds
filtered_tableandsummaryto context
Tool that calls an API¶
Wrap external services:
def fetch_weather(location: str) -> str:
"""
Get current weather for a location.
Parameters
----------
location : str
City name
Returns
-------
str
Weather description
"""
import requests
response = requests.get(f"https://api.weather.gov/...")
return f"Weather: {response.json()['temp']}°F"
ui = lmai.ExplorerUI(
data='penguins.csv',
tools=[fetch_weather]
)
ui.servable()
Complete example: Data validation¶
Tool components¶
requires - Context keys the tool needs:
provides - Context keys the tool creates:
purpose - Description for the LLM:
Multiple tools¶
Combine tools for complex workflows:
from lumen.ai.tools import DocumentLookup
def get_stats(table) -> dict:
"""Calculate summary statistics."""
return {
"min": table['bill_length_mm'].min(),
"max": table['bill_length_mm'].max(),
"mean": table['bill_length_mm'].mean(),
}
def filter_species(table, species: str) -> dict:
"""Filter by species name."""
filtered = table[table['species'] == species]
return {
"filtered": filtered,
"count": len(filtered)
}
ui = lmai.ExplorerUI(
data='penguins.csv',
tools=[get_stats, filter_species, DocumentLookup()]
)
ui.servable()
Best practices¶
Write clear docstrings¶
def my_tool(data: list) -> str:
"""
One-line summary of what it does.
Detailed explanation if needed.
Parameters
----------
data : list
What the data represents
Returns
-------
str
What gets returned
"""
Use type hints¶
def process(numbers: list[float], threshold: int) -> dict:
"""Type hints help the LLM call correctly."""
Name parameters clearly¶
# Good
def calculate_average(numbers: list[float]) -> float:
# Bad
def calculate(x: list[float]) -> float:
Keep tools focused¶
# Good - one task
def validate_email(email: str) -> bool:
# Bad - too many tasks
def validate_and_process_user_data(data: dict):
Return structured data when using provides¶
Match provides with return keys
When using provides, your function must return a dict with those keys:
Handle errors gracefully¶
When to use tools vs agents¶
| Use tools when | Use agents when |
|---|---|
| Simple function call | Complex prompting needed |
| No async/await needed | Multiple LLM calls required |
| Wrapping external API | Multi-step reasoning needed |
| Straightforward logic | Sophisticated error handling |
Troubleshooting¶
Tool never gets called¶
The coordinator doesn't think the tool is relevant. Make the purpose clear and specific:
# Bad
purpose = "Does stuff with data"
# Good
purpose = "Validates email addresses and returns True if valid"
Missing required argument¶
Tool expects a context key that doesn't exist. Ensure requires lists correct keys:
Tool fails silently¶
Add error handling and return error messages instead of raising exceptions:
KeyError when using provides¶
Common mistake with provides
Your function must return a dict with all keys listed in provides:
See also¶
- Vector Stores - Configure document search and table discovery tools
- Embeddings - Configure semantic search for tools
- Agents - When to use agents instead of tools