Skip to content

Getting Started

ms-markets 2.x requires Python 3.13, Main Sequence SDK >=9.0.29,<10, and the MetaTables client mainsequence-metatable>=0.1.51,<0.2 (imported as metatables). It cannot run against an SDK 8 or earlier contract and does not provide compatibility aliases or a mixed-version mode. Install a 1.x ms-markets release when maintaining an SDK 8 project.

Install the project in editable mode with development dependencies:

uv sync --extra dev

Or with pip:

python -m pip install -e ".[dev]"

The project-level FastAPI surface is optional. Install it only for public API work:

uv sync --extra public_api

Verify that the import package is available:

import msm
from msm.api.http import ResourceCollection, build_resource_discovery_spec

Provider FastAPI projects should use the installable msm.api.http boundary for shared collection, discovery, preflight, operation, and error behavior.

Install ms-markets agent skills into a host CodeRepository only through the explicit CLI command:

msm copy-msm-skills --path .

This copies the packaged skill bundle into .agents/skills/ms_markets/ and writes .agents/skills/ms_markets/PINNED_FROM.txt with the ms-markets version that supplied the installed skills. Importing msm does not write files, create .agents/, or auto-install skills.

Run this command only from a separate host CodeRepository. The CLI blocks msm copy-msm-skills --path . inside the ms-markets source checkout because the destination would overlap the package's own skill source.

Documentation

Serve the documentation locally:

mkdocs serve

Build the static documentation site:

mkdocs build

Architecture Decisions

Implementation decisions should be recorded under docs/ADR.

First Market Setup

Start with the typed row API for simple workflows. Apply the migrations to your local runtime first:

metatables --local migrations upgrade --provider msm_migrations:migration head

Hosted environments are migrated by the deployment workflow's migration Job, not from a developer session; see Hosted Deployments.

import msm

from msm.api.assets import Asset, AssetCategory, AssetType

msm.start_engine(models=["AssetType", "Asset", "AssetCategory"])

AssetType.upsert(asset_type="crypto", display_name="Crypto")

asset = Asset.upsert(unique_identifier="example-asset-btc", asset_type="crypto")
assets = Asset.filter(asset_type="crypto")

category = AssetCategory.upsert(
    unique_identifier="example-crypto",
    display_name="Example Crypto",
)

This follows the library-wide convention: user code works with Pydantic row objects, while schema code works with SQLAlchemy *Table declarations. Asset.upsert(...) and Asset.filter(...) use the active markets runtime. They do not attach to MetaTables or create schemas on first use.

For application startup that wants a controlled runtime preflight, attach directly:

import msm

runtime = msm.start_engine()
context = runtime.context
asset_table = runtime.table("Asset")

That startup preflight resolves already-registered backend MetaTable and TimeIndexMetaTable resources by each selected model's SQLAlchemy table name. Missing backend tables fail startup and should be fixed through the MetaTables migration upgrade flow.

For development examples that should use an example namespace, set MSM_AUTO_REGISTER_NAMESPACE before importing msm.api, then call msm.start_engine(...) during startup. That namespace also becomes the default namespace for markets TimeIndexTableUpdater identifiers and hash_namespace values created in the same process.

Every markets MetaTable now has a user-facing row model under msm.api.*. Legacy imports such as from msm.models import Asset have been removed; use from msm.api.assets import Asset for row operations and from msm.models import AssetTable for SQLAlchemy schema declarations.

Treat explicit runtime attachment as process startup work: run it once during application initialization after admin migrations are current. Repeated calls with the same arguments return the cached runtime; different arguments are rejected for that process. See MetaTable Registration, Migrations, and Tutorial.

Local Django backend

For the Mac/workstation development stack, set MAINSEQUENCE_ENDPOINT=http://local-backend:8000 in the ignored local .env. Map local-backend to the machine running the Django Compose stack with that stack's maintenance/switch_local_backend.py, after stopping the old stack and starting the selected one. Restart clients after switching.

Use this base URL for the platform API and connection-contract examples. Application APIs, local MetaTables and test fixtures retain their own addresses. The endpoint change does not alter package APIs, deployment configuration or permissions. Credentials stay out of Git.