Contributing to AgentOps¶
Setup¶
git clone https://github.com/s7g4/AgentOps.git
cd AgentOps
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pip install -e "./client[dev]"
Before opening a PR¶
ruff check . # lint
mypy app # type check (strict)
pytest -q --cov=app --cov-report=term-missing # server test suite
pytest client/tests -q # client test suite
Redis-backed tests (trace/workflow/routing stores, the Redis rate limiter) skip automatically if no Redis is reachable. To run them locally:
docker run -d --rm -p 6379:6379 redis:7-alpine
REDIS_URL=redis://localhost:6379/0 pytest -q
CI runs the full suite against a real redis:7-alpine service container, enforces ruff check ., mypy app (strict), and a coverage floor via --cov-fail-under. A PR that doesn't pass all three won't merge.
Code style¶
This isn't enforced by a linter beyond ruff, but the codebase is consistent about a few things — match them rather than introducing a new pattern:
- Provider abstraction: agent-facing behavior (classification, planning, verification, response generation, decomposition) is an ABC in
app/providers/base.pyorapp/messaging/decomposition.py, with a deterministic implementation and (optionally) an OpenAI-backed one. New LLM-backed capability follows the same shape — extend, don't special-case. - Dataclasses for internal domain objects, Pydantic only at the API boundary.
WorkflowStep,Trace,AgentMessageetc. are dataclasses withto_dict()/from_dict().app/schemas/*.pyis the only place Pydantic models exist, because that's the only place validating untrusted input pays for itself. - Two-tier persistence. Anything that needs to survive a restart or be shared across replicas gets an in-memory implementation (default, zero deps) and a Redis implementation, behind the same
Protocol. Seeapp/workflows/store.pyfor the shape to copy. - Typed exceptions. New failure modes get a subclass of
AgentOpsErrorinapp/exceptions.py, not a bareExceptionor a string-matched error path. - Docstrings explain why, not what. Look at any existing module docstring in
app/for the expected shape: a design rationale, the alternatives considered, and why this one won.
Tests¶
New behavior needs a test in the same style as the surrounding file — plain functions (not test classes) for most things, async def test_...() where pytest-asyncio's auto mode picks it up directly. Look at the file you're editing before adding a new pattern.
Reporting bugs / requesting features¶
Use the issue templates. The bug template asks for a minimal repro because "it doesn't work" against a system with three orchestration entry points, two persistence backends, and optional LLM providers isn't actionable without knowing which combination you hit.