Setup
# Fork the repo on GitHub, then:git clone https://github.com/<your-user>/agentloom.gitcd agentloomgit remote add upstream https://github.com/cchinchilla-dev/agentloom.git
# Install dev dependencies (requires uv)uv sync --group dev --all-extras
# Install the git hooks (ruff and version-linearity on every commit)uv run pre-commit install
# Verifyuv run pytestDevelopment workflow
- Sync your fork:
git fetch upstream && git rebase upstream/main - Create a branch:
git checkout -b my-feature - Make your changes
- Run the quality gate:
Terminal window uv run pytest # testsuv run ruff check src/ tests/ # lintuv run ruff format src/ tests/ # formatuv run mypy src/ # type check - Push to your fork and open a pull request against
upstream/main
Code style
- Python 3.11+ with type hints on all public APIs
- Pydantic v2 for models and validation
- anyio for async (never raw
asyncio) - httpx for HTTP (no provider SDKs)
ruffhandles formatting and linting — run it before committingmypy --strictmust pass
Tests
- Use
pytestwithpytest-asyncio(auto mode) - Mock HTTP calls with
respx— no real API keys in tests - Focus on behavior, not implementation details
- Place tests mirroring the source tree:
tests/core/,tests/providers/, etc.
Commit messages
Conventional-Commits style with scope:
feat(providers): add streaming usage extraction for Anthropicfix(steps): respect router skip closure across parallel brancheschore(deps): bump httpx to 0.28.1ci(version): add version-linearity gatedocs(observability): document OTel span schema migrationrefactor(gateway): extract candidate cache into LRU helpertest(providers): add 429 contract suite parametrised across adaptersperf(state): swap dict-snapshot for copy-on-write read viewbuild(deps): pin httpx to 0.28.x for connection-pool compatibilitystyle(core): apply ruff format- Imperative mood, lowercase after the colon. Single-line subject under ~72 chars; body only when justification adds value.
- Types:
feat,fix,chore,ci,test,docs,refactor,perf,build,style. - Common scopes:
core,cli,providers,observability,steps,resilience,tools,webhooks,checkpointing,record-replay,release,deps,version,meta,examples,infrastructure. - Several scopes go comma-separated, without spaces:
feat(core,steps): …. - PR-merge commits append
(#NN)and may include(#issue)references — e.g.feat(providers): add structured output (#117) (#42). - Release commits are the one exception: exactly
bump version to X.Y.Z, with no type or scope.auto-tag.ymlonly tags commits that start with that prefix.
The PR title becomes the squash-merge commit on main, so the same convention applies to PR titles. The pr skill enforces this.
Pull requests
- Keep PRs focused — one feature or fix per PR
- Link issues:
Closes #123in the PR description - All CI checks (tests, ruff, mypy) must pass before merge
- PRs are squash-merged to keep history clean
AI-assisted contributions
AI coding assistants are welcome. The project rules they need live in AGENTS.md, which most assistants read automatically.
The repository ships a small set of shared skills in .agents/skills/ for routine work on this repo: check (the local quality gate), review, commit, pr, release, and a few more. Codex reads them from that folder, Claude Code through the .claude/skills symlink, and any other assistant can follow the SKILL.md files as plain instructions. They are optional: CI does not depend on them.
Whatever tool wrote the code, the author of the pull request is responsible for it: run the quality gate, read the diff, and be ready to explain any line.
Review
- During development — the deep review happens before a pull request is opened. Review your own changes with an AI assistant, by hand, or both; a model from a different vendor than the one that wrote the code tends to catch more. The checklist is the Review guidelines section of
AGENTS.md. - On the pull request — CI must pass. CodeRabbit posts a light automated review focused on bugs, security and the rules in
AGENTS.md. Its comments are suggestions; a maintainer decides what to merge.
Adding a provider
- Create
src/agentloom/providers/<name>.pyextendingBaseProvider - Register it in
_PROVIDER_CLASSES(cli/run.py) and give it defaults in_PROVIDER_DEFAULTS(config.py) - Add pricing data to
providers/pricing.yaml(the weekly refresh,scripts/update_pricing.py, covers OpenAI, Anthropic and Gemini only) - Add tests in
tests/providers/ - Update the capability matrix in
docs/providers.mdand the providers table in the README
Adding a step type
- Create
src/agentloom/steps/<name>.pyextendingBaseStep - Register it in
steps/registry.py - Add tests in
tests/steps/
Reporting bugs
Use the bug report template and include your workflow YAML if applicable.
Report a security vulnerability privately instead, as the security policy describes.