Skip to content
BreachPilot

Models

tools/run_service/models.py:1 — transport-neutral dataclasses + enums shared between CLI (main.async_main via AssessmentService.prepare/execute) and the API daemon (RunManager + route handlers). The API returns many of these shapes serialized (also via _request_to_dict/_preview_to_dict/_result_to_dict in tools/api/run_manager.py:569). Events are tools/run_service/models.py:230; decisions are tools/run_service/models.py:210.

Enums

EnumValuesNotes
RunState (tools/run_service/models.py:26)draft, awaiting_confirmation, queued, running, awaiting_input, cancelling, completed, failed, cancelled, interruptedterminal: `completed
RunKind (tools/run_service/models.py:41)agentmanual removed — agent + MCP gateway only (drive manual calls via POST /runs/{id}/tools/*/calls)
DecisionKind (tools/run_service/models.py:52)start_confirm, goal_select, tool_approval, campaign_next_stepcampaign_next_step is the mid-run checkpoint (service.py:964)
DecisionStatus (tools/run_service/models.py:59)pending, answered, denied, expiredexpired = run cancelled/failed before answer (decision_broker.cancel_all)

Helpers: is_agent_attack_mode(mode: str) (tools/run_service/models.py:73) → mode in {attack, fast}; is_fast_mode (tools/run_service/models.py:84) → mode=="fast".

RunRequest

tools/run_service/models.py:88 — what operator wants to run. Built from POST /api/v1/runs RunCreateRequest (tools/api/routes/runs.py:142).

FieldTypeDefaultSetter
targetstrrequiredPOST /runs.target
mode`RunMode("recon""attack""fast")`
goal_namestr""goal
custom_goalstr""
recon_first`boolNone`null
model_aliasstr""POST model else config models.default_alias / chatgpt.default_model
config_path / reports_dirPathconfig.yaml / reportsoverwritten to manager's values (tools/api/run_manager.py:208)
swarm / parallel_swarm / critic / reflection / adaptive_exploits / long_sessionboolfalsepower-ups
multi_model_consult`boolNone`none
observer_modestrhybrid
ultrathink / debug / plain / json_output / yesboolfalseyes skips start_confirm
skills_mode`strNone`none
skills_include / skills_excludestr[][]
skills_no_reselectboolfalse
resume_sourcestr""resume / set by resume route
kindRunKindagent
interactiveboolfalseAPI-only target-via-menu flag

_request_to_dict (tools/api/run_manager.py:569) serializes to request_json.

RunPreview

tools/run_service/models.py:132 — returned from AssessmentService.prepare before any side effects (tools/run_service/service.py:498). Serialized by _preview_to_dict (tools/api/run_manager.py:598).

FieldTypeNotes
run_idstrstrftime %Y%m%d_%H%M%S_%f UTC (service.py:618)
reports_dir / config_pathPath
target_ipstrnormalized (_resolve_target, validation validate_target)
original_targetstroperator input
resolved_ip / resolved_domain`strNone`
mode / goal_name / goal_descriptionstrGoalEngine preset/ custom
model_alias / model_labelstrresolved via models.registry/info + format_model_choice
transport_summarystrf"http on port {http_port}"
permissionstr`read_only
attack_modeboolis_agent_attack_mode(mode)
swarm / parallel_swarm / multi_modelbooleffective flags
destructiveboolpermission==full_access && attack_mode
required_confirmation_textstr"" non-destructive else ALLOW <ip> (service.py:641)
budgetsdict{commands, rounds, duration_minutes} from ExploitSettings
skill_activations / skill_errorslist[dict] / list[str]runtime skill selection
resumed_fromstr

Shown to operator at the start_confirm gate. Frozen config_snapshot & allowlist at create_run so PATCH between confirm and start cannot retroactively change it.

RunResult

tools/run_service/models.py:170 — sanitized serializable outcome (keys in _result_to_dict tools/api/run_manager.py:625).

FieldTypeNotes
run_id / target_ip / mode / goal_name / goal_descriptionstr
total_actionsintexecuted actions
workspace / audit_path / reports_dir / summary_path / run_json_pathstrpaths under reports/<run_id>/
recordslist[dict]audit records
messageslist[dict]conversation
errorstrempty on success
swarm_result`dictNone`
active_skillslist[dict]
outcome_summarystrverified-compromise + timeline summary
telemetry`dictNone`
safety_review`dictNone`
cancelledboolmid-run cancel at checkpoint (service.py:1090)
objective_transitionslist[dict]{from, to, at_checkpoint} (service.py:1060)

Persists in result_json.

Decision

tools/run_service/models.py:210:

FieldTypeNotes
idstrassigned by broker dec-<12hex> (decision_broker.py:34)
run_idstr
kindDecisionKind
prompt_textstr
required_textstrexact match needed for start_confirm/tool_approval
optionslist[dict]goal_select presets, campaign_next_step actions (+ nested goals)
statusDecisionStatus(pending default)
answerstr
created_at / answered_atstrISO UTC

HTTP mapping DecisionOut is tools/api/routes/decisions.py:41 (adds options field mapping from options_json).

Event

tools/run_service/models.py:230:

FieldTypeNotes
sequenceintmonotonic per broker (event_broker.py:44)
timestampstrdatetime.now(timezone.utc).isoformat()
run_idstr
typestrEVENT_* constants (models.py:248) + runtime heartbeat|title|approval
payloaddictsanitize'd

Constants (tools/run_service/models.py:248): EVENT_STATE, EVENT_BOOT, EVENT_PROGRESS, EVENT_PHASE, EVENT_GOAL_SUGGESTIONS, EVENT_RECON, EVENT_ASSISTANT, EVENT_TOOL_REQUEST, EVENT_TOOL_START, EVENT_TOOL_RESULT, EVENT_APPROVAL, EVENT_SWARM, EVENT_ARTIFACT, EVENT_COMPLETION, EVENT_ERROR, plus Fast: EVENT_FAST_RECON_STARTED etc., EVENT_AI_TAKEOVER_STARTED.

Wire shape: HTTP GET /events?after and WS send_json(event) both use this shape. SSE wraps data: {json}\n\n.

Pydantic route models

ModelFileFields
RunCreateRequesttools/api/routes/runs.py:142target, mode, goal, custom_goal, recon_first, model, swarm, parallel_swarm, critic, reflection, adaptive_exploits, long_session, multi_model_consult, observer_mode, ultrathink, skills, skills_include, skills_exclude, resume, kind, yes
TitleRequesttools/api/routes/runs.py:170title?:str, regen:bool
ToolCallRequesttools/api/routes/runs.py:177arguments:dict
DecisionAnswer/Outtools/api/routes/decisions.py:37answer:str / full row
UserRequest/Response, AnnotationRequest/Responsetools/api/routes/users.py:61user/ann shapes when multi_operator
EventOuttools/api/routes/events.py:56typed event for OpenAPI

Provider protocols

tools/run_service/providers.py:40 DecisionProvider(request)->str, EventSink(emit), ApprovalProvider(approve) (providers.py:193), CancellationToken (providers.py:346). Api* vs Terminal* adapters wire CLI vs daemon; ApiApprovalProvider routes to tool_approval decision with ALLOW <target> required text (providers.py:327).

source: repo docs (build sync)Edit this page on GitHub →