QAP Agent Layer — role agents, the promotion boundary, and the SAF
This is the operator-facing walkthrough of the Quant Agent Platform (QAP) agentic enhancement: a thin "LLM cognitive plane" bolted onto AlphaSwarm's fixed stack, where every crossing into the money plane is gated structurally in code — not by prompt instruction.
It complements agents.md (the spec-driven AgentRuntime),
workflow-studio.md (WorkflowRuntime + adapters), and the
reconciled design in
alphaswarm_internal/plans/raw/alphaswarm_research/qap_role_aligned_agent_layer_plan.md
(relocated out of alphaswarm_research/ into the alphaswarm_internal
plans SSoT).
The two planes
Agents emit typed proposals (Pydantic contracts in
alphaswarm_core.contracts). The only sanctioned crossing toward capital is a
StrategyPromotionRequest, which cannot even be constructed around a FAILED
validation and cannot reach the money plane without a deterministic risk pass +
a human approval.
The typed contracts (alphaswarm_core.contracts)
Shared by the LLM plane (which produces them) and the money plane (which gates on them):
StrategyCandidate— QR output. Apbo > 0.5candidate is unrepresentable (the structural overfitting gate).ProductionStrategyArtifact— QD output, carriesresearch_to_live_parity_hash.AllocationProposal— PM output.ValidationVerdict/RiskDecision/RiskReport— SR 11-7 effective challenge + deterministic risk (SR 26-2 is a separate, newer citation used elsewhere to scope the agentic layer itself out of model-risk review while keeping the quant models the agents produce in scope — seealphaswarm/risk/model_inventory.py).StrategyPromotionRequest— the single money-plane crossing.DataQualityReport/DataQualityEvent/DatasetReady— DQE outputs.LiveOpsAlert/ParamChangeProposal/LimitBreachEvent— desk outputs.
Every contract carries a Lineage envelope (data as_of, transaction time,
producing agent, SOKG node id, Iceberg identifier + snapshot).
The promotion gate (B-1)
alphaswarm.promotion.gate.PromotionGateChain is a chain of pure functions over
a StrategyPromotionRequest + an injected GateContext — no LLM:
- kill-switch engaged -> DENY
- FAILED validation -> DENY (also unrepresentable at the contract layer)
- FAILED risk -> DENY
- validator not independent of producer (SR 11-7) -> DENY
- missing research-to-live parity hash (strategy/DRL) -> DENY
- needs human approval -> REQUIRE_APPROVAL
PromotionService persists the request (strategy_promotion_requests), parks a
REQUIRE_APPROVAL outcome in promotion_approval_queue, and on approval flips
the MLflow alias (champion/challenger/shadow) and writes the decision back
to the SOKG. Approval is reachable only via the step-up-MFA-gated
POST /promotion/requests/{id}/approve route — agents can submit (via
data.promotion.submit) but can never self-approve.
The agent-tool facades (T-1)
Thin DataMCP tools over already-built capability (auto-bridged into the agent tool registry; rule 22):
data.research.overfitting_audit— DSR + PBO (CSCV).data.portfolio.allocation_optimize— HRP / HERC / risk-parity / min-variance.data.execution.tca— effective / realized / vs-VWAP + spread/impact/timing.data.quality.check— Pandera-backed data-quality gate + quarantine.data.risk.stress_scenario— 2008 / 2020 / corr->1 / rate-shock scenarios.data.risk.model_inventory— SR 26-2 inventory + materiality tiering.data.promotion.submit/data.promotion.status— the promotion boundary.data.component.audit/data.component.register— the SAF.
Role agents
Six primary + five secondary institutional role agents (hash-locked AgentSpec
YAMLs in configs/agents/ + CrewAI factories in
alphaswarm_agents/.../roles.py). PM / Desk / Risk agents are money-plane-safe
(propose only). The five secondary agents added by this change:
pm.mandate_benchmark, qr.validation_statistician, qd.infra_latency,
desk.param_tuner, risk.limits_stress.
SAF / Component Registry (S-1)
The structural "audit before build" gate. data.component.audit searches the
component_registry ledger + the in-process registries + the SOKG before any
build; data.component.register records an approved component (citing rejected
reuse candidates) and mirrors it as a (:Component) SOKG node. The
build_saf_graph LangGraph workflow runs discover -> spec -> audit -> human gate
(halt-token) -> emit. CI gate: scripts/ci/check_component_registry.py.
Two-engine parity + interrupt_before (N-1, B-2)
alphaswarm.backtest.two_engine routes one TwoEngineRequest to a discovery
engine (VectorBT PRO) and an event-driven validation engine — NautilusTrader is
now the default validation engine (ENGINE_ROUTING["validation"] = "nautilus"
in two_engine.py; its live adapter has landed at
alphaswarm/trading/execution/nautilus_adapters/) — and mints a
research_to_live_parity_hash only when they reconcile within tolerance — the
hash the promotion gate requires.
alphaswarm.promotion.execution_graph.build_execution_graph adds the optional
B-2 hardening: a risk_gate -> order graph where the order node is unreachable
without a deterministic risk pass AND an explicit human resume
(interrupt_before=["order"] natively, or the dependency-free
InterruptBeforeGraph fallback), alongside the halt-token.
Cross-cutting invariants
- LLM-plane / money-plane separation is structural (typed
PromotionRequest- deterministic gate + human approval). No LLM on the order path.
- Point-in-time correctness:
data_as_ofset once; Icebergread_arrow_atfor every historical read;alphaswarm.features.point_in_timeproves offline retrieval equals the as_of snapshot (no train/serve skew). - Overfitting controls are structural gates (PBO>0.5 rejected; DSR deflation).
- SR 11-7 independent validation: the validator must differ from the producer.