πŸ¦β€β¬› Skwaq

A self-improving, multi-agent vulnerability analyzer that bootstrapped from a short spec into a competitive detection system β€” using AI agents to analyze, benchmark, and improve their own investigation methodology.
The name comes from the Lushootseed word for Raven β€” the trickster who reveals hidden truths.
Skwaq multi-agent vulnerability analyzer

What Is Skwaq?

An agentic vulnerability analyzer that uses a team of AI agents to investigate source code and binaries for security vulnerabilities. Unlike traditional static analysis tools that rely on fixed rules, skwaq's agents reason about code like experienced security researchers β€” tracing data flows, mapping attack surfaces, and debating exploitability.

What makes it unique: skwaq improves itself. A built-in benchmark harness (Skwaq Gym) measures detection accuracy against industry benchmarks, and a self-improvement loop uses AI agents to analyze their own failures and propose better investigation strategies.

97.3%
Juliet F1 (agentic)
91.0%
CSE F1
18
Agent Prompts
6
Benchmark Suites
22+
Improvement Cycles
Key differentiator: 100% precision across all benchmarks (0 false positives). Most tools trade precision for recall.

The Story

From spec to self-improving system

Can AI agents bootstrap themselves into a competitive vulnerability detection system?

Step 1

The Spec

Started with a brief specification for a "vulnerability investigation copilot":

  • Analyze binaries and source code using a code property graph
  • AI agents reason about the results
  • No training data, no pre-built rules, no benchmark infrastructure

The question: Can a short spec + AI bootstrapping produce a competitive detection system from scratch?

  • No labeled datasets β€” agents must reason, not memorize
  • No manually tuned rules β€” improvement comes from the loop
  • Benchmark infrastructure built alongside the tool, not before
Step 2

Building the Harness

  • Built the Skwaq Gym benchmark harness β€” started with a small fixture suite at F1=50%
  • Wired up 5-layer detection: patterns, dataflow, context validation, LLM agents, synthesis
  • Connected four industry benchmarks:
    • NIST Juliet β€” 54K synthetic C/C++ cases across 116 CWEs
    • OWASP Benchmark β€” 2,740 Java web-app vulnerability cases
    • DARPA CGC β€” real challenge binaries (patched/unpatched)
    • Meta CyberSecEval β€” real-world vulnerability patterns
  • Development and multi-agent analysis pipelines orchestrated by amplihack-recipe-runner
Starting F1 = 50%  Β·  Having measurable baselines made every improvement cycle legible
Step 3

Leveraging the Graph Database

Built a code property graph in LadybugDB β€” skwaq's own analysis code extracts and stores:

  • Functions and call edges
  • Taint flows β€” how untrusted user input propagates through code
  • Data sources and data sinks
  • Symbols and imports

Graph capabilities unlock:

  • Cross-file analysis
  • Recursive call-graph traversal
  • Source-to-sink data flow tracing
  • 2-hop neighborhood queries

Agents query this graph with specialized tools β€” enabling analysis that static patterns alone cannot achieve.

Step 4

Multi-Agent Pipeline

Started with a small set of agents. The self-improvement loop was given instructions to experiment with new agentic workflows and agent types β€” and evolved the pipeline organically as it learned what worked:

  • Phase 1: Basic attack-surface mapping + vulnerability hunting
  • Phase 2: Specialized language-specific agents added (Java, Python)
  • Phase 3: Critic agent for false-positive reduction
  • Phase 4: Offense/defense debate for high-stakes findings

Powered by RustyClawd β€” a Rust-based agentic LLM framework

Grew to 18 specialized agents across discovery, validation, debate, and self-improvement stages. Fixture F1 reached 92.9%.
Step 5

Agent Knowledge Graph Packs

Integrated agent-kgpacks β€” portable knowledge graph packages that encode:

  • Vulnerability patterns per CWE class
  • CWE taxonomies and family relationships
  • Investigation strategies learned from prior cycles

Purpose: Agents load domain-specific knowledge packs to bootstrap expertise without re-learning from scratch on every run. Accumulated institutional knowledge becomes portable and reusable across runs and agent instances.

  • Knowledge packs are versioned β€” improvements accumulate without overwriting
  • Different CWE families can load specialized expertise independently
Step 6

Agent Memory

Added durable agent memory (adapted from amplihack-memory-lib's cognitive memory model) so investigation insights persist across cycles:

  • Which detection strategies worked for which CWE families
  • Which proposals were rejected by the overfitting-reviewer and why
  • CWE-specific instructions that improved recall in prior cycles
Result: Agents build institutional knowledge over 22+ improvement cycles β€” each cycle starts smarter than the last.
  • Memory is durable β€” survives restarts and new deployments
  • Memory is queryable β€” agents retrieve relevant past experience before each investigation
  • Rejection reasons stored alongside accepted improvements β€” both inform future proposals
Step 7

Self-Improvement Loop

Built the gym improve command β€” agents started teaching themselves:

  • failure-analyst investigates each false negative, diagnoses why detection failed
  • Proposes improvements to agent prompts, taint rules, CWE mappings, or patterns
  • overfitting-reviewer validates every proposal before it is applied
  • Accepted improvements are written back to agent prompts, taint engine, and scoring
  • Rejected proposals are stored as lessons in durable memory
Key insight: The loop is closed β€” benchmark failures directly drive agent capability improvements, without a human in the loop for routine cycles.

Four proposal types (in preference order): AGENT_PROMPT β†’ TAINT_RULE β†’ CWE_MAPPING β†’ NEW_PATTERN

Step 8

The Importance of Not Overfitting

It became critical to ensure improvement loops don't "build to the benchmark" β€” overfitting to specific test cases rather than improving general detection.

Problem: A loop that only optimizes for benchmark score can learn benchmark artifacts β€” naming conventions, file structures, synthetic patterns β€” instead of real vulnerability semantics.

Response: built a specialized overfitting-reviewer agent with explicit rejection criteria:

  • Duplicate boilerplate proposals from different test cases
  • Benchmark-specific naming conventions
  • Narrow detection logic for broad CWE classes
  • Generic graph traversal where type/semantic analysis is needed
  • Speculative detection based on proximity rather than evidence
overfitting-reviewer has rejected ~66% of proposals across 22+ cycles β€” ensuring improvements generalize.
Step 9

Scale and Results

  • 22+ self-improvement cycles across all suites
  • 100+ proposals generated, 34% acceptance rate
  • Added CyberGym (3,014 real CVEs from OSS-Fuzz)
  • 6 benchmark suites now active
97.3%
Juliet F1 (agentic)
100%
Precision (all suites)
34%
Proposal accept rate
22+
Improvement cycles
Agentic eval: Juliet F1 = 97.3% β€” from a 50% starting baseline, bootstrapped by the loop itself.

Architecture: Five-Layer Detection Pipeline

Each vulnerability investigation passes through five layers, from fast pattern matching to deep semantic reasoning:

flowchart LR SRC["Source Code / Binary"] --> L1 L1["Layer 1\nPattern Detection\n~260 patterns / 6 langs"] --> L2 L2["Layer 2\nDataflow Analysis\nTaint source-to-sink"] --> L3 L3["Layer 3\nContext Validation\nFalse-positive reduction"] --> L4 L4["Layer 4\nLLM Agent Pipeline\nattack-surface Β· vuln-hunter Β· critic"] --> L5 L5["Layer 5\nSynthesis\nDomain-expert weighted evidence"] --> OUT["Findings"]

Why five layers? Fast layers (1-2) handle high-volume pattern detection. Slow layers (4-5) apply expensive LLM reasoning only where needed. Context validation (3) eliminates noise before agents see it.

Cost control: Pattern-only mode skips layers 4-5, enabling large-scale batch evaluation. Agentic mode activates all layers for high-confidence findings.

Architecture: Code Property Graph

All analysis operates on a code property graph stored in LadybugDB β€” functions, call edges, taint flows, data sources, data sinks, and symbols. Agents query this graph with specialized tools.

erDiagram FUNCTIONS ||--o{ CALLS : "caller-callee" FUNCTIONS ||--o{ DATA_SOURCES : "reads from" FUNCTIONS ||--o{ DATA_SINKS : "writes to" DATA_SOURCES ||--o{ TAINT_FLOWS : "source" DATA_SINKS ||--o{ TAINT_FLOWS : "sink" FUNCTIONS ||--o{ SYMBOLS : "defines-imports" FUNCTIONS ||--o{ FINDINGS : "contains"

Agent Tools

  • get_taint_paths β€” source-to-sink flow traces
  • get_cross_file_calls β€” cross-module call edges
  • get_data_sources β€” user-controlled inputs
  • get_imports β€” dependency analysis
  • build_analysis_context() β€” 2-hop call graph + string refs

Multi-Agent Analysis

All 18 agents and the pipelines they participate in:

flowchart TB subgraph INPUT["Input"] SRC["Source Code"] BIN["Binary"] end subgraph PREPROCESS["Pre-processing (binary only)"] DR["decompile-renamer"] DA["decompile-analyst"] end subgraph DISCOVERY["Discovery"] AS["attack-surface"] VH["vuln-hunter"] VHJ["vuln-hunter-java"] VHP["vuln-hunter-python"] TT["taint-tracer"] end subgraph VALIDATION["Validation"] CR["critic"] RS["results-skeptic"] CC["cwe-classifier"] end subgraph DEBATE["Debate (deep pipeline)"] EA["exploit-analyst"] DEF["defense-analyst"] end subgraph SYNTHESIS["Synthesis"] VS["verdict-synthesizer"] end subgraph IMPROVE["Self-Improvement"] FA["failure-analyst"] OR["overfitting-reviewer"] end SRC --> AS BIN --> DR --> DA --> AS AS --> VH & VHJ & VHP VH & VHJ & VHP --> TT --> CR CR --> RS --> CC --> VS CR --> EA & DEF --> VS VS --> OUT["Confirmed Findings"] OUT --> FA --> OR -->|"~34% accepted"| APPLY["Apply improvements"] OR -->|"~66% rejected"| MEM["Store lesson"] APPLY --> AS

Self-Improvement Loop

flowchart TB BENCH["Run Benchmark"] --> SCORE["Score Results"] SCORE --> FN["Identify False Negatives"] FN --> FA["failure-analyst\nReads code, queries graph\ndiagnoses WHY we missed it"] FA --> PROP["Generate Proposals\n1 Agent Prompt\n2 Taint Rule\n3 CWE Mapping\n4 Pattern"] PROP --> REV["overfitting-reviewer\nValidates proposals"] REV -->|Accepted| APPLY["Apply to agents\ntaint engine, scoring"] REV -->|Rejected| LEARN["Store lesson\nin durable memory"] APPLY --> MEM["Durable memory\nfor future cycles"] MEM --> BENCH

Proposal Types

TypeEffect
AGENT_PROMPTTeaches agents new investigation strategies
TAINT_RULEAdds source/sink definitions to dataflow engine
CWE_MAPPINGFixes scoring / classification
NEW_PATTERNRegex detection (last resort only)

Rejection Reasons (~66%)

  • Benchmark-specific naming conventions
  • Narrow logic for broad CWE classes
  • Speculative proximity-based detection
  • Duplicate boilerplate proposals

Results: Benchmark Suites

SuiteSourceCasesLanguagesFocus
JulietNIST54,488C/C++116 CWEs, synthetic variants
OWASP BenchmarkOWASP Foundation2,740JavaWeb app vulns (XSS, SQLi, crypto)
CyberSecEvalMeta578C/C++, PythonReal-world vuln patterns
CGCDARPA300CReal challenge binaries (patched/unpatched)
CyberGymUC Berkeley3,014C/C++Real OSS-Fuzz CVEs from 188 projects
Fixturesskwaq team99MixedRegression suite

Why multiple suites? Juliet tests synthetic breadth (116 CWEs). OWASP tests Java web semantics. CSE tests real-world C patterns. CyberGym tests real CVEs. No single suite validates the full capability envelope.

Results: Current Baselines β€” Pattern+Dataflow Mode

SuiteCasesF1PrecisionRecallTPFPFNTN
Fixtures9993.7%98.1%89.3%10321211
CSE57891.8%100%84.8%4340780
Juliet1,00088.8%100%79.9%79802011
OWASP50093.8%100%88.3%228030242
CGC22689.8%100%81.5%3880880
CyberGym10071.9%100%56.1%640500
100% precision across all benchmarks β€” zero false positives. The self-improvement loop runs continuously; scores grow with each cycle.

Results: Per-CWE Improvements (Self-Improvement Loop)

CWEBeforeAfterMethod
CWE-401 memory leak0%99%Agent-recommended calloc→ResourceLeak mapping
CWE-614 secure cookie0%100%setSecure(false) + semantic class fix
CWE-78 cmd injection37%70%spawn family (agent-identified taint rules)
CWE-22 path traversal41%65%java.io.File* qualified name fix
CWE-79 XSS46%63%getWriter().format/append (agentic cycle)
Race conditions33%100%signal handler + thread (agentic cycle)

Pattern: The loop finds the specific taint source/sink or agent reasoning gap that caused misses, proposes a targeted fix, and the overfitting-reviewer validates it generalizes beyond the specific test case.

Results: Industry Comparison

ToolApproachBenchmarkPrecisionRecallF1
Skwaq (agentic)Multi-agent + graphJuliet 20100%95%97.3%
VulBinLLMLLM decompile+reasonJuliet stripped~85%~100%~92%
PSΒ³Binary patternCurated dataset82%97%89%
LATTETaint + LLMJuliet~70%~85%~77%
IRIS (LLM+CodeQL hybrid) detected 2Γ— more vulns than CodeQL alone β€” validating skwaq's hybrid approach.
GitHub SecLab Taskflow Agent is the closest competitor architecture β€” 80+ real CVEs found using multi-agent investigation.

Note: Benchmarks differ across tools β€” direct comparison is approximate. See IRIS paper for methodology.

Improvement History: Key Milestones

PRChangeImpact
#29Gym benchmark harnessBaseline F1=50%
#35–39Agentic pipeline, multi-agent validationFirst agent-driven detection
#49Dual-judge breakthroughPrecision: 15%β†’100%
#57All 4 industry benchmark adaptersJuliet, OWASP, CGC, CSE
#217–24334 semantic classes, 109/109 Juliet CWEsFull CWE coverage
#298Industry expansionJuliet 1K, OWASP 1K, CSE 400
#302CyberGym + results-skeptic agent3,014 real CVEs added
#3033-layer improvement + 4 agentic cycles+7.6% Juliet, +8.0% OWASP
#312–313Agentic eval tuningJuliet F1=97.3%

Full benchmark progress and history β†’

Benchmark Ground-Truth & False-Positive Problem

Critical caveat: Benchmark answer keys are not complete precision oracles. Treating benchmark disagreement as a confirmed false positive leads to systematically wrong conclusions.
1 β€” Benchmark answer keys are incomplete

Suites like Juliet, OWASP, and CyberGym label specific synthesized or known vulnerabilities. They do not exhaustively label every real vulnerability in the code. A finding the benchmark does not expect may still be a genuine bug β€” the label set is a lower bound on truth, not an upper bound.

2 β€” Unlabeled findings may be real bugs

When skwaq reports a finding that the benchmark marks as a negative, that disagreement has three possible explanations: (a) a genuine false positive, (b) a real vulnerability the benchmark didn't label, or (c) a variant of a labeled vulnerability that falls outside the benchmark's expected form. Only (a) is a true FP. Conflating all three causes the tool to suppress valid detections.

3 β€” Benchmark disagreement β‰  confirmed false positive

Skwaq's 100% benchmark precision is real β€” but it reflects agreement with the benchmark's label set, not proof that every suppressed finding was wrong. Investigator review of "FP" cases on CyberGym and Juliet has surfaced genuine vulnerability variants outside the expected answer key. Improvement cycles must distinguish benchmark-label mismatches from actual detection errors.

Usage

Analyze Source

# Full agentic analysis
skwaq analyze /path/to/repo

# Quick pattern-only scan
skwaq analyze path/to/src.c --quick

Binary Analysis

# Analyze compiled binary
skwaq analyze path/to/binary --binary

# Stripped binary with renaming
skwaq analyze path/to/binary \
  --binary --decompile-rename

Benchmarks & Self-Improvement

# Agentic eval
skwaq gym eval \
  --suites juliet,owasp,cyberseceval

# Pattern-only eval (fast)
skwaq gym eval --suites juliet \
  --quick --max-cases 200

# Run improvement cycle
skwaq gym improve juliet \
  --max-cases 30 --max-improvements 5

# Target specific CWE
skwaq gym improve juliet \
  --cwe CWE-78 --max-cases 20

Supports Azure AI Foundry (GPT-5.4), Anthropic Claude (via Azure MaaS), and GitHub Copilot (Claude Opus 4.6) backends β€” configured in skwaq.toml.