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