K.O.D.A. — open-source security specialist agent
Project description
K.O.D.A.
Kinetic Operative Defense Agent
Open-source security specialist — grounded tool-use, honest scanning, model-agnostic, air-gap ready.
Why · Install · Quickstart · Skills · NLU · Security · Architecture · Providers · Scanners · Roadmap · Issues
K.O.D.A. is an open-source AI security specialist built by Vektra Industries. It wraps your scanners, your intel, and your LLM of choice inside a harness that enforces Rules of Engagement, grounds every claim in tool evidence, signs every artifact, and behaves like an operator — not a chatbot with regex. It runs on a SOC workstation, an offline analyst laptop, or a $5 VPS. Local-first via Ollama; BYO key for hosted models. Zero telemetry. Zero phone-home.
If you want a security agent that can be trusted with a real engagement — authorized scope, reviewable decisions, auditor-grade evidence — this is it.
| Grounded tool-use | Every CVE, file path, line number, and CVSS score in assistant output must appear verbatim in a prior tool result. Fabrications are rejected before they reach the operator. |
| Rules-of-Engagement gate | Scope (CIDR/hostname) is declared up front. Destructive actions require explicit authorization. Every approval decision is logged to an append-only JSONL with fsync on security-relevant events. |
| Evidence-first | SHA-256 content-addressed artifacts, per-engagement merkle chain, portable tar.gz bundles that reverify offline with Python stdlib only — years later, on any machine. |
| External skill packs | Drop a SKILL.md directory into skills/ and it auto-registers. Frontmatter drives mode/phase/ATT&CK mapping; markdown body becomes the operator playbook. Ships with sherlock, oss-forensics, 1password; community packs compose. |
| Rule-based NLU router | Pure-Python intent classifier (recon / exploit / IR / audit / lookup / admin / chat) runs before every LLM call. Extracts targets (domains, IPv4, usernames, CVEs, paths), infers risk tier, ranks matching skills, emits a turn.route audit event. No LLM calls in the hot path. |
| Red / Blue / Purple harness | Phase-aware operator voice — 8 red phases (recon → exfil), 6 blue phases (defense, hunt, triage, IR, forensics, hardening). Every finding carries an ATT&CK technique ID. Sigma rules, CIS audits, and NIST 800-61 IR playbooks ship with the harness. |
| Model-agnostic | Eleven providers behind one adapter contract. Ollama, Claude CLI, Anthropic, OpenAI, Gemini, Groq, Together, OpenRouter, DeepSeek, xAI, Mistral. Switch with koda setup — no code changes. |
| Remote operations | Telegram bridge with inline-keyboard approvals, fragment buffering, and slash-command parity with the REPL. MCP server (stdio + SSE) exposes scanners and evidence tools to any MCP-compatible client. |
| Air-gap ready | Ollama local models, offline threat-intel cache (KEV, EPSS, CWE, NVD, ExploitDB, MITRE ATT&CK, CAPEC), stdlib-only verification. No outbound calls after initial corpus sync. |
Why K.O.D.A.
Most agent frameworks are general-purpose. Security work isn't.
The question a SOC lead, pentester, or IR consultant needs answered before handing an agent real access is always the same: can I trust its output to a client report? K.O.D.A. is engineered around that question. A grounding verifier rejects ungrounded claims. An approval gate fences every risky call. A credential broker redacts secrets across transcripts, evidence, and audit logs. A per-engagement merkle chain makes tampering detectable in a way that survives offline review.
The agent is narrow on purpose. It wraps scanners, not browsers. It reasons in MITRE ATT&CK IDs, not ad-hoc prose. It ships with rules of engagement, not a kitchen sink. Keeping scope tight keeps the trust boundary reviewable.
Ask → Route (NLU) → Approve → Tool-call → Ground → Evidence + Audit → Respond
Install
curl -fsSL https://koda.vektraindustries.com/install | bash
The installer handles Python 3.11+ via uv, venv, dependencies, PATH, and launches the first-run setup wizard.
Linux and macOS supported. Windows users should run under WSL2. Tested on Ubuntu 22.04+, Debian 12+, Kali, macOS 13+.
Manual install:
git clone https://github.com/PabloTheThinker/K.O.D.A..git && cd K.O.D.A.
python3 -m venv .venv && source .venv/bin/activate
pip install .
koda setup
Quickstart
koda setup # configure providers + verify credentials live
koda doctor # verify config + provider status
koda # start the interactive REPL
koda telegram # run the Telegram operator bridge
koda mcp # expose tools over MCP (stdio + SSE)
koda intel sync --all # pull offline threat-intel corpus
koda update # pull + install the latest release
koda version # print version and exit
koda uninstall # interactive removal checklist (--dry-run supported)
Skills
Skill packs are the extensibility seam. A skill is a directory with a single SKILL.md file:
skills/
sherlock/
SKILL.md # YAML frontmatter + markdown playbook
The frontmatter drives mode, phase, MITRE ATT&CK mapping, and prerequisites. The markdown body is injected into the system prompt as an operator playbook when the phase is active:
---
name: sherlock
description: OSINT username search across 400+ social networks.
version: 1.0.0
mode: red
phase: recon
attack_techniques: [T1589, T1593]
tools_required: [shell.exec]
prerequisites:
commands: [sherlock]
---
# Sherlock OSINT Username Search
...
Packs auto-register from three locations at boot:
./skills(project-local)~/.koda/skills(per-user)$KODA_SKILLS_PATH(colon-separated, OS-path style)
Malformed packs don't raise — they surface as (path, message) errors the loader reports back. To load manually:
from koda.skills import load_default_packs
count, errors = load_default_packs()
Built-in packs (v0.3.0):
| Pack | Mode | Phase | ATT&CK | Purpose |
|---|---|---|---|---|
sherlock |
red | recon | T1589, T1593 | OSINT username search across 400+ social networks |
oss-forensics |
blue | ir | T1195.002, T1588.001 | Supply-chain investigation of GitHub repositories |
1password |
blue | hardening | T1552.001 | 1Password CLI integration for secret handling |
Community packs compose the same way — drop the directory in skills/ and it's live.
NLU Router
Before every LLM call, a pure-Python rule-based router classifies the user's request:
- Intent — recon, exploit, IR, audit, lookup, admin, chat, or ambiguous
- Targets — domains, IPv4 addresses, usernames, CVE IDs, file paths
- Risk tier — SAFE, SENSITIVE, or DANGEROUS (EXPLOIT → DANGEROUS; active recon → SENSITIVE; passive recon → SAFE)
- Matched skills — registry-backed ranking of packs whose mode/phase fits the intent
- Clarify question — one sharp question when scope or intent is unclear
The decision is injected into the system prompt as an <nlu> hint block and emitted as a turn.route audit event. The model still makes the call — the router is a pre-LLM signal layer, not a gate.
from koda.nlu import IntentRouter
router = IntentRouter()
decision = router.route("find accounts for username johndoe123")
# decision.intent == Intent.RECON
# decision.risk == RiskTier.SAFE
# decision.matched_skills[:3] == ('red.recon', 'red.enumeration', 'sherlock')
Zero network calls. All regex compiled at module load. Deterministic.
Security Model
K.O.D.A. is a security tool, so the trust boundary is the product. Five components enforce it:
- Grounding verifier. Assistant text is checked against the tool transcript before release. Ungrounded CVEs, file paths, and line numbers are rejected.
- Approval gate. Every tool carries a risk tier — SAFE / SENSITIVE / DANGEROUS / BLOCKED — with argument-level guardrails. BLOCKED never runs. Thresholds are set per-engagement at wizard time.
- Credential broker. Per-engagement vault with placeholder detection, cooldown on failure, and automatic redaction across transcripts, evidence, and audit rows.
- Tamper-evident evidence. SHA-256 content addressing, per-engagement merkle chain, portable
tar.gzbundles that reverify with Python stdlib only. - Append-only audit. JSONL with
fsyncon security-relevant events, size-rotated, engagement-scoped.
Found a vulnerability? See SECURITY.md — do not open a public issue.
Architecture
┌──────────────────────────────────────────────────────────────┐
│ Operator │
│ (REPL · Telegram · MCP) │
└──────────┬───────────────────────────────────┬───────────────┘
│ │
▼ ▼
┌───────────────────────┐ ┌──────────────────────────┐
│ NLU router │ │ Approval gate │
│ intent · risk · scope│ │ SAFE|SENSITIVE|DANGER │
└──────────┬────────────┘ └────────────┬─────────────┘
│ │
▼ │
┌───────────────────────┐ │
│ Provider adapter │ │
│ (11 backends, BYO) │ │
└──────────┬────────────┘ │
│ │
▼ ▼
┌───────────────────────┐ ┌──────────────────────────┐
│ Grounding verifier │◀─────────▶│ Tool registry │
│ reject fabrications │ │ scanners · fs · net │
└──────────┬────────────┘ └────────────┬─────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ Evidence store (SHA-256 + merkle chain, tar.gz bundles) │
│ Audit log (append-only JSONL, fsync) │
│ Credential broker (per-engagement, redaction) │
│ Local threat intel (KEV / EPSS / CWE / NVD, offline) │
│ Skill registry (built-in + SKILL.md packs) │
└──────────────────────────────────────────────────────────────┘
Flow: the operator prompts, the NLU router classifies intent and risk, the provider routes through the matched skill, the approval gate guards, the tool runs, the grounding verifier checks the output, evidence and audit capture the transcript. Scanners plug in through a uniform Finding contract.
Providers
Eleven providers — local-first, BYO model. The wizard pings each candidate with a real chat roundtrip before writing config, so you know credentials work before the first engagement.
| Provider | Detect | Key env |
|---|---|---|
| Ollama | http://127.0.0.1:11434 reachable |
(none — local) |
| Claude CLI | claude binary on PATH |
(none — CLI auth) |
| Anthropic | ANTHROPIC_API_KEY |
ANTHROPIC_API_KEY |
| OpenAI | OPENAI_API_KEY |
OPENAI_API_KEY |
| Google Gemini | GEMINI_API_KEY / GOOGLE_API_KEY |
GEMINI_API_KEY |
| Groq | GROQ_API_KEY |
GROQ_API_KEY |
| Together AI | TOGETHER_API_KEY |
TOGETHER_API_KEY |
| OpenRouter | OPENROUTER_API_KEY |
OPENROUTER_API_KEY |
| DeepSeek | DEEPSEEK_API_KEY |
DEEPSEEK_API_KEY |
| xAI (Grok) | XAI_API_KEY / GROK_API_KEY |
XAI_API_KEY |
| Mistral | MISTRAL_API_KEY |
MISTRAL_API_KEY |
On verification failure: retry with new creds, skip (save anyway), or abort.
Scanners
Eight scanner wrappers plus a generic SARIF 2.1.0 reader. Findings flow through a uniform contract: content-fingerprint dedup, KEV/EPSS/CVSS enrichment, severity upgrade on KEV hit.
| Tool | Role |
|---|---|
| Semgrep | Source-code static analysis |
| Bandit | Python security linter |
| Gitleaks | Secret detection in git history |
| Trivy | Container / filesystem / dependency scan |
| OSV-Scanner | OSS vulnerability enumeration |
| Grype | SBOM / image vulnerability scan |
| Nuclei | Template-driven network / web probes |
| Nmap | Network reconnaissance |
| SARIF reader | Ingest any SARIF 2.1.0 output |
Security Harness
K.O.D.A. ships with a phase-aware security harness that turns any connected model into a disciplined operator — red, blue, or purple.
koda intel sync --all # offline corpus: KEV, EPSS, CWE, NVD,
# ExploitDB, MITRE ATT&CK, CAPEC
koda intel lookup CVE-2021-44228 # full chain: CVE → KEV → EPSS → CWE
# → linked exploits → ATT&CK
koda report generate \ # exec, technical, Markdown, SARIF 2.1
--findings findings.jsonl --out ./reports
Red mode exposes 8 phase skills (recon → enumeration → initial access → execution → persistence → privesc → lateral → exfil). Blue mode exposes 6 (defense, hunt, triage, IR, forensics, hardening). Each phase injects its own ATT&CK-tagged skill fragment into the system prompt so the model reasons in TTPs, not in ad-hoc prose. A Rules-of-Engagement gate enforces scope (CIDR/hostname), blocks destructive actions, and logs every decision to <KODA_HOME>/engagements/<roe_id>/roe.jsonl. Sigma rules, CIS audits, and NIST 800-61 IR playbooks are bundled. Stdlib-only.
Operator persona. Koda speaks as a professional red-turned-blue operator: calm, precise, ROE-first, evidence-over-opinion, jargon-matching. It infers the narrowest reasonable scope from vague asks, drops ceremony under incident pressure, and refuses action outside declared scope. The persona block loads into every system prompt.
Engagements
Every session is scoped to an engagement — a named boundary for a pentest, IR case, or audit. Sessions, credentials, evidence, and audit rows all carry the engagement label. Set it via KODA_ENGAGEMENT=acme-q2 before starting the REPL, or leave it at default for personal use.
Remote Operations
K.O.D.A. ships a Telegram bridge for running engagements from a phone. Configure via koda setup (Stage 8), or manually by writing ~/.koda/secrets.env:
KODA_TELEGRAM_BOT_TOKEN=<BotFather token>
KODA_TELEGRAM_CHAT_ID=<your Telegram user id>
koda telegram runs a daemon that relays messages, approvals, and alerts to your chat. Only the configured CHAT_ID is served — all other chats are audit-logged and dropped. Inline-keyboard approvals, inbound photos/documents (25 MB cap), fragment buffering, and slash commands (/help, /new, /reset, /status, /model, /models, /history, /stop) work from both the REPL and Telegram with parity. Stdlib-only — no third-party dependencies.
An MCP server is also available: koda mcp exposes the scanner and evidence tools to any MCP-compatible client (stdio + SSE transports).
Status & Roadmap
Beta. The harness, 11 provider adapters, grounding verifier, approval gate, credential broker, evidence store, threat-intel cache, 8 scanner wrappers, external skill pack loader, NLU router, Telegram bridge, and MCP server are live with smoke coverage (scripts/smoke.sh) and a focused unit suite (tests/). CI runs lint + install matrix on every push. API surface is stabilizing; expect small breaking changes before 1.0.
See ROADMAP.md for what's next.
Migrating From
K.O.D.A. draws architectural inspiration from two projects — here's how the concepts map if you're already using them:
- Hermes Agent — K.O.D.A.'s profile isolation, REPL slash-command grammar, and
SKILL.mdpack format are Hermes-style. If you have Hermes skill packs, they typically load with minor frontmatter additions (mode,phase,attack_techniques). - OpenClaw — OpenClaw's installer UX and onboarding flow are the model for
install.shandkoda setup. If you've used OpenClaw skills, the risk-tier approval model maps directly onto OpenClaw's approval prompts.
A full migration guide will land in docs/migrating.md once the hosted docs site is up.
Contributing
See CONTRIBUTING.md. Short version: run ruff check . && pytest tests/ && scripts/smoke.sh, update CHANGELOG.md under [Unreleased], open a PR. Agent-readable project instructions live in AGENTS.md.
Security issues go to SECURITY.md, not public issues.
License
MIT — see LICENSE.
Architectural credit: K.O.D.A. is an independent reimplementation inspired by the open-source harness patterns of Nous Research's Hermes (MIT) and OpenClaw. No code was copied; the patterns were analyzed and rewritten from scratch for the security domain.
Built by Vektra Industries.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file koda_security-0.5.0.tar.gz.
File metadata
- Download URL: koda_security-0.5.0.tar.gz
- Upload date:
- Size: 232.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a95ce7ba8a97e2a5f85067a004f3045843ea85da7f7a7b469e2739696bb5e82d
|
|
| MD5 |
d1f3ef592f096b29c05706e8ed64d7a4
|
|
| BLAKE2b-256 |
871c61548f99087897ecae19c94f7433b61ec48023005afd6f7edda578366cb9
|
Provenance
The following attestation bundles were made for koda_security-0.5.0.tar.gz:
Publisher:
release.yml on PabloTheThinker/K.O.D.A.
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
koda_security-0.5.0.tar.gz -
Subject digest:
a95ce7ba8a97e2a5f85067a004f3045843ea85da7f7a7b469e2739696bb5e82d - Sigstore transparency entry: 1340716993
- Sigstore integration time:
-
Permalink:
PabloTheThinker/K.O.D.A.@4bec5b41759601fa290282b8c9cd685f8cc40b12 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/PabloTheThinker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4bec5b41759601fa290282b8c9cd685f8cc40b12 -
Trigger Event:
push
-
Statement type:
File details
Details for the file koda_security-0.5.0-py3-none-any.whl.
File metadata
- Download URL: koda_security-0.5.0-py3-none-any.whl
- Upload date:
- Size: 255.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1996e267e925b7f980e5dbf92974e1fdd1133807d64bc51b8216bab611e2bdc1
|
|
| MD5 |
7262ebbd3eab764e4baa83f73cebeca6
|
|
| BLAKE2b-256 |
37ff0ad0f28ed5df82d7340be81fda0261f3da943a6d063eee75ad998f1bfb4d
|
Provenance
The following attestation bundles were made for koda_security-0.5.0-py3-none-any.whl:
Publisher:
release.yml on PabloTheThinker/K.O.D.A.
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
koda_security-0.5.0-py3-none-any.whl -
Subject digest:
1996e267e925b7f980e5dbf92974e1fdd1133807d64bc51b8216bab611e2bdc1 - Sigstore transparency entry: 1340717001
- Sigstore integration time:
-
Permalink:
PabloTheThinker/K.O.D.A.@4bec5b41759601fa290282b8c9cd685f8cc40b12 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/PabloTheThinker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4bec5b41759601fa290282b8c9cd685f8cc40b12 -
Trigger Event:
push
-
Statement type: