Use this file to choose models and backends for VVAH roles, and to find the typed records passed between stages. A backend choice affects credentials, tool access and runtime limits—not only which API receives a request.
| Part | Use it to |
|---|---|
| Model selection & backends | Choose a model and route for each LLM-backed role. |
| Pydantic data models | Find the validated contracts exchanged by the pipeline. |
An active model role is configured as {id, via, provider}. The via value
selects cli, sdk, openai, or deepagents; provider applies only to
DeepAgents and selects the Anthropic Messages or OpenAI-compatible protocol.
The pipeline combines deterministic and LLM-backed stages. S0, S1, S3, S5 and
S9 are deterministic. S7 calls models.dedup only when semantic dedup is
enabled, but every profile must still set models.dedup, because the scan reads it.
The shipped default.yaml runs auto-step1 and S2/S4/S6/S8 through
DeepAgents/Anthropic, normally on claude-opus-4-7. S10 and S11 are off in this
profile; --remediate turns S10 on. Detection uses the API route directly: one
of ANTHROPIC_SDK_API_KEY, ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN covers
it, and the claude CLI is optional. With this profile, in-scan S10 and S11
need ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN; without one, the scan skips
them.
| Step | Model role | Default behavior | Available model routes |
|---|---|---|---|
| s0 static seed | No model call | In-process source/sink pattern matching | Not applicable |
| auto-step1 | autoexclude |
DeepAgents/Anthropic, single-shot | cli · sdk · openai · deepagents |
| s1 preprocess | No model call | In-process inventory, context and graph metadata | Not applicable |
| s2 threat model | threatmodel |
DeepAgents/Anthropic, agentic | cli · sdk · openai · deepagents |
| s3 decompose | No model call | In-process investigation-unit construction | Not applicable |
| s4 deep dive | deepdive |
DeepAgents/Anthropic, agentic | cli · sdk · openai · deepagents |
| s5 prefilter | No model call | In-process filtering | Not applicable |
| s6 verify | verify |
DeepAgents/Anthropic, agentic | cli · sdk · openai · deepagents |
| s6 exploit verification | exploit_verification.* |
Opt-in; DeepAgents/Anthropic | cli · sdk · openai · deepagents; attacker uses sdk · openai · deepagents |
| s7 dedup | dedup when semantic: true |
Deterministic in every shipped profile | cli · sdk · openai · deepagents when enabled |
| s8 chain | chain |
DeepAgents/Anthropic, no tools | cli · sdk · openai · deepagents |
| s9 SARIF | No model call | In-process rendering | Not applicable |
| s10 remediate | remediate |
Configured for opt-in DeepAgents/Anthropic use | cli · sdk · deepagents; openai only with remediate --mode report-only |
| s11 DTO discovery | No model call | In-process discovery | Not applicable |
| s11 validation | validate and personas |
Configured for opt-in DeepAgents/Anthropic use | cli · sdk · deepagents; openai normalizes to DeepAgents/OpenAI |
Four model keys belong to stages that make no model call: S0, S1 and S3 are
deterministic. Keep models.preprocess and models.decompose set to a
reachable model, as every shipped profile does. The scan reads both keys, and
preflight sends each configured detection role a live probe before any stage
runs.
| Key | Current behavior |
|---|---|
models.preprocess |
Required. Supplies the auto-step1 model when models.autoexclude is unset. Preflight also probes its tool round trip. S1 makes no model call. |
models.decompose |
Required. Preflight probes it. S3 makes no model call. |
models.graph_annotate |
Probed by preflight only when step0.callgraph_detection: llm is set. S0 makes no model call. |
models.callgraph_creation |
Probed by preflight only when step0.callgraph_detection: llm is set, on the cli, sdk and openai routes. S0 makes no model call. |
See the User Guide for route selection and the errors reference for recovery behavior.
Exploit verification sends live attack traffic. This Beta S6 pass for API targets sends requests, including state-changing ones, to a localhost target. Setting
EV_API_COLLECTIONturns it on, and a value left in.envcounts.--resumeturns it back on for a run that had it. To send no traffic, unsetEV_API_COLLECTIONand start a fresh run without--resume.
When exploit verification runs, its judge and classify roles are required.
The optional attacker role uses sdk, openai or DeepAgents so it can receive
the in-process http_request tool. See
Exploit verification.
In-scan S10 edits target files. S10 and S11 run inside
scanwhen a profile enables them;sdk.yamlandfull.yamldo. In-scan S10 always usesfixmode. Pass--stop-after s9for a detection-only run. See Stages.
S10 and S11 also run as the remediate and validate commands: remediate
proposes fixes and writes DTOs; validate discovers DTOs deterministically and
then grades them with an agentic panel.
Validation always runs three personas: security_architect,
penetration_tester, and cross_repo_analyzer. Each inherits the orchestrator
model unless its own id is set; all shipped profiles set the ids explicitly.
models:
validate:
orchestrator: {id: claude-opus-5, via: deepagents, provider: anthropic}
security_architect: {id: claude-opus-4-8}
penetration_tester: {id: claude-opus-4-8}
cross_repo_analyzer: {id: claude-opus-4-8}The orchestrator selects the backend and provider for the whole panel. Persona
entries set id and inherit that route. Preflight enforces one API family for
the complete panel before staging a workspace or spending tokens; a mismatch
exits with code 2. For configuration compatibility, via: openai on the
orchestrator resolves to {via: deepagents, provider: openai}. See
Validation for the panel workflow.
Five profiles ship in vvaharness/config/profiles/:
| Profile | Use it when | Main difference from default.yaml |
|---|---|---|
default.yaml |
Standard detection scan | Baseline: DeepAgents/Anthropic for every model role; S10/S11 off. |
full.yaml |
You want broader candidate coverage and accept higher cost | Raises finding/threat caps, lowers verification and duplicate thresholds, enables S10/S11, and uses an OpenAI-compatible model for the EV judge, which an EV run needs (OPENAI_API_KEY). |
sdk.yaml |
You require Anthropic SDK routing without shell access | Every model role uses SDK; S10/S11 enabled. S11 needs Claude login/OAuth or standard Anthropic credentials. |
semgrep.yaml |
S2/S4/S6 should consult Semgrep output | Adds p/security-audit, p/python, and p/secrets; four read-only graph tools expose matches, taint traces, sink callers and coverage. Needs semgrep on PATH. |
taint.yaml |
You want source/sink-oriented investigation tuning | Same routes as default.yaml. Tuning only, with no separate taint engine: one S4 unit per batch, S2/S4 planning on, and unmetered S4/S6 model calls. S10/S11 off. |
All five enable auto-step1, use deterministic S7 dedup, and keep S2/S4 shell access off. For exact values and credentials, use the profile comparison.
Choose a backend for its transport, tooling and security controls. Evaluate model quality separately on representative repositories.
via |
Transport | Tool and limit differences |
|---|---|---|
cli |
claude subprocess for detection/S10, with stage tools through the Claude Agent SDK bridge while cli.mcp_tools is on; Claude Agent SDK for S11 |
Read/Glob/Grep and optional Bash; S10 fix mode adds Edit/Write and excludes Bash. A deepdive on this route needs cli.mcp_tools: true; preflight stops the scan otherwise. Supported runtime controls are CLI-version dependent; this transport has no flags for temperature, thinking_budget or betas. |
sdk |
Anthropic Python SDK; Claude Agent SDK for mutating S10 and for S11 | Read-only detection tools; repo-confined S10 edits; hard max_turns; supported temperature/thinking settings and schema output. |
openai |
OpenAI-compatible Chat Completions, with a learned or pinned Responses path for tool calls | Sandboxed read-only tools; temperature, max_turns, and schema output with JSON-object fallback. |
deepagents |
DeepAgents/LangGraph over Anthropic or OpenAI-compatible APIs | Tool-free single-shot roles; stage-scoped tools on agentic roles; repo-confined S10 edits. Supported controls are timeout, effort and max_turns. Here max_turns sets a LangGraph recursion limit of max_turns + 900, not a turn cap, so bound sessions with max_model_calls, max_tokens and stage deadlines (budgets). Top-level think_in_prompt, on in every shipped profile, replaces native reasoning with reasoning written in the prompt for faster sessions; set it to false to restore native reasoning. max_budget_usd, temperature, thinking_budget and betas are outside this route's runtime controls. |
DeepAgents is a backend, not a profile. Without provider, a DeepAgents role
uses the Anthropic API only when its model id contains claude; set provider
for any other id, such as a gateway-namespaced one. A model entry without
via, including a bare-string id, uses via: cli. See
User Guide,
Deep Agents route, and
security.md for credentials, TLS/mTLS,
tool confinement, fallbacks and exact limits.
max_tokens on a model node caps that model's output; stage-level token keys
set per-request limits, which are clamped to the model cap. When an endpoint's
limit is lower than the stage request, set the model cap to keep requests within
the provider's accepted range. See
User Guide and
errors.md for route defaults and
retry behavior.
Select models by their demonstrated API, tool-use, structured-output and context capabilities rather than parameter count alone. Use probes to confirm connectivity and representative scans to evaluate detection quality.
| Dimension | Requirement | Why it matters |
|---|---|---|
| API surface | Match via and provider |
The endpoint must implement the selected protocol. |
| Tool use | Reliable multi-turn replay where required | S2, S4, S6, EV, S10 and S11 may continue after tool calls. |
| Structured output | Reliable schema/tool output | Keeps stage responses valid and machine-readable. |
| Context and output | Fit the configured operation | Prompts, tool results and expected output must fit together. |
| Quality | Validate on your workload | Representative evaluation establishes security recall for your codebase. |
“OpenAI-compatible” describes an API protocol, not a model family. VVAH has run models from the families below. The list is illustrative, not an allowlist or a quality ranking; other models can be used when they meet the selected route's API and role requirements.
| API protocol | Examples tested | Notes |
|---|---|---|
| Anthropic Messages | Claude Opus, Sonnet and Mythos | Shipped profiles use Claude Opus and Sonnet for every role except the full.yaml exploit-verification judge, which uses an OpenAI-compatible model. |
| OpenAI-compatible | GPT, Grok, Kimi, GLM and Gemini | Tested using OpenAI-compatible API endpoints. |
Before production use, validate the exact model, endpoint and route in your environment.
VVAH adapts transport behavior for known API differences. The tested combinations below have specific routing guidance for reliable tool workflows.
| Model and route | Compatibility consideration | Recommended configuration |
|---|---|---|
| Gemini via DeepAgents | In tested multi-turn tool sessions, replay may omit required state such as thought_signature, causing the next request to fail. |
Use direct via: openai for tool-using detection or exploit-verification roles that support it. For S10 fix and S11, use another compatible model. Tool-free calls are not affected by this issue. |
| Kimi K2.6, Kimi K2.7 Code or GLM 5.2 via the DeepAgents Responses API | In tested configurations, responses could end before emitting the required tool call. | Keep automatic transport selection: it uses Chat Completions for kimi-k2.6, kimi-k2.7-code and glm-5.2, also behind a vendor/ gateway prefix. For another Kimi or GLM id, test both transports and pin use_responses_api. Pin use_responses_api: true for a listed id only after verifying that path on your endpoint. |
See errors.md for the Gemini diagnostic signature and troubleshooting guidance.
| Role | Suggested tier | Reason |
|---|---|---|
| Detection | Mid-to-high reasoning | Balance security analysis against repeated S4/S6 calls, latency and cost. |
| S10 remediation | High reasoning | Proposed code changes require strong correctness reasoning. |
| S11 orchestrator | High reasoning | It synthesizes adversarial persona results into a verdict. |
| S11 personas | Mid-to-high reasoning | Each performs an independent review of the full diff. |
Use these tiers as starting points and tune them with representative evaluations.
Change an active role in a git-ignored config.local.yaml beside the profile;
no code change is required:
models:
threatmodel: {id: <anthropic-model-id>, via: deepagents, provider: anthropic}
deepdive: {id: <openai-compatible-model-id>, via: openai}
verify: {id: <claude-model-id>, via: cli}Raise
max_turnswhen a role leaves DeepAgents. Oncli,sdkandopenai,max_turnsis a hard per-session turn cap. The shipped DeepAgents profiles set 12–30 for S2, S4 and S6, and on DeepAgents that value does not cap turns. As a hard cap, it can stop a stage before it finishes its analysis. Raisestep2.max_turns,step4.max_turnsorstep6_verify.max_turnswhen you movethreatmodel,deepdiveorverify;sdk.yamluses 60, 60 and 30. Preflight warns at 20 or lower.
To verify a swap with a real model call, use an active role such as
threatmodel, deepdive or verify. See
User Guide for model configuration and
Deep Agents route for provider-specific behavior.
For roles whose matrix includes it, use direct via: openai for an
OpenAI-compatible endpoint. Use DeepAgents with provider: openai where the
role supports DeepAgents and its tooling is required. DeepAgents also supports
mTLS; the User Guide lists which
setting each stage reads.
models:
threatmodel: {id: <model-id>, via: deepagents, provider: openai}# .env — keep credentials outside YAML
OPENAI_API_KEY=<vendor-api-key>
OPENAI_BASE_URL=<openai-compatible-base-url>| Constraint | What to do |
|---|---|
| Endpoint count | All OpenAI-compatible roles in one run share one OPENAI_BASE_URL. Use an aggregating proxy to reach multiple OpenAI-compatible vendors. |
| Azure OpenAI | Use the /openai/v1/ surface with the deployment name as the model id. Classic per-deployment endpoints require a compatible proxy. |
| Structured calls | Confirm the endpoint's tool_choice and schema support. Some compatible endpoints accept only auto or none. |
| Token parameter | Direct OpenAI automatically retries with max_completion_tokens when required; DeepAgents uses LangChain translation. Set the cap high enough to include the model's reasoning budget. |
| TLS and mTLS | Follow the User Guide. Direct via: openai cannot present a client certificate; use DeepAgents with provider: openai for an mTLS endpoint. When a configured mTLS chain cannot be loaded, VVAH warns and keeps server-authenticated TLS; confirm activation in stderr. |
| Pricing | Supply pricing.file or VVAHARNESS_PRICING_FILE to populate cost_usd. Models without a pricing entry report null. See architecture.md. |
| Prompt caching | DeepAgents uses sdk.cache_markers; direct SDK/OpenAI use the top-level cache_markers. Set both to off for strict gateways and verify with doctor --cache-probe. |
See the User Guide for credentials and Gateway and budget decisions for provider, caching and connection details.
VVAH uses Pydantic, a Python data-validation library, for most pipeline
contracts. Runtime validation contains invalid stage output at a defined
boundary. SeedPackage is a dataclass; most other public contracts inherit from
Pydantic BaseModel.
| Area | Primary contracts | Location |
|---|---|---|
| Scan inputs | CVE, Control, AppProfile |
models/scan/inputs.py |
| Static seed and surface | SeedPackage, EntryPoint, Sink, ModuleInfo |
models/scan/seed.py, models/scan/surface.py |
| Scan context | ContextPackage |
models/scan/context.py |
| Threat model | Asset, TrustBoundary, Threat, ThreatModel |
models/scan/threat.py |
| Work decomposition | InvestigationUnit, TaskManifest, DupLocation, UnitSize |
models/scan/work.py |
| Findings and chains | Finding, RankedFinding, DroppedFinding, LinkEvidence, Chain |
models/scan/findings.py |
| Metrics and report | ScopeEntry, ScanMetrics, FinalReport |
models/scan/metrics.py, models/scan/report.py |
| Finding lifecycle | Attempt, FindingCase, ScoringPolicy |
models/case.py, models/context.py |
| Evidence and gates | EvidenceAnchor, GateAssessment |
models/gates.py |
| Remediation | FileChange, Remediation, RemediationEvidence |
models/remediation.py |
| Validation | Ticket, Verdict |
models/verdict.py |
| Provenance and vocabulary | Provenance, gate/state/remediation enums |
models/provenance.py, models/vocab.py |
Import these contracts from the public vvaharness.models or
vvaharness.models.scan namespaces.
S0 leaves SeedPackage.taint_paths empty; source/sink evidence is in
EntryPoint and Sink.