Plugin Protocol

September 21, 2026 · View on GitHub

READ_ONLY_NO_ORDER_NO_CANCEL_NO_TRADE

SmartMoney-Cub is built so that "everything is a plugin" without giving plugins the ability to trade. The harness publishes a stable protocol, a reference plugin, and a curated catalog. It does not bundle AKShare, TradingAgents, Qlib, vectorbt, QuantStats, Backtrader, vn.py, or ZVT.

What automatic integration means here

A plugin that a user installs is found, validated, loaded, and injected automatically. There is no "edit the core to add a data source" step.

StepAutomatic?Notes
DiscoveryYesPython entry points and explicit --plugin-dir paths
ValidationYesManifest schema, safety declaration, API range, license field
Dependency resolutionYesinject; missing hard dependencies become PENDING
ActivationYesGated by profile permissions and health check
ExecutionYesEvery result is wrapped in an Evidence Envelope
InstallationNoUser-initiated; workbench can install into a dedicated venv upon explicit per-item confirmation
DownloadingNoOnly via verified curated catalog whitelist on explicit confirmation; never silent background fetching
Enabling network or a modelNoRequires an explicit profile, credentials confirmation, or flag

Layer model

The design follows the same three-layer separation that DeepSeek Harness uses: definition, provider, consumer.

LayerResponsibilityMay depend on
Service definitionStable request and result types for one capabilityNothing
ProviderOne implementation of a capabilityIts own project only
ConsumerUses a capability by nameThe definition only

Because a consumer never imports a provider, replacing a provider requires no change to the consumer. That is what makes an external project swappable.

from smartmoney_cub_harness.plugins import BaseConsumer, CapabilityName

class ReviewDashboard(BaseConsumer):
    required_services = (CapabilityName.TRADE_IMPORT,)
    optional_services = (CapabilityName.MARKET_CONTEXT,)

    def render(self, request):
        return self.call(CapabilityName.TRADE_IMPORT, request)

Capabilities

CapabilityPurpose
trade_importNormalize broker or 同花顺 fills into a position ledger
market_contextRead-only regime or sentiment context
reviewerProduce review observations
challengerProduce counter-arguments and rule candidates
evaluatorEvaluate a candidate against point-in-time samples
replayReconstruct a frozen decision context
report_rendererRender local artifacts
memoryStore portable text memory
llm_providerOptional external model access
agent_bridgeBridge a local external agent as review evidence

There is deliberately no order, cancel, account, or execution capability. A manifest that declares one is rejected at load time.

Manifest

Every plugin ships a plugin.json. The reference file is examples/toy_plugin/plugin.json. The machine-readable schema is schemas/plugin-manifest.schema.json.

FieldRequiredMeaning
schemaYessmartmoney_cub_plugin_manifest.v1
plugin_idYesStable identifier; duplicates are rejected
name, versionYesIdentity and version recorded in evidence
source_repoYesUpstream project
source_commit / source_tagRecommendedExact provenance
licenseYesUpstream license
kindYesentry-point, local-path, subprocess, or companion
trust_levelYescore, review-only, data-network, untrusted-external
api_rangeYesCompatibility range, for example >=1,<2
capabilitiesYesNon-empty list of capability names
data_time_semanticsYespoint_in_time, historical_export, live_fetch, derived_static
required_services / optional_servicesNoDependency seams
network_requiredNoDefaults to false
credential_requirementsNoNames only; values stay in the user's environment
supported_marketsNoFor example CN-A
safetyYesMust be READ_ONLY_NO_ORDER_NO_CANCEL_NO_TRADE

Lifecycle and Status Vocabulary

AVAILABLE -> [PERMISSIONS_CONFIRMED] -> INSTALLED (in dedicated venv/sources) -> ENABLED/DISABLED -> HEALTH_CHECKED
   -> ACTIVE -> EXECUTED -> EVIDENCE_WRAPPED -> REVIEWED
   -> UNINSTALLED / REVOKED
PENDING  (a required service is missing)
FAILED / ERROR (a health probe, installation, or execution raised)
BLOCKED  (high execution risk or the active profile does not permit permissions)

Market States

The workbench and catalog contract define five explicit market states:

StateMeaning
AVAILABLEThe plugin is cataloged and available for installation, but not yet downloaded or installed.
INSTALLEDThe plugin package has been fetched into the dedicated venv (or cloned into sources/), passes health check, but is currently inactive.
ENABLEDThe plugin is active and available for invocation in workflows.
DISABLEDThe plugin is installed but intentionally disabled by the user or profile.
ERRORA health probe, installation step, or execution failed, or the entry is in an invalid state.

Activation registers providers as reversible effects. Deactivation runs those disposers in reverse order, so no consumer keeps a reference to a provider that is no longer loaded. Removing a plugin revokes the entry while keeping its audit trail.

Isolation and permission honesty

Third-party projects default to a report-only subprocess provider. A subprocess plugin receives one JSON request on stdin and returns one JSON object on stdout.

Declared permissions are a statement, not a sandbox attestation. Doctor output and every envelope therefore report enforcement: declarative and verified: false. Place untrusted code in an operating-system or container sandbox before running it.

Evidence Envelope

Every execution returns a wrapped envelope rather than a bare result:

  • plugin id, version, and source reference;
  • input and output SHA-256;
  • decision time and available time;
  • data source and data quality;
  • whether network or a model was used;
  • declared permission state;
  • the normalized result_kind, which separates facts, statistics, model opinions, and user records;
  • champion_mutated: false and core_rules_mutated: false.

An output whose available_at is after decision_time raises instead of being recorded. That single check prevents most look-ahead mistakes.

Command line

smcub plugin list   --plugin-dir examples/toy_plugin
smcub plugin inspect examples/toy_plugin/plugin.json
smcub plugin doctor  --plugin-dir examples/toy_plugin
smcub plugin install ./my-plugin          # registers a local path, never downloads
smcub plugin enable  toy.review-tagger --plugin-dir examples/toy_plugin
smcub plugin run     toy.review-tagger \
  --request request.json \
  --decision-time 2026-09-10T15:00:00+08:00 \
  --available-at  2026-09-10T14:00:00+08:00 \
  --workspace-db state/workspace/review.db --case-id CASE-1
smcub plugin logs    toy.review-tagger
smcub plugin disable toy.review-tagger
smcub plugin remove  toy.review-tagger
smcub plugin catalog

smcub profile show default-offline
smcub profile dump --output profiles.json
smcub profile reload --plugin-dir examples/toy_plugin

Installation Channels and Workbench Wizard

The harness provides two installation avenues:

  1. CLI Local Registration: smcub plugin install <local-dir> registers an existing local directory or manifest path.
  2. Workbench Installation Wizard (Dedicated venv & Whitelist): The review workbench provides an interactive, human-gated installation flow for curated catalog plugins:
    • Catalog Whitelist Enforcement: Only entries present in the curated catalog whitelist (catalog_index()) can be installed. Arbitrary URLs or unauthorized packages are strictly rejected.
    • Absolute Execution Ban on High Risk: Catalog entries marked with execution_risk: "high" (such as vn.py, which contains order placement and account manipulation capabilities) are never installed under any circumstance. The installer immediately refuses them.
    • Explicit Permission Confirmation: Installation cannot proceed without explicit human consent to the READ_ONLY_NO_ORDER_NO_CANCEL_NO_TRADE boundary.
    • Dedicated Virtual Environment (.plugins/venv): PyPI-based plugins are installed into an isolated dedicated virtual environment, avoiding pollution of the core runtime.
    • Dedicated Sources Directory (.plugins/sources): Git-based plugins are cloned into an isolated sources directory with health probes verified.
    • Health Checks & Probes: Immediately following download/install, a non-mutating health check (probe) verifies that the declared module can be imported cleanly. If the probe fails, the installer reports ERROR, rolls back changes, and surfaces the failure.
    • Clean Uninstallation: Uninstallation cleanly removes packages from the dedicated venv or deletes cloned directories while preserving audit logs.

Pass --workspace-db to plugin run to persist the wrapped envelope into the review workspace, optionally linked to a case with --case-id.

Profiles

ProfileNetworkExternal modelContents
default-offlineNoNoOffline core only
a-share-reviewNoNoOffline core plus A-share review helpers
researchNoNoAdds disabled evaluation and replay slots
ai-optionalYesYesAdds disabled LLM and agent bridge slots

Composition is ordered bundles plus user patches. Because entries have stable ids, a patch keeps applying to the same logical slot even when providers change.

Curated catalog

smcub plugin catalog lists external projects with three integration levels:

  • companion — documentation only; nothing is executed.
  • adapter — wraps external output into an Evidence Envelope, preferably as a report-only subprocess.
  • runtime-plugin — a manifest, tests, permission declarations, safety docs, and a health check exist.

Projects with high execution risk, such as vn.py, stay at companion level and are listed with no capabilities. A catalog entry is never a bundled dependency.

Schemas

SchemaPurpose
plugin-manifest.schema.jsonPlugin declaration and the capability names it may not use
plugin-evidence-envelope.schema.jsonWire shape of wrapped plugin output

Writing a plugin

  1. Copy examples/toy_plugin as a starting point.
  2. Describe the plugin in plugin.json. Keep network_required false unless the plugin genuinely must reach the network.
  3. Implement the provider. For a subprocess plugin, read JSON from stdin and write JSON to stdout.
  4. Validate with smcub plugin inspect plugin.json.
  5. Run it with smcub plugin run and confirm the envelope has no error and reports the expected result_kind.
  6. Add tests covering success, a missing dependency, a future-data refusal, and a failure that must stay visible.

What plugins must not do

  • Place, cancel, or simulate orders; modify accounts; automate a broker.
  • Present a model opinion as a fact, a statistic, or a signal.
  • Write champion rules. A plugin may only propose a candidate.
  • Read credentials, cookies, or account identifiers, or write them into artifacts.
  • Require network access or an external model without an explicit user opt-in.
  • Claim sandbox verification that the harness has not performed.