-
-
Notifications
You must be signed in to change notification settings - Fork 2
Determinism and Anti Hallucination
LLMs hallucinate and are non-deterministic. Argo's design assumes this and wraps the model in deterministic gates and hard physical limits, so a wrong, invented, or unlucky model output is caught, bounded, or made harmless — never silently trusted or acted on.
Guardrails & Safety answers "can Argo do something it shouldn't?" (attack a live host, submit a report). This page answers the adjacent question: "can I trust what the model says, given that models make things up?" Three principles run through the whole pipeline:
- Take determinism out of the model's hands wherever a plain algorithm can do the job.
- Verify every consequential model claim against ground truth — the code, a schema, a real build, an actual observation.
- Physically bound what any run can consume or reach.
The model is a powerful proposer; the value comes from what the deterministic scaffolding does with its proposals.
-
Patch diffs are computed, not written. In Remediation & Fixes
the model supplies a full-file rewrite (
new_content) or exact search/replaceedits; Argo computes the unified diff mechanically withdifflib(fixes._mechanical_diff). The model never authors hunk headers, so it can't miscount@@ranges — the "corrupt patch" failure mode._apply_editsrequires eachsearchto match the file exactly once, else it rejects the whole file rather than half-applying it. - Live probes run in a fixed executor, not a model shell. In Runtime Verification / Live Verification the model proposes and interprets a probe plan, but a stdlib executor issues the requests — the model never gets a network/execution primitive.
-
Scoring is a deterministic matcher, not an LLM judge. Benchmarks & Costs
matches findings to labels by normalized CWE + file-suffix + line tolerance (
benchmark.score_run). -
Dedup is a pure key —
dedup_key(file + line + CWE), not a model similarity call.
-
Schema gates. Ingest validates
scope.jsonagainst its JSON Schema and refuses to proceed on an emptyprohibited_techniques; every finding is schema-validated. A malformed audit finding is repaired and flagged, never a silent whole-focus loss. -
Fixes must build, not just look right. A patch is accepted only if it deterministically applies
(
git apply -p1, fallbackpatch --fuzz=0) and compiles/builds (py_compile,node --check,go build,cargo check, or your--build-cmd/--docker) and introduces no new errors vs a pre-patch baseline — all on an isolated copy (verify.verify_patch). A model's "this is fixed" is worthless until the compiler agrees;--re-auditadds a second, unbiased check. -
Runtime / live confirmation. A static hypothesis becomes
confirmedonly when an observed runtime signal or in-scope HTTP response agrees, with a differentialcontrolprobe to judge the difference. - Adversarial, refute-first validation (Adversarial Validation). A user-proposed "why didn't you find X?" candidate is re-validated the same way and labelled an interactive probe — never silently promoted into the findings set.
- Corroboration against reality (Docs & History Corroboration) — downgrade by-design behavior, exclude already-fixed issues.
Unbounded model behavior — an infinite loop, a runaway agent — is capped by wall-clock and cost ceilings that fire regardless of what the model is "trying" to do.
-
Wall-clock timeouts —
session_timeout_s(default 1800s) + per-stagestage_timeouts; a hung session is killed, not waited on. Cancellation kills the whole process tree. -
Cost ceilings —
budget_usdHARD per-run abort;session_max_cost_usd(--max-budget-usd);session_max_turnstripwire. -
Concurrency + fan-out —
max_parallel_audits(3);max_focuses(used by--smoke). -
Sandbox anti-DoS — runtime
runtime_max_requests(50) + payload/boot caps; livelive_max_requests(30),live_max_writes(5, DELETE always blocked),live_max_redirects(3, each re-validated in-scope). An oversized probe plan is rejected whole, not truncated.
-
Read-only repo, single chokepoint — the target is mounted read-only to every session; detection
never patches it; remediation writes only to
patches/. TheAgentRunneris the one place tools are granted. - Offline by default — non-live stages get no network tools; only the bounded OSINT stages reach the public web, never the in-scope hosts.
- Files are the source of truth — every stage writes to disk and downstream stages re-read it; nothing hides in model memory.
-
Commit pinning —
argo pipeline --commit <sha>pins the source to an exact revision: identical input every time, and the basis for reproducible benchmark corpora. - Full ledger — every LLM call logged (model, tokens, cost); no hidden spend.
Plain-code assertions in argo/guardrails.py that run on the plan, not on a prompt — the model
can't talk its way past them: assert_prohibited_present, assert_no_network_tools,
assert_loopback_only + validate_probe_plan, assert_live_authorized, assert_inscope_only,
assert_live_write_policy. See Guardrails & Safety for what each enforces.
Every consequential step is either computed deterministically, verified against ground truth, or physically bounded. A hallucinated or unpredictable model output degrades to the safe outcome — a rejected finding, an unverified patch, a refused probe, an aborted-on-budget run — never a wrong action, a silently-trusted false claim, or an unbounded cost. That is what makes an LLM-native auditor safe to point at an arbitrary repository.
- Guardrails & Safety — the safety envelope (no live host, no auto-submit).
- Design Decisions — why Argo is LLM-direct with no CPG/AST engine.
- Remediation & Fixes · Benchmarks & Costs — the mechanical-diff and deterministic-scoring machinery in depth.