# sparshladani/sast-agentic-triage-workflow architecture

> Architecture diagram of the GitHub repository sparshladani/sast-agentic-triage-workflow, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/sparshladani/sast-agentic-triage-workflow
- Repository: https://github.com/sparshladani/sast-agentic-triage-workflow

## Overview

This repository is a prototype SAST-finding triage workflow: scanner SARIF is normalized, findings are investigated with bounded read-only tools, verdicts are validated and recorded, and a cited Markdown report is produced for human review. The README documents the LangGraph flow and its capabilities; the notebook is present in the tree but was not excerpted, so its implementation details cannot be verified. The normalization stage is supported by normalize.py. Edges cite the README where documented; normalization behavior cites its source.

Main entry points: [`sast_triage.ipynb`](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb) (Investigate finding), [`normalize.py`](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/normalize.py) (Normalize findings)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingest["Finding ingestion"]
  node_sarif["Scanner SARIF"]
  node_normalizer["Normalize findings<br/>[normalize.py]"]
  node_findings["Finding JSON"]
end

subgraph group_triage["Triage workflow"]
  node_load["Load state<br/>[sast_triage.ipynb]"]
  node_route_next{{"Select finding<br/>[sast_triage.ipynb]"}}
  node_investigate["Investigate finding<br/>[sast_triage.ipynb]"]
  node_tool_router{{"Route tool decision<br/>[sast_triage.ipynb]"}}
  node_finalize["Finalize verdict<br/>[sast_triage.ipynb]"]
end

subgraph group_safety["Investigation controls"]
  node_run_tools["Run read-only tools<br/>[sast_triage.ipynb]"]
end

subgraph group_outputs["Review outputs"]
  node_record["Record and validate extras<br/>[sast_triage.ipynb]"]
  node_report["Build triage report<br/>[sast_triage.ipynb]"]
  node_markdown["Markdown report"]
end

node_scanners["Semgrep / Bandit"]
node_user(("Analyst"))
node_repository["Target codebase"]
node_model["Language model"]

node_scanners -->|"emit SARIF"| node_sarif
node_sarif -->|"read reports"| node_normalizer
node_normalizer -->|"write findings"| node_findings
node_findings -->|"load input"| node_load
node_load -->|"initialize state"| node_route_next
node_record -->|"check remaining"| node_route_next
node_route_next -->|"findings remain"| node_investigate
node_route_next -->|"none remain"| node_report
node_investigate -->|"request analysis"| node_model
node_model -->|"return response"| node_investigate
node_investigate -->|"route response"| node_tool_router
node_tool_router -->|"tool call under cap"| node_run_tools
node_run_tools -->|"read code"| node_repository
node_run_tools -->|"return tool output"| node_investigate
node_tool_router -->|"answer or cap reached"| node_finalize
node_finalize -->|"request verdict samples"| node_model
node_model -->|"return verdicts"| node_finalize
node_finalize -->|"record verdict"| node_record
node_report -->|"compose report"| node_model
node_model -->|"return report text"| node_report
node_report -->|"write report"| node_markdown
node_user -.->|"provide scanner results"| node_findings
node_markdown -.->|"review findings"| node_user

click node_normalizer "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/normalize.py"
click node_load "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_route_next "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_investigate "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_tool_router "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_run_tools "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_finalize "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_record "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"
click node_report "https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_sarif,node_normalizer,node_findings toneBlue
class node_load,node_route_next,node_investigate,node_tool_router,node_finalize toneAmber
class node_run_tools toneMint
class node_record,node_report,node_markdown toneRose
class node_scanners,node_user,node_repository,node_model toneIndigo
```

## Components

### Finding ingestion

- **Scanner SARIF**
- [Normalize findings](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/normalize.py): `normalize.py`
- **Finding JSON**

### Triage workflow

- [Load state](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- [Select finding](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- [Investigate finding](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- [Route tool decision](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- [Finalize verdict](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`

### Investigation controls

- [Run read-only tools](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`

### Review outputs

- [Record and validate extras](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- [Build triage report](https://github.com/sparshladani/sast-agentic-triage-workflow/blob/main/sast_triage.ipynb): `sast_triage.ipynb`
- **Markdown report**

### Other components

- **Semgrep / Bandit**
- **Analyst**
- **Target codebase**
- **Language model**

## Connections

- Semgrep / Bandit → Scanner SARIF: emit SARIF (evidence: `README.md`)
- Scanner SARIF → Normalize findings: read reports (evidence: `normalize.py`)
- Normalize findings → Finding JSON: write findings (evidence: `normalize.py`)
- Finding JSON → Load state: load input (evidence: `README.md`)
- Load state → Select finding: initialize state (evidence: `README.md`)
- Record and validate extras → Select finding: check remaining (evidence: `README.md`)
- Select finding → Investigate finding: findings remain (evidence: `README.md`)
- Select finding → Build triage report: none remain (evidence: `README.md`)
- Investigate finding → Language model: request analysis (evidence: `README.md`)
- Language model → Investigate finding: return response (evidence: `README.md`)
- Investigate finding → Route tool decision: route response (evidence: `README.md`)
- Route tool decision → Run read-only tools: tool call under cap (evidence: `README.md`)
- Run read-only tools → Target codebase: read code (evidence: `README.md`)
- Run read-only tools → Investigate finding: return tool output (evidence: `README.md`)
- Route tool decision → Finalize verdict: answer or cap reached (evidence: `README.md`)
- Finalize verdict → Language model: request verdict samples (evidence: `README.md`)
- Language model → Finalize verdict: return verdicts (evidence: `README.md`)
- Finalize verdict → Record and validate extras: record verdict (evidence: `README.md`)
- Build triage report → Language model: compose report (evidence: `README.md`)
- Language model → Build triage report: return report text (evidence: `README.md`)
- Build triage report → Markdown report: write report (evidence: `README.md`)
- Analyst → Finding JSON: provide scanner results
- Markdown report → Analyst: review findings
