Saltar al contenido principal

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. A pbo > 0.5 candidate is unrepresentable (the structural overfitting gate).
  • ProductionStrategyArtifact — QD output, carries research_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 — see alphaswarm/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:

  1. kill-switch engaged -> DENY
  2. FAILED validation -> DENY (also unrepresentable at the contract layer)
  3. FAILED risk -> DENY
  4. validator not independent of producer (SR 11-7) -> DENY
  5. missing research-to-live parity hash (strategy/DRL) -> DENY
  6. 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_of set once; Iceberg read_arrow_at for every historical read; alphaswarm.features.point_in_time proves 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.