Open-source project
kulkarnirohit123/cra-agent avatar
kulkarnirohit123/cra-agent

cra-agent: a LangGraph pipeline that turns commit diffs into Jira tickets and fix PRs

Autonomous agentic AI for CRA (Cyber Resilience Act) compliance: scans repos, triages findings, opens Jira tickets, and auto-fixes vulnerabilities via PR.

402 stars175 forksPythonApache-2.0

At a glance

What is it?
kulkarnirohit123/cra-agent is a Python 3.11+ agent that watches a Git repository, runs semgrep, pip-audit and gitleaks on each commit, and routes confirmed findings into Jira. The README still labels its Quick Start as planned, so treat this as a design to read before you deploy it.
Who is it for?
Adopt cra-agent if your team already lives in Jira and wants vulnerability triage attached to commits rather than to a nightly scan report; the SQLite suppression store and the scanner rules in config/scanner_rules.yaml are the two files that decide whether it stays quiet. Skip it if you have no Jira instance, no LLM API key, or no appetite for an agent that opens pull requests on your behalf.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 33 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap cra-agent targets: compliance work that starts after the merge

Most scanning setups run on a schedule. A nightly job walks the whole repository, produces a report, and someone reads it the next morning. By then the commit that introduced the vulnerable dependency is three merges deep, and the person who wrote it has moved on. cra-agent inverts that ordering. The GitMonitor watches a branch, the DiffAnalyzer extracts only the changed files and hunks, and the scanners run against that subset. The stated goal is continuous CRA compliance monitoring, which in practice means every commit gets evaluated while the author still remembers what they changed.

The audience is narrow and worth naming. This is for a team that ships a product with a software component, already uses Jira as its system of record, and has someone accountable for producing evidence that known vulnerabilities were identified and handled. It is not a scanner for a solo developer with a personal repository, and it is not a replacement for a dedicated SBOM tool. The README frames the output as Jira tickets carrying triage recommendations, which tells you the intended consumer is a triage queue, not a dashboard nobody opens.

How the orchestrator, agents and scanners fit together

The architecture diagram in the README shows two entry paths that converge on one agent layer. On the left, GitMonitor detects a commit by polling or webhook, DiffAnalyzer extracts the changed files, and ScannerAgent runs the scanner set over them. On the right, a FastAPI webhook server receives Jira updates and the JiraHandler routes the resulting action.

The agent layer is a LangGraph state machine in src/agents/orchestrator.py with four nodes: Scanner, Triage, Fixer and Jira. Scanner produces raw findings. SuppressionStore, a SQLite table, filters out anything previously marked known or ignored. Triage classifies what remains by severity, exploitability and CRA relevance. Jira creates the ticket. Fixer is the node that writes a patch and opens a pull request.

The scanner layer is deliberately thin. Dependency scanning, SAST and secret detection are separate classes behind base_scanner.py, and the tech stack table names semgrep, pip-audit and gitleaks as CLI tools. That means the agent does not reimplement detection logic; it shells out and reasons over the output. The consequence is that scanner coverage is exactly the coverage of those three tools, and the LLM layer only decides what the findings mean and what to do about them.

One detail in the workflow deserves attention. The suppression filter runs before triage, not after. A finding that lands in the suppression store never reaches the LLM, which keeps token cost down on a repository with a long tail of accepted risks. It also means a bad suppression entry silently removes a class of findings from every future commit, and the README does not describe an expiry or review mechanism for those rows.

Installing cra-agent and running the first scan

The README marks its Quick Start as planned, so treat these commands as the intended path rather than a verified one. Dependencies install from pyproject.toml, which requires Python 3.11 or newer and pulls in langgraph, langchain, fastapi, streamlit and gitpython.

bash
pip install -e ".[dev]"

The editable install also exposes a console script named cra-agent, declared under [project.scripts] and pointing at src.main:main.

bash
cp .env.example .env

Open .env and fill in the values the agent needs. The template groups them: GIT_REPO_PATH and GIT_BRANCHES for the repository to watch, LLM_PROVIDER and LLM_MODEL for the model, and the JIRA_BASE_URL, JIRA_EMAIL and JIRA_API_TOKEN triple for ticketing. LLM_PROVIDER accepts openai or anthropic, and the default template pairs openai with gpt-4o at a temperature of 0.1.

bash
python -m src.main

That starts the orchestrator, which begins polling the configured branches at GIT_POLL_INTERVAL_SECONDS, set to 60 in the example. The webhook listener runs as a separate process, because it needs its own port and its own lifecycle.

bash
uvicorn src.webhook.server:app --reload --port 8080

If you prefer containers, docker-compose.yml defines an agent service and a webhook service on a shared cra-network. The agent service mounts the target repository read-only at /app/repo and a local ./data directory at /app/data, which is where SUPPRESSION_DB_PATH points. The Dockerfile exposes 8080 for the webhook server and 8501 for the Streamlit dashboard.

bash
docker-compose up -d
docker-compose logs -f

On a first run, expect the agent to produce Jira issues rather than pull requests. The Fixer node is the last stage in the workflow, and the README does not describe a dry-run mode that would let you watch triage decisions without writing to Jira.

Where the design gets thin: suppression, rollback and the planned Quick Start

The suppression store is the weakest documented part. It is a SQLite table that decides which findings never reach the LLM, and the README describes it only as holding known and ignored vulnerabilities. There is no documented schema, no documented command for adding an entry, and no documented way to expire one. On a repository with active development, an entry added for a dependency you plan to upgrade next sprint will keep suppressing that finding after the sprint ends. The docker-compose file persists the database through a volume mount at /app/data, so the state survives restarts, which is the right choice for durability and the wrong one for accidental staleness.

The second gap is rollback. The README does not document how to undo a Fixer pull request beyond closing it, nor how to stop the agent mid-run. The orchestrator is a state machine, and the documentation does not describe checkpointing, so an interrupted run is an unknown quantity.

Third, the Quick Start section is explicitly labelled planned. Combined with version 0.1.0 in pyproject.toml and no retrieved releases, that is a signal about maturity. The repository structure is complete and the tests directory has separate suites for scanners, agents and webhook, but the documentation does not claim the pipeline has been run end to end in production. Anyone evaluating this should read DESIGN.md and Project.md before assuming the workflow section reflects working code.

There is also a cost dimension the README does not address. Every non-suppressed finding is sent to an LLM, and the Fixer node generates patches. A repository with noisy semgrep rules will produce a steady stream of model calls, and nothing in the configuration template caps that.

cra-agent versus wiring the same scanners into CI yourself

The obvious alternative is not another agent framework. It is the set of tools cra-agent already depends on, run directly in a CI pipeline. semgrep, pip-audit and gitleaks all have their own CLI entry points and their own exit codes, and a GitHub Actions or GitLab CI job can run them on a pull request diff, fail the build on a threshold, and post the output as a comment. That approach has no LLM dependency, no Jira API token to rotate, and no suppression database to maintain, because the CI platform already has a way to mark a finding as accepted.

The difference is what happens to a finding that is not a clear pass or fail. A CI job can tell you that pip-audit flagged a transitive dependency with a CVE. It cannot read the finding, decide that the vulnerable function is never called in your code path, write that reasoning into a ticket, and open a patch that bumps the dependency. cra-agent's Triage and Fixer nodes exist for exactly that middle band of findings that are real but not obviously exploitable.

That is a genuine trade, not a clear win. You are exchanging determinism for judgement. A CI threshold produces the same verdict on the same diff every time; an LLM at temperature 0.1 produces a verdict that is mostly stable and occasionally not. For a compliance workflow where you need to show an auditor why a finding was closed, reproducibility matters, and the README does not describe how triage decisions are logged or replayed. Teams with a large volume of low-severity noise will likely find the CI approach cheaper. Teams drowning in triage queues may find the agent worth the nondeterminism.

Licence, dependencies and the maintenance picture

cra-agent is Apache-2.0, declared both in the LICENSE file at the repository root and in the pyproject.toml license field. That is a permissive licence with an explicit patent grant, and it imposes no copyleft obligation on code you write alongside it. The licence implications that matter here are indirect. The agent shells out to semgrep, pip-audit and gitleaks, each of which carries its own licence, and it calls OpenAI or Anthropic endpoints under your own API agreement. If you redistribute cra-agent inside a product, check those upstream terms separately. This is not legal advice; read the licences.

On maintenance, the last push to the default branch was on 2026-08-15. The repository is not archived. The version is 0.1.0 and no releases were retrieved, so there is no release cadence to plan upgrades around. Dependencies are pinned with lower bounds only, for example langgraph>=0.2.0 and langchain>=0.3.0, which means a fresh install months from now resolves to whatever is current then. LangChain and LangGraph have both moved quickly, so an unpinned lower bound is a real upgrade risk: a breaking change in either library lands in your build without a version bump in this project.

Upgrading means tracking those two frameworks yourself. There is no changelog in the repository and no release notes to read.

Editorial conclusion

Adopt cra-agent if your team already lives in Jira and wants vulnerability triage attached to commits rather than to a nightly scan report; the SQLite suppression store and the scanner rules in config/scanner_rules.yaml are the two files that decide whether it stays quiet. Skip it if you have no Jira instance, no LLM API key, or no appetite for an agent that opens pull requests on your behalf. Before deploying, run the CLI scanners by hand against a sample diff, confirm the JIRA_WEBHOOK_SECRET path in src/webhook/handlers.py, and check that the suppression database under SUPPRESSION_DB_PATH survives a container restart.

Frequently asked questions

What is cra-agent?

It is an autonomous agentic AI system for continuous CRA compliance monitoring, written in Python. According to the README, it scans every commit, identifies vulnerabilities, creates Jira tickets with triage recommendations, and reacts to Jira webhook updates by suppressing known issues or auto-fixing them.

How do I install cra-agent?

The README gives a Quick Start labelled planned: install dependencies with pip install -e ".[dev]", copy .env.example to .env and fill in the Jira, LLM and Git credentials, then run python -m src.main. The webhook server runs separately with uvicorn src.webhook.server:app --reload --port 8080.

Which scanners does cra-agent use?

The tech stack table lists semgrep for SAST, pip-audit for dependencies and gitleaks for secrets, all invoked as CLI tools behind the base_scanner.py interface. The scanner layer also includes a suppression store backed by SQLite that filters out known or ignored vulnerabilities before triage.

Does cra-agent need an LLM API key?

Yes. The .env.example template defines LLM_PROVIDER with supported values openai and anthropic, along with LLM_MODEL, LLM_TEMPERATURE and LLM_MAX_TOKENS, plus OPENAI_API_KEY and ANTHROPIC_API_KEY fields. The docker-compose file passes the provider and model through from the environment.

Official sources

  1. Issues
  2. kulkarnirohit123/cra-agent on GitHub
  3. License: Apache-2.0
  4. README
Community notes

Community notes