|
| 1 | +--- |
| 2 | +title: Contributing to UTCP |
| 3 | +layout: default |
| 4 | +nav_order: 10 |
| 5 | +permalink: /contributing |
| 6 | +--- |
| 7 | +# Contributing to UTCP Organization Repositories |
| 8 | + |
| 9 | +Welcome to the Universal Tool Calling Protocol (UTCP) organization! We're excited to have you contribute to our mission of creating efficient, decentralized, and scalable AI tool integration. This document serves as the unified contribution guideline for all repositories in our organization. |
| 10 | + |
| 11 | +## Core Requirements |
| 12 | + |
| 13 | +Our development follows the fundamental UTCP requirements: |
| 14 | + |
| 15 | +- **No wrapper tax**: Solutions must work with existing tools without requiring changes |
| 16 | +- **No security tax**: Maintain the same security guarantees as human interaction |
| 17 | +- **Scalable**: Handle large numbers of tools and calls efficiently |
| 18 | +- **Simple**: Keep implementation and usage straightforward |
| 19 | + |
| 20 | +> **Core Principle**: If humans can interact with an API, AI should be able to do the same with no change in the API and the same security guarantees. |
| 21 | +
|
| 22 | +## Development Workflow |
| 23 | + |
| 24 | +### Git Workflow |
| 25 | + |
| 26 | +We follow a **Gitflow release model** with the following branch structure: |
| 27 | + |
| 28 | +``` |
| 29 | +main (production-ready releases) |
| 30 | + ↑ |
| 31 | +dev (integration branch) |
| 32 | + ↑ |
| 33 | +feature/fix branches |
| 34 | +``` |
| 35 | + |
| 36 | +**Branch Flow:** |
| 37 | +1. **Development** → All changes go into the `dev` branch first |
| 38 | +2. **Integration** → `dev` is merged into `main` for releases |
| 39 | +3. **Versioning** → `main` creates version-specific branches, with major and minor versioning (e.g., `v1.0`, `v2.1`) |
| 40 | + |
| 41 | +**Working with Branches:** |
| 42 | +- Create feature branches from `dev`: `git checkout -b feature/your-feature-name dev` |
| 43 | +- Create bug fix branches from `dev`: `git checkout -b fix/issue-description dev` |
| 44 | +- Submit PRs to the `dev` branch |
| 45 | +- Only release managers merge `dev` → `main` → version branches |
| 46 | + |
| 47 | +### Pull Request Process |
| 48 | + |
| 49 | +1. **Fork and Branch**: Fork the repository and create a feature branch from `dev` |
| 50 | +2. **Develop**: Make your changes following our architectural guidelines |
| 51 | +3. **Test**: Ensure all tests pass and add new tests for your changes |
| 52 | +4. **Document**: Update documentation if your changes affect public APIs |
| 53 | +5. **Submit**: Open a PR against the `dev` branch with a clear description |
| 54 | +6. **Review**: Address feedback from maintainers |
| 55 | +7. **Merge**: Once approved, your PR will be merged by a maintainer |
| 56 | + |
| 57 | +## Architecture Guidelines |
| 58 | + |
| 59 | +Our codebase follows a **dependency injection-based architecture** with clear separation of concerns: |
| 60 | + |
| 61 | +### Core Architectural Principles |
| 62 | + |
| 63 | +#### 1. Dependency Injection First |
| 64 | +- Use constructor injection for dependencies |
| 65 | +- Favor composition over inheritance |
| 66 | +- Make dependencies explicit through interfaces |
| 67 | +- Enable easy testing through mock implementations |
| 68 | + |
| 69 | +```python |
| 70 | +# Good - Dependency injection |
| 71 | +class ToolClient: |
| 72 | + def __init__(self, repository: ToolRepository, search_strategy: ToolSearchStrategy): |
| 73 | + self._repository = repository |
| 74 | + self._search_strategy = search_strategy |
| 75 | + |
| 76 | +# Avoid - Direct instantiation |
| 77 | +class ToolClient: |
| 78 | + def __init__(self): |
| 79 | + self._repository = FileSystemToolRepository() # Hard dependency |
| 80 | +``` |
| 81 | + |
| 82 | +#### 2. Discourage Subclassing for Non-Data Types |
| 83 | +- Prefer composition and interfaces over inheritance for business logic |
| 84 | +- Subclassing is acceptable for data types and value objects |
| 85 | +- Use protocols/interfaces to define contracts |
| 86 | + |
| 87 | +```python |
| 88 | +# Good - Interface-based design |
| 89 | +from abc import ABC, abstractmethod |
| 90 | + |
| 91 | +class ToolSearchStrategy(ABC): |
| 92 | + @abstractmethod |
| 93 | + def search(self, query: str) -> List[Tool]: |
| 94 | + pass |
| 95 | + |
| 96 | +class SemanticSearchStrategy(ToolSearchStrategy): |
| 97 | + def search(self, query: str) -> List[Tool]: |
| 98 | + # Implementation |
| 99 | + pass |
| 100 | + |
| 101 | +# Acceptable - Data type subclassing |
| 102 | +class HttpTool(Tool): |
| 103 | + def __init__(self, endpoint: str, method: str): |
| 104 | + super().__init__() |
| 105 | + self.endpoint = endpoint |
| 106 | + self.method = method |
| 107 | +``` |
| 108 | + |
| 109 | +#### 3. Separate Data and Logic |
| 110 | +- **Data classes**: Pure data containers with minimal behavior |
| 111 | +- **Logic classes**: Business logic with clear responsibilities |
| 112 | +- Avoid mixing data storage with business logic |
| 113 | + |
| 114 | +```python |
| 115 | +# Data class - Pure data container |
| 116 | +@dataclass |
| 117 | +class ToolDefinition: |
| 118 | + name: str |
| 119 | + description: str |
| 120 | + parameters: Dict[str, Any] |
| 121 | + endpoint: str |
| 122 | + |
| 123 | +# Logic class - Business behavior |
| 124 | +class ToolInvoker: |
| 125 | + def __init__(self, http_client: HttpClient): |
| 126 | + self._http_client = http_client |
| 127 | + |
| 128 | + def invoke(self, tool: ToolDefinition, params: Dict[str, Any]) -> Any: |
| 129 | + # Business logic implementation |
| 130 | + pass |
| 131 | +``` |
| 132 | + |
| 133 | +#### 4. Interface-First Design |
| 134 | +- Define interfaces before implementations |
| 135 | +- Document business logic through interface contracts |
| 136 | +- Enable multiple implementations for flexibility |
| 137 | + |
| 138 | +```python |
| 139 | +# 1. Define interface first |
| 140 | +class ToolRepository(ABC): |
| 141 | + """Repository for storing and retrieving tool definitions. |
| 142 | + |
| 143 | + Supports scalable storage backends for enterprise use cases. |
| 144 | + """ |
| 145 | + |
| 146 | + @abstractmethod |
| 147 | + def store(self, tool: ToolDefinition) -> None: |
| 148 | + """Store a tool definition.""" |
| 149 | + pass |
| 150 | + |
| 151 | + @abstractmethod |
| 152 | + def retrieve(self, tool_id: str) -> Optional[ToolDefinition]: |
| 153 | + """Retrieve a tool by ID.""" |
| 154 | + pass |
| 155 | + |
| 156 | + @abstractmethod |
| 157 | + def search(self, criteria: SearchCriteria) -> List[ToolDefinition]: |
| 158 | + """Search for tools matching criteria.""" |
| 159 | + pass |
| 160 | + |
| 161 | +# 2. Implement the interface |
| 162 | +class DatabaseToolRepository(ToolRepository): |
| 163 | + def store(self, tool: ToolDefinition) -> None: |
| 164 | + # Database implementation |
| 165 | + pass |
| 166 | + |
| 167 | + # ... other implementations |
| 168 | +``` |
| 169 | + |
| 170 | +## Testing Requirements |
| 171 | + |
| 172 | +### Test Coverage for Source Code Changes |
| 173 | + |
| 174 | +**All PRs that modify source code in the library must include appropriate tests:** |
| 175 | + |
| 176 | +- **Unit Tests**: Test individual components in isolation |
| 177 | +- **Integration Tests**: Test component interactions |
| 178 | +- **Contract Tests**: Verify interface implementations |
| 179 | +- **End-to-End Tests**: Test complete workflows |
| 180 | + |
| 181 | +### Test Structure |
| 182 | + |
| 183 | +``` |
| 184 | +tests/ |
| 185 | +├── unit/ # Fast, isolated tests |
| 186 | +├── integration/ # Component interaction tests |
| 187 | +├── e2e/ # End-to-end workflow tests |
| 188 | +└── fixtures/ # Test data and mocks |
| 189 | +``` |
| 190 | + |
| 191 | +### Test Quality Standards |
| 192 | + |
| 193 | +- **Coverage**: Maintain minimum 80% code coverage for new code |
| 194 | +- **Independence**: Tests must not depend on external services |
| 195 | +- **Speed**: Unit tests should run in milliseconds |
| 196 | +- **Clarity**: Test names should describe the scenario being tested |
| 197 | + |
| 198 | +```python |
| 199 | +# Good test structure |
| 200 | +class TestToolInvoker: |
| 201 | + def test_invoke_with_valid_params_returns_success_response(self): |
| 202 | + # Arrange |
| 203 | + mock_client = Mock(spec=HttpClient) |
| 204 | + mock_client.post.return_value = {"status": "success"} |
| 205 | + invoker = ToolInvoker(mock_client) |
| 206 | + |
| 207 | + # Act |
| 208 | + result = invoker.invoke(sample_tool, {"param": "value"}) |
| 209 | + |
| 210 | + # Assert |
| 211 | + assert result["status"] == "success" |
| 212 | + mock_client.post.assert_called_once() |
| 213 | +``` |
| 214 | + |
| 215 | +## Code Quality Standards |
| 216 | + |
| 217 | +### Code Style |
| 218 | +- Follow language-specific style guides (PEP 8 for Python, etc.) |
| 219 | +- Use consistent naming conventions |
| 220 | +- Write self-documenting code with meaningful names |
| 221 | +- Keep functions and classes focused on single responsibilities |
| 222 | + |
| 223 | +### Documentation |
| 224 | +- Document all public APIs with docstrings |
| 225 | +- Include usage examples for complex functionality |
| 226 | +- Update README files when adding new features |
| 227 | + |
| 228 | +### Error Handling |
| 229 | +- Use specific exception types |
| 230 | +- Provide meaningful error messages |
| 231 | +- Log errors with sufficient context |
| 232 | +- Handle edge cases gracefully |
| 233 | + |
| 234 | +## Scalability Considerations |
| 235 | + |
| 236 | +Remember that UTCP is designed for enterprise-scale deployment: |
| 237 | + |
| 238 | +- **Performance**: Design for high throughput and low latency |
| 239 | +- **Concurrency**: Design thread-safe components!!! |
| 240 | +- **Configuration**: Make components configurable for different deployment scenarios |
| 241 | + |
| 242 | +## Community Guidelines |
| 243 | + |
| 244 | +### Communication |
| 245 | +- Be respectful and inclusive |
| 246 | +- Ask questions in discussions or issues |
| 247 | +- Provide context when reporting bugs |
| 248 | +- Suggest improvements through issues before implementing |
| 249 | + |
| 250 | +### Getting Help |
| 251 | +- Check existing issues and discussions |
| 252 | +- Read the documentation thoroughly |
| 253 | +- Provide minimal reproducible examples |
| 254 | +- Tag maintainers only when necessary |
| 255 | + |
| 256 | +## Release Process |
| 257 | + |
| 258 | +1. **Feature Freeze**: No new features in `dev` branch |
| 259 | +2. **Testing**: Comprehensive testing of `dev` branch |
| 260 | +3. **Documentation**: Update all relevant documentation |
| 261 | +4. **Merge**: `dev` → `main` with release notes |
| 262 | +5. **Tag**: Create version tag on `main` |
| 263 | +6. **Branch**: Create version branch for maintenance |
| 264 | +7. **Deploy**: Deployment from version branch |
| 265 | + |
| 266 | +--- |
| 267 | + |
| 268 | +Thank you for contributing to UTCP! Your efforts help build a more efficient and scalable future for AI tool integration. |
| 269 | + |
| 270 | +For questions about this guide, please open a discussion in the repository or contact the maintainers. |
0 commit comments