Thank you for your interest in contributing to agentexec! This guide will help you get started.
By participating in this project, you agree to abide by our Code of Conduct. Please be respectful and constructive in all interactions.
- Python 3.11 or higher
- Redis 7.0 or higher
- uv (for package management)
- Git
- Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/agentexec.git
cd agentexec- Install uv (if not already installed):
curl -LsSf https://astral.sh/uv/install.sh | sh- Install dependencies:
uv sync- Start Redis (for tests):
# macOS
brew services start redis
# Ubuntu/Debian
sudo systemctl start redis- Run tests to verify setup:
uv run pytestCreate a branch for your changes:
git checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fix- Write your code following our style guidelines
- Add or update tests as needed
- Update documentation if applicable
- Run the test suite
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=agentexec
# Run specific test file
uv run pytest tests/test_task.py
# Run specific test
uv run pytest tests/test_task.py::test_task_creationWe use ruff for linting and formatting:
# Check for issues
uv run ruff check .
# Fix auto-fixable issues
uv run ruff check --fix .
# Format code
uv run ruff format .We use mypy for type checking:
uv run mypy src/agentexecInstall pre-commit hooks to automatically check code before commits:
uv run pre-commit install- Follow PEP 8 style guidelines
- Use type hints for all function signatures
- Write docstrings for public functions and classes
- Keep functions focused and small
from uuid import UUID
from typing import Optional
from pydantic import BaseModel
class TaskContext(BaseModel):
"""Context for task execution.
Attributes:
name: Name of the task
priority: Task priority (1-10)
metadata: Optional additional metadata
"""
name: str
priority: int = 5
metadata: Optional[dict] = None
async def process_task(
agent_id: UUID,
context: TaskContext,
timeout: int = 300,
) -> dict:
"""Process a task with the given context.
Args:
agent_id: Unique identifier for the task
context: Task configuration
timeout: Maximum execution time in seconds
Returns:
Dict containing the task result
Raises:
TimeoutError: If task exceeds timeout
ValueError: If context is invalid
"""
# Implementation here
passUse clear, descriptive commit messages:
feat: add support for custom queue names
- Allow specifying queue_name in enqueue()
- Update Pool to accept queue_name parameter
- Add tests for custom queue functionality
Prefixes:
feat:- New featurefix:- Bug fixdocs:- Documentation changestest:- Test additions or changesrefactor:- Code refactoringchore:- Maintenance tasks
tests/
├── test_task.py # Task-related tests
├── test_activity.py # Activity tracking tests
├── test_worker_pool.py # Worker pool tests
├── test_queue.py # Queue operation tests
├── test_runner.py # Runner tests
└── conftest.py # Shared fixtures
import pytest
from uuid import uuid4
from unittest.mock import AsyncMock, patch
import agentexec as ax
@pytest.fixture
def mock_queue_push(monkeypatch):
"""Patch the queue backend so tests don't need a live Redis."""
pushed = []
async def _push(value, *, priority=None, partition_key=None):
pushed.append(value)
monkeypatch.setattr("agentexec.state.backend.queue.push", _push)
return pushed
@pytest.mark.asyncio
async def test_enqueue_creates_activity(mock_queue_push, monkeypatch):
"""Test that enqueueing a task creates an activity record."""
# Arrange: stub Task.create so we don't need a real DB.
async def fake_create(**kwargs):
from agentexec import Task
return Task(agent_id=uuid4(), **kwargs)
monkeypatch.setattr("agentexec.core.task.Task.create", fake_create)
# Act
task = await ax.enqueue("test_task", MyContext(data="test"))
# Assert
assert task.agent_id is not None
assert task.task_name == "test_task"
assert len(mock_queue_push) == 1- Test one thing per test function
- Use descriptive test names
- Include docstrings explaining what's being tested
- Use fixtures for common setup
- Mock external dependencies (Redis, databases, APIs)
Documentation is in the docs/ directory:
docs/
├── index.md # Main landing page
├── getting-started/ # Getting started guides
├── concepts/ # Conceptual documentation
├── guides/ # How-to guides
├── api-reference/ # API documentation
├── deployment/ # Deployment guides
└── contributing.md # This file
- Use clear, concise language
- Include code examples
- Add cross-references to related docs
- Keep examples up to date
# Preview documentation locally (if using MkDocs)
uv run mkdocs serve- Ensure all tests pass
- Run linting and type checking
- Update documentation if needed
- Add entry to CHANGELOG.md
- Push your branch to your fork
- Create a PR against the
mainbranch - Fill out the PR template
- Wait for CI checks to pass
- Request review from maintainers
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How was this tested?
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] CHANGELOG.md updated
- [ ] Code follows style guidelines- Maintainers will review your PR
- Address any feedback promptly
- Once approved, your PR will be merged
Releases are managed by maintainers:
- Update version in
pyproject.toml - Update CHANGELOG.md
- Create a release tag
- CI publishes to PyPI
- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and discussions
- Discord: Join our community (if available)
Contributors are recognized in:
- CHANGELOG.md for their contributions
- GitHub contributors page
Thank you for contributing to agentexec!