Development
This guide is for developers who want to extend Huf’s functionality, create custom integrations, or contribute to the project.
Prerequisites
Required knowledge:
- Frappe Framework development experience
- Python programming
- Understanding of DocTypes, hooks, and permissions
- Basic knowledge of LLMs and AI agents
If you’re new to Frappe: Start with the Frappe Framework Documentation before extending Huf.
Project Structure
Huf follows standard Frappe application structure:
huf/
├── huf/ # Main Python module
│ ├── doctype/ # DocType definitions
│ │ ├── agent/
│ │ ├── ai_provider/
│ │ ├── ai_model/
│ │ └── agent_tool_function/
│ └── ai/ # Core AI integration
│ ├── agent_integration.py
│ ├── conversation_manager.py
│ ├── tool_discovery.py # @agent_tool decorator
│ └── providers/
│ └── litellm.py
├── hooks.py
├── install.py
└── www/ # Web assetsExtension Points
1. Publishing Tools from Your App
The easiest way to extend Huf is by publishing tools from your Frappe app.
Use the @agent_tool decorator:
from huf.ai.tool_discovery import agent_tool
@agent_tool
def my_custom_tool(param1: str, param2: int) -> dict:
"""
Description of what this tool does.
Args:
param1: Description of param1
param2: Description of param2
Returns:
dict: Result data
"""
# Your implementation
return {"result": "data"}See: Publishing Tools for complete guide.
2. Custom Tool Functions
Create tools manually via Agent Tool Function DocType:
- Write Python function in your app
- Create Agent Tool Function record
- Link function via Function Path
- Assign to agents
See: Creating Custom Tools for details.
3. Frappe Hooks
Extend Huf using Frappe’s hook system:
In your app’s hooks.py:
# Before agent runs
agent_before_run = "my_app.hooks.validate_agent_config"
# After agent runs
agent_after_run = "my_app.hooks.log_custom_metrics"
# Custom tool execution
agent_tool_call = "my_app.hooks.handle_custom_tool"Example hook implementation:
# my_app/hooks.py
def validate_agent_config(agent, prompt, context):
"""Validate agent configuration before run."""
if agent.name == "Critical Agent":
# Add custom validation
if not agent.custom_field:
frappe.throw("Custom field required for critical agents")4. Custom Providers
While Huf uses LiteLLM for most providers, you can add custom provider implementations:
Create provider module:
# huf/ai/providers/custom.py
async def run(agent, enhanced_prompt, provider, model, context=None):
"""Custom provider implementation."""
# Your custom logic
response = await your_custom_api_call(enhanced_prompt)
return {
"response": response.text,
"tokens": response.tokens_used,
"cost": response.cost
}Register in routing:
# huf/ai/run.py
if provider.name == "Custom Provider":
from huf.ai.providers import custom
return await custom.run(...)5. DocType Customizations
Extend Huf DocTypes using Frappe’s customization system:
Add custom fields:
- Navigate to Customize Form
- Add fields to Agent, AI Provider, etc.
- Use in hooks and scripts
Add custom scripts:
- Client scripts for UI behavior
- Server scripts for validation
- Print formats for reports
6. API Extensions
Create custom API endpoints that use Huf:
# my_app/api/agent_extensions.py
import frappe
from huf.ai.agent_integration import AgentManager
@frappe.whitelist()
def custom_agent_workflow(data):
"""Custom workflow using Huf agents."""
# Get agent
manager = AgentManager("My Agent")
# Run agent
result = manager.run_sync(data["prompt"])
# Custom processing
processed = your_custom_logic(result)
return processedDevelopment Setup
1. Clone Repository
git clone https://github.com/tridz-dev/agent_flo.git
cd huf2. Install in Bench
cd /path/to/your/bench
bench get-app huf /path/to/huf
bench --site your-site install-app huf
bench setup requirements3. Development Mode
# Start bench
bench start
# Run migrations after changes
bench --site your-site migrate
# Clear cache
bench --site your-site clear-cache4. Testing
# Run tests (if available)
bench --site your-site run-tests --app huf
# Test in console
bench --site your-site consoleCore Components
Agent Integration (agent_integration.py)
AgentManager class:
- Prepares agents for execution
- Manages conversation context
- Handles tool serialization
- Routes to providers
Key methods:
prepare_agent(): Load agent configurationrun_sync(): Execute agent synchronouslyget_conversation(): Retrieve conversation history
Conversation Manager (conversation_manager.py)
Handles:
- Conversation persistence
- Message history
- Session management
- Context building
Key methods:
get_or_create_conversation(): Get conversation sessionadd_message(): Add message to conversationget_history(): Retrieve conversation history
Tool Discovery (tool_discovery.py)
@agent_tool decorator:
- Scans apps for decorated functions
- Creates Agent Tool Function records
- Syncs on app install/migrate
Key functions:
agent_tool(): Decorator functiondiscover_tools(): Scan and register toolssync_tools(): Update tool records
Provider System (providers/litellm.py)
LiteLLM integration:
- Unified interface to 100+ providers
- Automatic retry logic
- Cost tracking
- Model normalization
Why LiteLLM:
- Supports 100+ providers
- Built-in error handling
- Cost calculation
- Model name normalization
Architecture Decisions
Why Frappe DocTypes?
Benefits:
- Built-in CRUD operations
- Permission system integration
- Audit trails automatically
- Standard UI components
- Database abstraction
Why LiteLLM?
Benefits:
- Unified API for all providers
- Automatic retry and error handling
- Built-in cost tracking
- Model name normalization
- Active maintenance
Tool System Design
Principles:
- Flexible: Support multiple tool types
- Extensible: Easy to add custom tools
- Secure: Respects Frappe permissions
- Trackable: All calls logged
- Discoverable: Auto-discovery via decorator
Contributing
Reporting Issues
Use GitHub Issues:
- Include steps to reproduce
- Provide error messages and logs
- Specify Huf and Frappe versions
- Include relevant code snippets
Pull Requests
Process:
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Commit with clear messages
- Push to your fork
- Open Pull Request
PR Requirements:
- Clear description of changes
- Reference related issues
- Update documentation if needed
- Follow code style guidelines
- Ensure tests pass (if applicable)
Code Style
Python:
- Follow PEP 8
- Use type hints where appropriate
- Write docstrings for functions/classes
- Keep functions focused and small
JavaScript:
- Follow Frappe conventions
- Use ES6+ features
- Comment complex logic
- Follow existing patterns
DocStrings:
def function_name(param1: str, param2: int) -> dict:
"""
Brief description of function.
Args:
param1: Description of param1
param2: Description of param2
Returns:
dict: Description of return value
Raises:
ValueError: When param1 is invalid
"""
passTesting
Before submitting:
- Test your changes thoroughly
- Test edge cases
- Verify error handling
- Check performance impact
- Test with different models/providers
Common Extension Patterns
Pattern 1: Custom Validation
Use case: Validate agent configuration before runs
# hooks.py
agent_before_run = "my_app.hooks.validate_agent"
# hooks.py implementation
def validate_agent(agent, prompt, context):
if agent.custom_field == "restricted":
# Check permissions
if not frappe.has_permission("Custom DocType", "read"):
frappe.throw("Permission denied")Pattern 2: Custom Metrics
Use case: Track custom metrics for agent runs
# hooks.py
agent_after_run = "my_app.hooks.track_metrics"
def track_metrics(agent, run_result, context):
frappe.get_doc({
"doctype": "Custom Metric",
"agent": agent.name,
"tokens": run_result.get("tokens_used", 0),
"cost": run_result.get("cost", 0),
"success": run_result.get("status") == "success"
}).insert()Pattern 3: Tool Wrapper
Use case: Add logging or validation to tool calls
# hooks.py
agent_tool_call = "my_app.hooks.wrap_tool_call"
def wrap_tool_call(tool_name, params, context):
# Log tool call
frappe.logger().info(f"Tool called: {tool_name}")
# Add custom validation
if tool_name == "sensitive_tool":
validate_sensitive_access()
# Continue with normal execution
return None # Return None to proceed normallyResources
Documentation:
Code:
Community:
Getting Help
For Huf-specific questions:
- Check this documentation
- Search GitHub Issues
- Ask in GitHub Discussions
- Review source code
For Frappe questions:
Next Steps
- Explore the codebase: Understand structure and patterns
- Read Frappe docs: Ensure you understand Frappe development
- Create a custom tool: Start with
@agent_tooldecorator - Extend functionality: Use hooks for custom behavior
- Contribute: Submit improvements and fixes
Ready to contribute? Check out the GitHub repository and open an issue or pull request!