Contributing
Development Workflow
- Fork and clone the repository
- Create a feature branch from
master:git checkout -b feat/my-feature - Run
task setup(first time) ortask install(subsequent) - Make changes —
task devfor hot reload - Run
task test:quick(fast) ortask test(full) - Run
task lintandtask check:types - Commit with a descriptive message
- Submit a pull request
Branch Naming
| Prefix | Use |
|---|---|
feat/ | New features |
fix/ | Bug fixes |
refactor/ | Code restructuring |
docs/ | Documentation changes |
test/ | Test additions/fixes |
Commit Style
Use imperative mood: “Add memory recall layer” not “Added memory recall layer”.
Prefix with scope when relevant: fix(mcp): resolve env var expansion in headers.
Code Style
Python
- Linter/formatter: ruff (
task lint:python,task format:python) - Type checker: pyright (
task check:types:python) - Follow existing patterns — look at neighboring code before writing new code
- Use type hints on all public function signatures
- Docstrings on public classes and non-obvious functions
TypeScript
- Type check:
task check:types:client - Build check:
task check:build:client
Testing
Running Tests
task test:quick # Fast — skips model loading (HealthCheck, MCP tests)
task test # Full — includes TranslationKit tests (slow first run)
# Specific test class or method:
uv run python api/manage.py test agentx_ai.tests.MCPClientTest -v2
uv run python api/manage.py test agentx_ai.tests_memory.MemoryIntegrationTest -v2
Writing Tests
- Add tests to
tests.py(core) ortests_memory.py(memory system) - Use
@unittest.skipUnlessfor tests that require Docker or API keys - Tests should be independent — no shared mutable state between test methods
- Memory tests: skip gracefully when databases are unavailable
Architecture Guidelines
Lazy Initialization
Heavy subsystems use @lazy_singleton (see utils/decorators.py). Never import heavy modules at file scope — use deferred imports inside functions.
Sync/Async Boundary
Django is synchronous. MCP and provider streaming use asyncio. Bridge with call_tool_sync() or asyncio.run_coroutine_threadsafe(). Only agent_chat_stream and providers_health are async views.
Adding a New Provider
- Create
providers/my_provider.pyimplementingModelProviderABC - Add models to
providers/models.yamlwithprovider: my_provider - Register in
providers/registry.pyloader - Add env vars to
.env.example
Adding a Reasoning Strategy
- Create
reasoning/my_strategy.pyimplementingReasoningStrategyABC - Add to orchestrator’s strategy map in
orchestrator.py - Add task type classification keywords if needed
Adding a Memory Subsystem
- Create module under
kit/agent_memory/memory/ - Wire into
AgentMemoryinterface (memory/interface.py) - Add database schema if needed (
management/commands/init_memory_schemas.py) - Add tests in
tests_memory.py
PR Checklist
- Tests pass (
task test:quickat minimum) - Linter passes (
task lint) - Type checker passes (
task check:types) - New public APIs have docstrings
- Documentation updated if user-facing behavior changed
- No hardcoded API keys or secrets