Tools
Tools are functions that agents can call to interact with the world. Hugin provides built-in tools for common operations and makes it easy to create custom tools.
Tool Execution Flow
- Agent asks oracle what to do
- Oracle responds with a tool call
- Tool executes and returns result
- Result is pushed to stack
- Agent continues with new context
Built-in Tools
Located in gimle.hugin.tools.builtins:
| Tool | Description |
|---|---|
finish |
Complete the current task |
save_insight |
Save information to long-term memory (artifacts) |
query_artifacts |
Search saved artifacts |
get_artifact_content |
Retrieve a specific artifact |
ask_human |
Request input from a human |
create_branch |
Create a parallel exploration branch |
call_agent |
Invoke another agent |
Creating Custom Tools
A tool consists of two files:
Python Implementation
tools/greet.py:
def greet(stack, name: str, formal: bool = False) -> str:
"""
Greet someone by name.
Args:
stack: The agent's interaction stack (auto-injected)
name: The name of the person to greet
formal: Whether to use formal greeting
Returns:
A greeting string
"""
if formal:
return f"Good day, {name}."
return f"Hello, {name}!"
YAML Definition
tools/greet.yaml:
name: greet
description: Greet someone by name
parameters:
- name: name
type: string
description: The name of the person to greet
required: true
- name: formal
type: boolean
description: Whether to use formal greeting
required: false
default: false
implementation: greet:greet
Parameter Types
| Type | Description |
|---|---|
string |
Text value |
integer |
Whole number |
number |
Decimal number |
boolean |
True/false |
array |
List of values |
object |
Nested structure |
Adding Tools to Agents
Reference tools in your agent config:
# configs/my_agent.yaml
name: my_agent
tools:
# Built-in tools
- builtins.finish:finish
- builtins.save_insight:save_insight
# Custom tools from tools/ directory
- greet:greet
- query_database:query_database
Accessing Context in Tools
The stack parameter provides full access to agent context:
def my_tool(stack, param: str) -> str:
# Access the agent
agent = stack.agent
# Access environment variables
api_key = agent.environment.env_vars.get("API_KEY")
# Access shared state
state = stack.get_shared_state("my_namespace")
# Access storage
storage = agent.environment.storage
# Access other registries
config_registry = agent.environment.config_registry
return "result"
Tool Chaining
Tools can trigger other tools using next_tool:
# tools/process_data.yaml
name: process_data
description: Process and then analyze data
implementation: process_data:process_data
next_tool: analyze_results # Automatically call this tool next
This creates deterministic pipelines where one tool always leads to another.
Interactive Tools
Some tools require human interaction:
def approve_action(stack, action: str) -> str:
"""Request human approval for an action."""
# This will pause and wait for human input
stack.push(AskHuman(
prompt=f"Do you approve this action: {action}?",
options=["yes", "no"]
))
# Execution continues when human responds
return "Waiting for approval..."
Error Handling
Tools should handle errors gracefully:
def query_database(stack, query: str) -> str:
try:
result = execute_query(query)
return f"Query returned {len(result)} rows"
except DatabaseError as e:
return f"Error executing query: {e}"
The result (including errors) is always pushed to the stack, allowing the agent to adapt its behavior.