flwr new @christofilojohn/argus
Argus

Argus

Many eyes. One verdict.

Narrow scout agents review a public GitHub repository, each hunting one class of defect with its own playbook. A synthesizer ranks what they found, drops the noise, and writes a review anchored to file:line. A remediation pass proposes the smallest fix for each surviving finding.

The playbooks are the product. A curator edits them after every review, so the scouts get sharper each time they run.

Built for the Collaborative Agent Hackathon, Cambridge 2026.

   GitHub repo
        |
        v
  +---------------------------------------------------+
  |  scouts - one lens each, its own playbook         |
  |  network  ingestion  crypto  supplychain  memory  |
  +---------------------------------------------------+
        |
        v
   synthesizer     ranks findings, drops noise
        |
        v
   review + score  each finding tied to file:line
        |
        v
   remediation     smallest fix per finding
        |
        v
   curator         one new rule per scout
        |
        +--------> back into the playbooks

How it works

Whole-repo coverage at constant context. Growing a tool loop until it has seen a large repository exhausts the model's context and it stops answering. Argus separates discovery from judgement instead:

  1. Each scout's playbook yields literal search patterns — the backticked terms already written in it, so no model call is needed to produce them.
  2. Python greps every source file in the repository. No tokens, full coverage.
  3. The model judges the matched lines in independent batches, each with a fresh context. A 40-file repo and a 4000-file repo cost the same per call.

Line numbers therefore come from reading files, not from a model counting lines — every finding is anchored to code that was actually read.

Self-improving playbooks. Each scout has a Mission it may never change and a Learned section the curator appends to. After each review the curator compares what the scouts reported against what survived, and writes one rule per scout. Because patterns are extracted from the playbook text, a learned rule naming torch.load becomes a search pattern on the very next run.

A score that is arithmetic, not an opinion. Severity counts with diminishing returns, so the same findings always produce the same number. Crucially, a clean result on thin coverage reports as inconclusive rather than as a pass — finding nothing in 9% of a repository is not a clean bill of health, and neither is a lens whose patterns never matched the language.

Results

Run against public repositories, at the coverage shown:

RepositoryCoverageFindingsScore
ARM-software/kleidiai1617/1617 files19.0 / 10
ROCm/legacy-rocm-build115/115 files57.8 / 10
parasecurity/FLASHfull55.0 / 10

Representative findings:

  • parasecurity/FLASHdill.load applied to bytes received from a network peer at four call sites, giving remote code execution during parameter exchange.
  • ARM-software/kleidiaialloca sized from a caller-supplied matrix dimension, so a large N can overflow the thread stack.
  • ROCm/legacy-rocm-build — an upstream tarball fetched over the network and compiled as root with no checksum or signature check.

Where a review does not finish, it says so: a scout that never ran, or candidates left unjudged at the deadline, are reported alongside the score rather than being quietly folded into a pass.

Usage

Ask it in a sentence — the repository is parsed out of your message:

Review github.com/owner/repo for security issues.

Argus runs against a Flower SuperLink pointed at any endpoint that speaks the OpenAI Responses API:

export FLWR_MODEL_API_ENDPOINT='http://<host>:<port>/v1/responses'
uv run flower-superlink --insecure

Add the connection to ~/.flwr/config.toml:

[superlink.local-agent]
address = "127.0.0.1:9093"
insecure = true

Then review a repository:

uv sync
uv run flwr run . local-agent \
  --run-config 'agent.input="Review github.com/owner/repo for security issues."' \
  --stream

Reviews are written to ~/.argus/reviews/<owner>__<repo>__<stamp>.json with a standalone HTML report beside them. Learned playbooks live in ~/.argus/playbooks/.

Model. The results above were produced with Kimi-K2.7-Code, served on AMD Instinct MI300X accelerators. Every role — the five scouts, the synthesizer, the remediation pass and the curator — runs on that one model; they differ by playbook and brief, not by weights. Set scout_model and synth_model to whatever model ID your endpoint serves.

A SuperLink is bound to exactly one endpoint, so reaching a second model in the same run means calling it directly: set synth_endpoint to that model's /v1/responses URL and the synthesizer alone will use it.

Choosing a model. The scout loop needs a model that emits tool calls and then stops to answer. Reasoning-heavy models tend to spend their whole output budget thinking and return a response with no message at all, which Argus reports as a failed synthesis rather than inventing a result. If findings come back empty on a repository that clearly has candidates, that is the first thing to check.

Configuration

Every knob lives in [tool.flwr.app.config.argus] and can be overridden per run with --run-config.

KeyDefaultPurpose
scoutsfive threat lensesWhich playbooks to run.
modesweepsweep for whole-repo coverage; explore for a model-driven tool loop.
max_files1200Files to read. Bounds time, not context.
scout_model / synth_modelModel per role.
synth_endpointemptyPoint synthesis at a second, larger model.
budget_seconds210Deadline for the scout phase.

Adding a scout needs no code: drop a Markdown playbook in argus/playbooks/ with a Mission, Rules, and an empty Learned section, then name it in scouts.

Deliberate limits

  • No automatic pull requests. Findings are model-generated, so publishing them stays a human action. scripts/post_review.py posts a review to GitHub as inline comments carrying GitHub suggestion blocks, so a maintainer can apply or dismiss each fix in the review UI. It refuses to send anything without --confirm.
  • Fixes stay one or two edits deep. Where a real fix is larger, the report says what to investigate instead of inventing a redesign.
  • Findings without a real file:line are dropped before they reach the synthesizer.
  • The curator may only append to ## Learned. A scout's mission cannot drift.
  • Coverage is always reported, and a clean result on partial coverage is never presented as a pass.

Authors

Amar SaiTeja Chityala · Ioannis Christofilogiannis · Ayomide Lambe · Hanaa Babrakar

Licensed under Apache-2.0.