Adaptive Campaigns¶
Why Adaptive?¶
A fixed-order scan runs every phase regardless of what it finds. This is predictable but wasteful -- if reconnaissance reveals the agent has no file access tools, running file-based exploitation phases produces no results.
Adaptive strategies use the knowledge graph to make better decisions: skip phases that won't yield findings, repeat phases where partial results suggest deeper vulnerabilities, and prioritize the most promising attack surface. This means higher coverage with fewer wasted interactions.
Strategies¶
Fixed (Default)¶
Runs phases in their defined sequential order. Simple, predictable, and deterministic.
ziran scan --target target.yaml --strategy fixed
Best for: CI/CD pipelines, reproducible scans, benchmarking.
Adaptive (Rule-Based)¶
Analyzes knowledge graph state after each phase and applies rules to decide the next action:
- Skip phases that are unlikely to yield findings based on discovered capabilities
- Re-order phases to prioritize the most promising attack surface
- Repeat phases with adjusted parameters when partial findings suggest deeper vulnerabilities
- Early termination when the graph shows the agent is fully hardened
ziran scan --target target.yaml --strategy adaptive
Best for: Thorough manual assessments, complex agents with many capabilities.
LLM-Adaptive¶
Uses an LLM to analyze the current knowledge graph, all previous findings, and the agent's capabilities to dynamically plan the next phase. The LLM acts as a strategy advisor -- it doesn't execute attacks, it decides which attacks to run and in what order.
ziran scan --target target.yaml --strategy llm-adaptive
Best for: Maximum coverage on high-value targets, red-team exercises.
LLM Required
The llm-adaptive strategy requires an LLM provider. Set --llm-provider and --llm-model, or use the ZIRAN_LLM_PROVIDER and ZIRAN_LLM_MODEL environment variables.
Comparison¶
| Aspect | Fixed | Adaptive | LLM-Adaptive |
|---|---|---|---|
| Deterministic | Yes | Partially | No |
| LLM required | No | No | Yes |
| Phase ordering | Sequential | Rule-driven | LLM-driven |
| Can skip phases | No | Yes | Yes |
| Can repeat phases | No | Yes | Yes |
| Token cost | None | None | Moderate |
| Best for | CI/CD | Manual assessment | Red-teaming |
How Adaptive Strategies Work¶
All three strategies follow the same loop -- execute a phase, update the knowledge graph, decide what to do next. The difference is how "decide" works:
flowchart TD
S["🚀 Start Campaign"] --> P["⚡ Execute Phase"]
P --> G["🧠 Update Knowledge Graph"]
G --> D{"Strategy\nDecision"}
D -->|"Fixed"| N["Next Phase\n(sequential order)"]
D -->|"Adaptive"| R["🔧 Rule Engine\n(graph-based rules)"]
D -->|"LLM-Adaptive"| L["🤖 LLM Advisor\n(dynamic planning)"]
R --> C{"Continue?"}
L --> C
N --> C
C -->|"Yes"| P
C -->|"No"| E["📋 Report"]
style S fill:#16213e,stroke:#0ea5e9,color:#fff
style P fill:#16213e,stroke:#0ea5e9,color:#fff
style G fill:#1a1a2e,stroke:#e94560,color:#fff
style D fill:#16213e,stroke:#e94560,color:#fff
style R fill:#0f3460,stroke:#10b981,color:#fff
style L fill:#0f3460,stroke:#10b981,color:#fff
style N fill:#0f3460,stroke:#10b981,color:#fff
style C fill:#16213e,stroke:#e94560,color:#fff
style E fill:#1e293b,stroke:#10b981,color:#fff
Python API¶
from ziran.application.strategies.adaptive import AdaptiveCampaignStrategy
from ziran.application.strategies.llm_adaptive import LLMAdaptiveCampaignStrategy
from ziran.application.strategies.fixed import FixedCampaignStrategy
# Use directly with the scanner
scanner = AgentScanner(adapter=adapter, attack_library=library)
# Fixed (default)
result = await scanner.run_campaign(strategy=FixedCampaignStrategy())
# Adaptive
result = await scanner.run_campaign(strategy=AdaptiveCampaignStrategy())
# LLM-Adaptive (requires LLM client)
result = await scanner.run_campaign(strategy=LLMAdaptiveCampaignStrategy(llm_client=client))
Custom Strategies¶
Implement the CampaignStrategy protocol to create your own strategy:
from ziran.application.strategies.protocol import CampaignStrategy
class MyStrategy(CampaignStrategy):
async def select_next_phase(self, context):
# Your logic here
...
async def should_continue(self, context):
# Your logic here
...
See Also¶
- Architecture -- Overall system design
- Trust Exploitation -- The 8-phase methodology
- CLI Reference --
--strategyoption documentation