Blackgeorge is a code-first Python framework for building AI agents with explicit APIs, tool calling, structured outputs, and multi-agent orchestration.
Core primitives: Desk (runtime), Worker (single agent), Workforce (multi-agent coordination), Workflow (step-based flows).
- Python 3.12+
uvfor package management- Pydantic v2 for data models
- LiteLLM + Instructor for LLM calls
- pytest + ruff + mypy for dev tooling
src/blackgeorge/— Library sourcesrc/blackgeorge/core/— Pydantic models (Event, Job, Report, etc.)src/blackgeorge/adapters/— LLM provider adapterssrc/blackgeorge/tools/— Tool system (@tool decorator, registry, execution)src/blackgeorge/workflow/— Flow orchestration (Step, Parallel)src/blackgeorge/store/— Run persistence backendssrc/blackgeorge/memory/— Memory storesdocs/— MkDocs documentationtests/— pytest suite
Install dev deps:
uv pip install -e .[dev]Run tests:
uv run pytestLint and format:
uv run ruff check .
uv run ruff format .Type check:
uv run mypy srcServe docs:
uv run mkdocs serve- No comments or docstrings in code; rely on clear naming
- All functions must be type annotated
- Avoid
Any; use concrete types, Protocols, or TypeVars - Prefer absolute imports from
blackgeorge - No unused imports or variables
- Line length: 100
PascalCasefor classessnake_casefor functions, methods, variables_prefixfor private methods/attributes
- Use
str | NonenotOptional[str] - Use
collections.abcfor abstract base classes - Use
TYPE_CHECKINGto avoid circular imports - Pydantic models for complex data with validation
- Use
@dataclass(frozen=True)for immutable value objects - Use
ConfigDict(frozen=True, arbitrary_types_allowed=True)for immutable Pydantic models - Provide both sync and async variants:
run()/arun() - Avoid module import side effects
- Use
uv add <package>for deps,uv add --dev <package>for dev deps - Never use pip directly
- Flow.run/Flow.resume cannot be called from a running event loop (use arun/aresume)
- Enable repo hooks locally:
git config core.hooksPath .githooks && chmod +x .githooks/pre-commit .githooks/commit-msg .githooks/pre-push pre-commit: runsruff checkandruff format --checkon staged Python filescommit-msg: enforces Conventional Commits (feat|fix|refactor|docs|test|chore) and no trailing periodpre-push: blocksv*tag pushes when tag version does not matchpyproject.tomlor tag commit is not onorigin/master(fallback: localmaster)
- Run the full suite:
uv run pytest - Run specific test:
uv run pytest tests/test_worker.py::test_name -v - Tests use pytest-asyncio with
asyncio_mode = auto - Add tests for behavior changes, even if not asked
Commit message format (Conventional Commits):
type: subject
Types: feat, fix, refactor, docs, test, chore
Subject: imperative, lowercase, no trailing period
Example: feat: add vector memory chunking
Pre-commit checklist:
uv run ruff check .
uv run ruff format .
uv run mypy src
uv run pytest- DO NOT commit
.blackgeorge/run state or database files - DO NOT commit
.envfiles or API keys - DO NOT bump versions in
pyproject.tomlunless asked - ALWAYS update docs in
docs/when changing public API or behavior (if module does not exists, make new .md file and update mkdocs.yml) - ALWAYS add tests when changing behavior