Extension Guide
This guide explains where to edit code when adding tools, integrations, config, runtime behavior, or tests. It assumes contributors have already read architecture.md, module-guide.md, and safety-model.md.
Add a Defensive MCP Tool
Use this path for scan-only or intelligence tools that should stay tightly scoped.
Edit:
mcp_server.py: add a new@mcp.tool()insidecreate_mcp_server.tools/validation_utils.py: add or reuse target/input validation helpers if the tool accepts hosts, IPs, URLs, or commands.tests/: add a focused test near existing MCP/safety coverage.
Follow these patterns:
- Normalize and check allowlists before touching a target.
- Return structured dictionaries with status, command/result text, and error details.
- Keep commands narrow. Existing nmap tools use fixed arguments and
_run_nmap. - Avoid shell expansion where possible.
Relevant tests:
tests/test_scope_gate.pytests/test_mcp_workspace.pytests/test_command_analyzer.pytests/test_recon_pipeline.py
Add an Exploit MCP Tool
Use this path only when the capability belongs in the broader exploit workspace.
Edit:
tools/mcp_tools/<category>.py: add the@mcp.tool()implementation inside the relevantregister_<category>_tools(...)function.tools/mcp_tools/registry.py: add MCP-tool-local shared helpers or dependency bundle fields only when the helper is genuinely shared by multiple exploit tool modules.mcp_exploit_server.py: update wiring only if the new tool needs a new category module or shared service.tools/mcp_shared.py: reuse workspace path resolution, audit logging, allowlist checks, and redaction helpers.tools/exploit_agent/policy.py: updateExploitPolicyso the model cannot call the tool outside the intended permission mode.tools/command_analyzer.py: update command/code analysis if the tool runs shell, Python, Metasploit, package installs, listeners, callbacks, or file writes.tests/: add policy, audit, redaction, and workspace tests.
Required safety work:
- Gate the tool by
ExploitPermissionmode. - Check
exploit.require_explicit_allowlistandexploit.allowed_targetsfor target-touching calls. - Write generated files into the configured workspace.
- Redact secrets before audit logging.
- Sanitize large output before returning it to the model.
- Preserve public MCP tool names, function signatures, return text formats, audit decorators, and config semantics when refactoring existing tools.
Current exploit MCP categories:
terminal.py: terminal, package, install, environment, and root-command helpers.workspace.py: workspace read/list/write helpers and Python file write/run helpers.research.py: exploit search, web fetch, deep research, and CVE lookup.runtime_skills.py: read-only runtime skill listing/search/loading.peer_models.py: advisory peer-model consultation.metasploit.py: Metasploit module execution and bridge/console helpers.credentials.py: encrypted credential store plus credential-use helpers.ad.py: Active Directory enumeration and attack helpers.payloads.py: payload generation helpers.cracking.py: local hash cracking with hashcat/john and auto hash-type identification.recon.py: OS/service detection and recon pipeline tools.domain.py: domain targeting — resolve_domain, enumerate_subdomains, dns_recon, vhost_enum, domain_whois.attack_modules.py: attack planning, exploit crafting/mutation, web probes, campaign, and module execution tools.sessions.py: persistent sessions, background jobs, listeners, and process helpers.
Relevant tests:
tests/test_mcp_workspace.pytests/test_mcp_tool_registration.pytests/test_command_analyzer.pytests/test_audit_redaction.pytests/test_credential_store.pytests/test_retry_logic.py
Add an Attack Module
Attack modules are reusable service/CVE/workflow modules selected by context.
Edit:
tools/attack_modules/modules/: subclassAttackModulein the relevant category module.tools/attack_modules/modules/: implementapplicability(ctx: ModuleContext) -> intif the base scoring is not enough.tools/attack_modules/modules/: implementrun(ctx: ModuleContext) -> dict[str, Any].tools/attack_modules/registry.py: register the class in_MODULE_CLASSES.tests/test_attack_modules.py: cover registry, applicability, run output, and edge cases.
Key types:
ModuleContext: target IP, service, port, CVEs, banners, credentials, and metadata.AttackModule: base class with module metadata and execution contract.list_modules,find_modules,get_module: registry helpers used by higher-level flows.
Conventions:
- Return data, commands, workflow instructions, or generated script text as structured dictionaries.
- Keep module names stable because tests and orchestrators can reference them.
- Do not embed credentials in plain output.
For out-of-tree attack modules, register the class through registry.register_attack_module(cls) instead of adding to _MODULE_CLASSES; see plugin-development.md.
Add Runtime Skill Guidance
Use this path for advisory methodology that should guide the model without adding new execution capability.
Edit:
skills/<skill-name>/SKILL.md: add YAML front matter and Markdown guidance.config.yaml: add the skill toskills.default_enabledor rely on tags for contextual selection.tests/test_skill_registry.pyortests/test_skill_selector.py: cover parsing and selection behavior when the skill changes core routing.
Conventions:
- Skills are prompt context only. They must not bypass scope, permission, approval, command safety, workspace containment, or audit logging.
- Prefer accurate tags such as
nmap,api,active-directory,tls,reconnaissance, orvulnerability-scanning. - Put higher-risk or niche skills under
skills/maybe/; they are ignored unlessskills.maybe_enabledis true. - Keep guidance compact. By default selected skills are exposed as short hints
and full text is loaded later through
load_runtime_skill; onlyskills.inject_startup_context: trueusesskills.max_total_charsto inject selected skill bodies into the startup prompt.
Add Recon Behavior
Use tools/recon_pipeline.py for host/service discovery and enrichment.
Important classes:
ServiceInfo: parsed service/port details.HostReconResult: per-host recon output.ReconConfig: scanner behavior and timeouts.PrimaryReconScanner: initial host/port/service scanning.SecondaryEnumerator: deeper service-specific enumeration.ReconPipeline: high-level orchestration.
Also check:
main.py::run_recon_assessmenttools/recon_assessment_cli.py: wrapsrun_recon_assessment(referenced frommain.py).tools/goal_suggester.pytests/test_recon_pipeline.pytests/test_recon_first_session.py
Keep recon changes deterministic where possible and make external tool failures explicit.
Add a Goal or Goal Suggestion
Preset goals and goal compatibility live in tools/goal_engine.py.
Recon-driven recommendations live in tools/goal_suggester.py.
Edit:
tools/goal_engine.py: add or modifyAttackGoalpresets and compatibility checks.tools/goal_suggester.py: update assessment heuristics and suggested-goal output.main.py: update argument handling only if a new CLI flag or flow is needed.
Tests:
tests/test_goal_engine.pytests/test_recon_first_session.py
Add Model Routing Behavior
Edit:
tools/model_router.py: model metadata, client selection, and routing strategy.config.yaml: operator-facing model aliases and info.tools/config_manager.py: defaults and validation.tools/mcp_tools/peer_models.py: peer-model advisory tooling whenmulti_modelis involved.main.py: CLI flag behavior only if required.
Tests:
tests/test_config_manager.pytests/test_ultrathink.py- Any focused tests that exercise model selection in
main.py.
Keep config.yaml model aliases and models.info synchronized because context-window metadata is used by adaptive context handling in tools/exploit_agent/. Peer consultation should stay opt-in via multi_model.enabled or a per-run CLI override because each consultation spends extra tokens.
Add a Model Provider (chat, embeddings, or research)
The engine has three provider surfaces, each coupled to Ollama differently. For the full architecture, current wiring, and concrete edit-point recipes, see providers.md. Summary:
- Chat/generate: the single factory is
_build_model_client()intools/model_router.py:290-377. Every consumer already receives aModelClientand calls.chat(), so adding a provider is a branch in the factory plus a config key — no consumer edits. Watch tool-schema conversion (mcp_tools_to_ollamainmcp_session.py:911-935) andtools/api/session_titler.py(constructs its own client). - Embeddings:
SemanticMemoryManager._generate_embeddingintools/semantic_memory.py:48-106is a rawurllibPOST to/api/embeddings. Abstract it behind anEmbeddingProviderbase (model onResearchProvider); consumers already call.embed(text). Update both Flow A and Flow B construction sites. - Research: already multi-provider. Subclass
ResearchProviderintools/web_researcher.py:235-307and add a config block underresearch:.
Add Config Keys
Edit:
config.yaml: checked-in operator defaults.tools/config_manager.py::CONFIG_SCHEMA: defaults used when config is missing or incomplete.tools/config_manager.py::ConfigValidator.validate: type/range validation.tools/config_cli.py: handlesload_configand the startup API-key bootstrap (referenced frommain.py).tools/interactive_menu.py: only if operators should edit the setting interactively.tests/test_config_manager.py: defaulting and validation coverage.
Conventions:
- Keep first-run defaults conservative.
- Treat unknown keys as warnings unless they make runtime behavior ambiguous.
- Document new environment variables in getting-started.md or this guide.
Add Persistent Data
Edit:
db.py: updateDDL,_SCHEMA_VERSION, and_run_migration.- Add migration helper methods for non-trivial schema changes.
- Add high-level database methods if multiple modules need the data.
- Update the relevant service module to use the database API rather than ad hoc SQL.
Tests:
- Existing module tests for the feature area.
- A migration/regression test if the schema change affects existing databases.
Conventions:
- Store JSON fields as text and deserialize at the boundary.
- Use prefix-style IDs created through
_new_id. - Keep writes inside
DatabaseManager.connection(write=True).
Add Task or Agent-Loop Behavior
Edit based on the layer you are changing:
planner.py: what work should exist.task_queue.py: task lifecycle, phase normalization, priority, deduplication.risk_controller.py: approval and budget behavior.executor.py: execution plans and results.tool_router.py: actual tool dispatch and scope-aware execution.observer.py: output parsing into facts, findings, memories, and follow-up tasks.agent_loop.py: high-level orchestration.
Tests:
tests/test_agent_loop.pytests/test_task_queue.pytests/test_risk_controller.pytests/test_scope_gate.py
Add Swarm Behavior
Edit:
tools/swarm/base.py: shared agent result/status contract.tools/swarm/orchestrator.py: routing, parallel execution, critic/reflection flow, persisted state.tools/swarm/agents/*.py: specialist behavior.
Tests:
tests/test_swarm.pytests/test_swarm_integration.pytests/test_swarm_observability.py
Conventions:
- Keep the critic path available for high-risk task types.
- Persist blackboard and battle-log changes where the orchestrator already writes state.
- Return structured
AgentResultvalues rather than free-form strings only.
Add Evidence, Finding, or Report Behavior
Edit:
evidence.py: raw artifacts, metadata, hashes, and evidence lookup.finding_verifier.py: candidate lifecycle, validation scoring, rejection, report readiness.report_generator.py: Markdown report output.tools/enhanced_reporting.py: exploit-session timelines, CVSS helpers, chains, and technical finding reports.
Tests:
tests/test_evidence.pytests/test_finding_verifier.pytests/test_report_generator.py
Conventions:
- Keep report output evidence-linked and reproducible.
- Avoid overstating severity when validation is incomplete.
- Store raw data separately from summaries.
Add External Tool Integration
Existing integrations include nmap, Ollama, NVD, searchsploit, Metasploit, tmux/background jobs, and package managers.
Use these modules:
tools/reliability.py: retries, timeouts, circuit breaker, fallback, error tracking.tools/doctor.py: local environment checks.tools/self_test.py: safe localhost smoke test.tools/validation_utils.py: target validation and command preflight checks.tools/command_analyzer.py: destructive command and egress analysis.tools/logging_setup.py: shared logging behavior.
Add tests for missing-tool behavior and timeout behavior. Do not assume the external binary exists on every developer machine.
Add OPSEC / Detection-Coverage Behavior
Edit:
tools/opsec.py:OpsecProfileandOpsecManager(target-aware viaresolve_for_target(ip), OFF for private/local targets, ON for public-routable targets).tools/detection_coverage.py: detection-coverage analysis and posture helpers.tools/mcp_tools/terminal.py::_opsec_advisory_block: appends a liveOPSEC_ADVISORY:block (noise score, quieter rewrite, pacing) to everyrun_exploit_terminalresult.tools/exploit_agent/prompt.py::build_opsec_briefing: target-aware posture section injected into the agent system prompt.
OPSEC is advisory-only on the attack path: it never gates tool calls, and is_quiet_blocked / noise_budget stay dormant. The command always executes.
Add a Plugin (out-of-tree)
Plugins are out-of-tree extensions that ship as self-contained directories and are discovered without modifying the core tree. See plugin-development.md for the full guide.
Key facts:
- Plugins live under
plugins/<name>/with aplugin.yamlmanifest and aplugin.pyentry point;plugins/example_recon_report/is a reference plugin. - Plugins are OFF by default; enable them via
config.plugins.enabled(per-plugin or as a list). - Any MCP tool a plugin exposes must stack
@ctx.require_allowlist()(for target-touching tools) or@ctx.audit_tool()(for local-only tools), reusing the same gates as in-tree tools.
Debugging Checklist
- Run the focused pytest file for the touched module.
- Run
python main.py --doctorfor environment/config issues. - Run
python main.py --self-testfor safe integration smoke testing. - Inspect
research_workspace/logs/app.logwhen logging is configured. - Inspect
exploit_workspace/exploit_audit.jsonlfor exploit MCP calls. - Inspect generated
reports/<timestamp>/directories for session output. - For database state, use the SQLite file under
research_workspace/research.dbor the test workspace being exercised.