Thank you for your interest in contributing. This document gives a short overview of how to get involved.
-
Report bugs or suggest features – Open an issue and describe the problem or idea. Check existing issues first to avoid duplicates.
-
Submit code changes – Create a branch (in your fork or directly in this repo if you have access), make your changes, and open a pull request (PR). You don’t need to fork if you can push branches here. Keep PRs focused; one feature or fix per PR is easier to review. When creating a PR, use the PR template and fill in each section.
-
Improve documentation – Fixes and clarifications in the README, agent docs, or code comments are always welcome. Use the
docs:prefix in your commit (see below). -
Add or fix tests – If you add or change behavior, consider adding or updating tests and use the
test:prefix in commits.
Before submitting, please read our Code of Conduct. By participating, you agree to uphold it.
This repository uses pre-commit hooks to enforce code quality checks before each commit. Set it up once after cloning:
uv tool install pre-commit
pre-commit install --install-hooksAfter this, every git commit will automatically run the checks listed in Pre-commit hooks on your staged files. Commits that fail any check will be blocked.
If you haven't run pre-commit install --install-hooks, hooks will not run automatically. In that case, you can run all checks manually before committing:
pre-commit run --all-filesThe following hooks run automatically on every commit. They are defined in .pre-commit-config.yaml.
Enforces the Conventional Commits format on commit messages (see Commit message conventions below). Runs at the commit-msg stage.
Two hooks from ruff:
- ruff — lints Python files and auto-fixes issues. Rules are defined in
ruff.toml. - ruff-format — enforces consistent formatting (quotes, indentation, line length).
Lints .md files and auto-fixes what it can (e.g., list indentation, code block languages). Rules are defined in .markdownlint.jsonc; ignored paths in .markdownlint-cli2.yaml.
General-purpose checks from pre-commit/pre-commit-hooks:
| Hook | What it does |
|---|---|
trailing-whitespace |
Removes trailing whitespace from all files |
end-of-file-fixer |
Ensures every file ends with a newline |
check-yaml |
Validates YAML syntax (excludes charts/ — Helm templates use Go syntax) |
check-json |
Validates JSON syntax |
check-toml |
Validates TOML syntax |
check-merge-conflict |
Detects leftover merge conflict markers |
check-added-large-files |
Blocks files larger than 1 MB |
debug-statements |
Catches leftover breakpoint() / pdb calls in Python |
check-case-conflict |
Detects filenames that differ only in case |
mixed-line-ending |
Ensures consistent line endings (no mixed LF/CRLF) |
no-commit-to-branch |
Blocks direct commits to main |
detect-private-key |
Catches accidentally committed private keys |
Validates .github/workflows/ files using actionlint. Only runs when workflow files are staged.
This project uses ruff for Python linting and formatting, markdownlint for Markdown linting, and actionlint for GitHub Actions workflow validation. All three run as blocking CI checks on every pull request via the Code Quality workflow, and locally via the pre-commit hooks described above.
Configuration files: ruff.toml (Python rules), .markdownlint.jsonc (Markdown rules), .markdownlint-cli2.yaml (ignored paths).
This repository enforces the Conventional Commits specification via a pre-commit hook. Commits that don't follow this format will be blocked locally by the pre-commit hook.
Tip: To bypass the hook in rare cases (e.g., merge commits, emergency hotfixes):
git commit --no-verify
<type>(optional scope): <description>
[optional body]
[optional footer(s)]
| Prefix | Meaning |
|---|---|
| feat: | A new feature |
| fix: | A bug fix |
| docs: | Documentation only |
| chore: | Maintenance (deps, tooling, config) |
| test: | Adding or updating tests |
| perf: | A change that improves performance |
| refactor: | Code change that neither fixes a bug nor adds a feature |
| ci: | CI/CD changes |
| build: | Build system or external dependency changes |
| style: | Code style (formatting, whitespace — no logic changes) |
| revert: | Reverts a previous commit |
You can optionally add a scope (e.g. the agent or module name) in parentheses after the type.
feat: add health check endpoint to autogen mcp_agent
fix: correct env var name in deployment in langgraph_react_agent
docs: update README with OpenShift deploy steps
test: add tests for tool registration
chore: bump python-dotenv in requirements
refactor(langgraph): extract tool registration into helper
ci: add ruff linting workflow
feat!: change /chat response format
For breaking changes, add ! after the type/scope (e.g. feat!:) or include a BREAKING CHANGE: footer:
feat: change /chat response format
BREAKING CHANGE: response field "text" renamed to "content"
This repository has GitHub + Jira integration enabled. When you include a Jira ticket ID (e.g. RHAIENG-123) in your PR title, branch name, commit message, or PR description, the pull request automatically appears under Development on the Jira issue. This gives visibility into which tickets have active or merged code without leaving Jira.
Every pull request is automatically labeled when opened or updated:
Area labels (area/*) — applied based on which directories your PR touches. A PR can have multiple area labels if it spans several directories. These help reviewers quickly identify which parts of the codebase are affected.
| Label | Matches |
|---|---|
area/langgraph |
agents/langgraph/** |
area/crewai |
agents/crewai/** |
area/autogen |
agents/autogen/** |
area/llamaindex |
agents/llamaindex/** |
area/langflow |
agents/langflow/** |
area/google-adk |
agents/google/** |
area/a2a |
agents/a2a/** |
area/vanilla-python |
agents/vanilla_python/** |
area/helm |
charts/** |
area/docs |
docs/**, *.md (root) |
area/ci |
.github/** |
area/tests |
tests/**, eval/** |
area/tracing |
**/tracing.py, tracing.md |
Size labels (size/*) — applied based on total lines changed (additions + deletions), excluding lock files, generated files, and images.
| Label | Lines Changed |
|---|---|
size/xs |
0–10 |
size/s |
11–100 |
size/m |
101–500 |
size/l |
501–1199 |
size/xl |
1200+ |
PRs labeled size/xl will receive an advisory comment encouraging the author to consider splitting the PR. This is informational only — it does not block merges.
All agent templates in this repo must include MLflow tracing integration. Tracing lets users optionally capture LLM calls, tool executions, and agent orchestration spans in MLflow — it's opt-in via the MLFLOW_TRACKING_URI environment variable. If MLFLOW_TRACKING_URI is set but the server is unreachable, the agent logs a warning and continues without tracing. Note: if MLFLOW_TRACKING_URI is set but the MLflow package is not installed, the agent will fail at startup with an ImportError — MLflow must be installed when the env var is set.
Read tracing.md for the full tracing architecture, design principles, and how the existing agents integrate with MLflow. In particular, see the Autolog Coverage Levels section — the amount of work required depends on whether your framework is Level A (full autolog), B (partial), or C (no framework autolog).
These are the files you need to create or update when adding tracing to your agent:
1. Create src/<package>/tracing.py
This module exports enable_tracing() (and wrap_func_with_mlflow_trace() if your framework's autolog doesn't cover everything). It handles health-checking the MLflow server with retry logic, configuring the experiment, enabling the correct autolog for your framework, and gracefully degrading if the server is unreachable. MLflow imports are inside enable_tracing() (not at module top) so the module can be imported without MLflow installed — but if MLFLOW_TRACKING_URI is set and MLflow is missing, the agent will fail at startup with a clear error.
See existing examples:
- Full autolog (no manual wrapping needed):
agents/langgraph/react_agent/src/react_agent/tracing.py - Partial autolog (tools need manual wrapping):
agents/crewai/websearch_agent/src/crewai_web_search/tracing.py - No framework autolog (tools + agent entry point need manual wrapping):
agents/vanilla_python/openai_responses_agent/src/openai_responses_agent/tracing.py
2. Edit main.py
Import enable_tracing and call it as the first line inside your lifespan() function, before any agent initialization. If your framework needs manual wrapping, also import wrap_func_with_mlflow_trace and wrap tool functions (span_type="tool") and the agent entry point (span_type="agent") — in both the streaming and non-streaming code paths.
3. Edit .env.example
Add commented-out MLflow environment variable sections for both local and OpenShift deployment (see any existing agent's .env.example for the format).
4. Edit README.md
Add tracing configuration examples (local and OpenShift) and the uv run --extra tracing mlflow server --port 5000 server start step.
5. Add MLflow as an optional dependency in pyproject.toml
MLflow is listed as an optional dependency under the tracing extra:
[project.optional-dependencies]
tracing = [
"mlflow>=3.10.0",
]This allows make run to auto-install MLflow when MLFLOW_TRACKING_URI is set (via uv run --extra tracing). MLflow is not a core dependency — agents run without it when tracing is disabled.
If you have Claude Code set up, this repo includes a skill that automates the entire process described above.
- Claude Code installed and configured
- Run Claude Code from the repo root so it discovers the skills in
.claude/skills/
/integrate-tracing <framework> <agent_path>
For example:
/integrate-tracing autogen agents/autogen/chat_agent
You can also prompt Claude Code directly (e.g., "integrate tracing into the autogen chat agent using the /integrate-tracing skill") and it will follow the same workflow.
This single command runs the entire pipeline end-to-end. The skill always creates a demo copy of the agent first, implements and verifies tracing on the demo, and only applies the changes to the actual agent template once everything works correctly.
- Researches your framework's MLflow autolog support and classifies it (Level A/B/C)
- Creates a demo copy of the agent with test tools for trace verification
- Reads the agent's code to understand its architecture
- Creates
tracing.pywith the correct pattern for the autolog level - Wires
enable_tracing()into the FastAPI lifespan inmain.py - Adds manual trace wrapping for tools and agent entry points (skipped if autolog covers everything)
- Verifies traces end-to-end — code review + live testing against the MLflow API
- Updates
.env.examplewith MLflow environment variables - Updates
README.mdwith tracing configuration and install steps
Each step of the pipeline is also available as a standalone skill. This is useful if you want to run just one phase, re-run a step after a fix, or integrate tracing manually with some automation:
/check-autolog-support <framework> # Research MLflow autolog support for a framework
/create-tracing-module <agent_path> [framework] # Create tracing.py only
/wire-into-lifespan <agent_path> # Wire tracing into main.py only
/add-manual-tracing <agent_path> # Add manual trace wrapping only
/verify-traces <agent_path> # Run code review + live trace testing
/review-tracing-code <agent_path> # Code review only (no live testing)
/test-tracing <agent_path> # Live trace testing only (no code review)
integrate-tracing is an orchestrator — it doesn't contain all the logic itself. Instead, it coordinates 7 specialized sub-skills in sequence, passing context between them. The most important piece of context is the autolog level (A, B, or C), which is determined in Step 1 by check-autolog-support and drives every decision downstream: what code create-tracing-module generates, what wire-into-lifespan imports, whether add-manual-tracing runs at all, and what spans verify-traces expects to find.
verify-traces is itself a sub-orchestrator — it calls review-tracing-code (static analysis) and test-tracing (live end-to-end testing) and combines their results into a single report. If verification fails, the report points back to which step to revisit.
All skills live as siblings in .claude/skills/ (not nested under integrate-tracing/) because Claude Code discovers skills by scanning .claude/skills/*/SKILL.md. The flat structure also makes each sub-skill independently callable. If you need to maintain or extend a skill, edit the SKILL.md file in its directory. Each skill includes a self-update instruction — if Claude deviates from a skill's steps because they were inaccurate, it updates the skill file automatically so the next run benefits.
Recommended model: These skills were developed and tested with claude-opus-4-6. Use Opus for best results — smaller models may not follow the multi-step orchestration reliably.
See the main README or open an issue. You can also contact wrebisz@redhat.com or tguzik@redhat.com.