Agent & Headless Ready
    API · MCP · SDK · CLI

    Built for Agents

    Skip the browser — call our REST API directly, connect Claude or GPT via our MCP server, use our Python or TypeScript SDK, or script workflows from the CLI. We are the server; you are the client.

    Need proof of accuracy first? View the full benchmark report — side-by-side cost and latency results across all four providers.

    Try it live

    Run real API calls right here — no account or API key required

    GET
    /api/health
    Health check

    Verify the API is up. Returns status, version, and uptime.

    GET
    /api/description
    API description

    Discover every capability, tool, and endpoint this platform exposes — no key needed.

    GET
    /api/chaos/scenarios
    Chaos scenarios

    List all built-in failure scenarios you can inject: AZ outage, DB crash, network partition, and more.

    POST
    /api/simulations
    Create & step a simulation

    Create a real AWS simulation with a t3.medium compute resource, then immediately run a step to see live metrics — cpu, latency, errorRate, and cost.

    POST
    /api/demo/rl/start
    RL training loop

    Bootstrap a Gym-compatible RL environment, run the first episode step, and see the reward signal. Hit 'Step again' to advance the episode — watch obs, reward, done, and sim_time_human update with each action.

    POST
    /api/demo/rl/db/start
    RL training loop — Aurora Serverless warm-up

    Same RL loop, but the scenario adds an Aurora Serverless v2 database. During the first few steps the DB is still warming up: its own cpu_util reads 0, ACU sits at the 0.5 floor, and it bills at the ~$0.06/hr floor — yet its small floor-sized pool saturates, so connection_pressure turns negative and the 'DB pool saturated' cue lights up. Hit 'Step again' and watch the per-DB metrics.serverless[] breakdown ramp its ACU and cost up while the pool pressure eases.

    Headless API Access

    Call our REST API directly — no browser or UI required on your end

    Your base URL

    Every API endpoint is available at this URL. Authenticate with your API key and start making requests — no setup on your end beyond getting a key.

    Bash
    https://www.cloudworldmodel.ai
    Authentication

    Pass your API key as a Bearer token in every request. Here's a minimal working example — create a simulation then advance it one step:

    Bash
    # All authenticated requests use a Bearer token in the Authorization header
    curl -X POST https://www.cloudworldmodel.ai/api/simulations \
    -H "Authorization: Bearer your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
    "name": "prod-replica",
    "resources": [
    { "id": "web", "type": "compute", "name": "Web Server", "provider": "aws" }
    ]
    }'
    # Then step the simulation (replace <id> with the id from the response above)
    curl -X POST https://www.cloudworldmodel.ai/api/simulations/<id>/step \
    -H "Authorization: Bearer your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{ "trafficRPS": 1500 }'
    Health & OpenAPI endpoints
    Bash
    # Health check — no auth required
    curl https://www.cloudworldmodel.ai/api/health
    # → { "status": "ok", "version": "1.0.0", "uptime": 42.3 }
    # Full OpenAPI spec as JSON
    curl https://www.cloudworldmodel.ai/api-docs/openapi.json
    # Interactive Swagger UI
    open https://www.cloudworldmodel.ai/api-docs
    RL tick rate — warm-up vs. training
    tick_seconds

    Every /rl/environments/:id/step call accepts an optional tick_seconds field (1–3600) that overrides the episode-level clock for that single step. Use this to run a fast warm-up phase before your agent starts making real decisions:

    • 300 sWarm-up. Each step jumps 5 simulated minutes. Twenty steps cover ~1.7 hours of simulated time in seconds of wall time — skipping past startup noise before the agent takes over.
    • 60 sTraining. One-minute ticks give the agent precise per-minute visibility — matching the granularity of real autoscaling cooldown windows (AWS default: 300 s).

    The actual value used is reflected back in observation.tick_seconds so your agent always knows how much simulated time each step represents.

    Python
    import requests
    BASE_URL = "https://your-domain.com/api"
    API_KEY = "your_api_key_here"
    ENV_ID = "env-aws-001"
    session = requests.Session()
    session.headers.update({"Authorization": f"Bearer {API_KEY}"})
    def step(action: dict, tick_seconds: int) -> dict:
    r = session.post(
    f"{BASE_URL}/rl/environments/{ENV_ID}/step",
    json={"action": action, "tick_seconds": tick_seconds},
    )
    r.raise_for_status()
    return r.json()
    NO_OP = {"type": "no_op", "parameters": {}}
    # Phase 1 — Warm-up: large ticks fast-forward through startup noise.
    # 20 steps × 300 s = 6,000 s ≈ 1.7 h of simulated time.
    for i in range(20):
    data = step(NO_OP, tick_seconds=300)
    print(f"warmup {i+1:2d} sim={data['sim_time_human']} cpu={data['obs']['cpu_util']:.1%}")
    if data["done"]:
    break
    # Phase 2 — Training: 1-minute ticks for precise autoscaling control.
    # The agent now reacts on a per-minute basis, matching real cooldown windows.
    done = False
    while not done:
    cpu = data["obs"]["cpu_util"]
    if cpu > 0.75:
    action = {"type": "scale_out", "parameters": {"instanceCount": 1}}
    elif cpu < 0.30 and data["obs"]["instances"] > 1:
    action = {"type": "scale_in", "parameters": {"instanceCount": 1}}
    else:
    action = NO_OP
    data = step(action, tick_seconds=60)
    done = data["done"]
    print(
    f"t={data['t']:4d} reward={data['reward']:+.3f} "
    f"cpu={data['obs']['cpu_util']:.1%} "
    f"p95={data['metrics']['latency_p95']} ms "
    f"cost=${data['metrics']['cost_usd_hr']:.2f}/hr"
    )

    See the full list of available observation fields, action types, and provider-specific environment options in the RL Environments reference.

    Aurora Serverless v2 episode-loop quickstart
    RL Quickstart
    aurora-serverless · Python

    Aurora Serverless v2 (aurora-serverless) scales ACUs continuously between minCapacity and maxCapacity, so cost tracks actual load rather than peak provisioned size. The simulation engine models a 2–4 step ACU ramp delay after add_resource — during those steps cpu_util reads 0 and cost_usd_hr reflects only the minCapacity floor (~$0.06/hr at 0.5 ACUs). Those top-level signals hold in this single-DB quickstart; in multi-resource sims the sim-wide aggregates mask one DB's warming window and ACU floor, so read the per-DB metrics.serverless[i] array instead. The full episode loop — including ramp-up handling, reward shaping, and idle scale-back — is covered in the Simulation Walkthrough.

    Pay-per-request

    x402 · USDC on Base

    Call metered endpoints without an account — pay per call in USDC, no API key required

    Metered endpoints support the x402 pay-per-HTTP-request protocol. When no API key is present the server returns 402 Payment Required with the payment details in the response body. Your client pays the exact amount in USDC on Base mainnet, then retries with the signed receipt — the call goes through as normal. No account, no signup, no monthly commitment.

    Payments are verified by the Coinbase x402 facilitator. You need a funded EVM wallet on Base with USDC to use this access method.

    Browse and call endpoints directly at x402scan — the discovery index for x402-enabled APIs.

    4-step flow
    1. 1

      Discover configuration

      Fetch GET /api/billing/x402/config to read the live wallet address, USDC amounts per call type, and facilitator URL.

    2. 2

      Call the endpoint (no key needed)

      Send your request without an API key. The server returns 402 Payment Required with payment details in the body.

    3. 3

      Pay and retry

      An x402-aware client signs a USDC transfer on Base, gets a receipt from the Coinbase facilitator, and retries with the X-Payment header attached.

    4. 4

      Check your balance

      Use GET /api/billing/x402/balance?address=0x… to see your remaining credits and GET /api/billing/x402/transactions?address=0x… for a full history.

    Bash
    # Step 1 — discover the live config (no auth required)
    curl https://www.cloudworldmodel.ai/api/billing/x402/config
    # → { "enabled": true, "network": "base", "asset": "0x833…913",
    # "payTo": "<wallet>", "facilitatorUrl": "https://x402.org/facilitator",
    # "creditsPerUsdc": 1000, "prices": { "simulation_step_hybrid": 1, ... } }
    # Step 3 — once you have a signed receipt from the facilitator,
    # attach it as the X-Payment header and retry the request.
    # (x402-aware clients handle this automatically — see snippets below.)
    curl -X POST https://www.cloudworldmodel.ai/api/simulations/<id>/step-hybrid \
    -H "Content-Type: application/json" \
    -H "X-Payment: <base64-encoded-receipt-from-facilitator>" \
    -d '{"trafficRPS":1000}'
    # → 200 OK with normal response body (payment verified, credits deducted)
    # Step 4 — check remaining credits for a wallet address
    curl "https://www.cloudworldmodel.ai/api/billing/x402/balance?address=0xYourWallet"
    # → { "address": "0xyourwallet", "credits": 847 }
    # Full transaction history (most recent first)
    curl "https://www.cloudworldmodel.ai/api/billing/x402/transactions?address=0xYourWallet&limit=10"
    # → { "address": "...", "transactions": [{ "delta": -1, "type": "rl_step", ... }, ...] }
    Price table
    EndpointCall typePrice (USDC)
    POST /api/simulations/:id/step-hybridsimulation_step_hybrid$0.0010
    POST /api/rl/environments/:id/steprl_step$0.0010
    POST /api/simulations/:id/explainai_explain$0.0010
    POST /api/simulations/:id/optimizeai_optimize$0.0010
    POST /api/simulations/:id/troubleshootai_troubleshoot$0.0010
    POST /api/simulations/:id/analyze-bottlenecksai_bottleneck$0.0010
    POST /api/chaos/runchaos_run$0.0050
    POST /api/chaos/batchchaos_batch$0.0050
    POST /api/multi-cloud/exploremulticloud_explore$0.0050
    POST /api/analysis/optimizeoptimization_run$0.0050
    POST /api/predictions/validateprediction_validate$0.0050
    POST /api/predictions/optimize-thresholdsprediction_optimize_thresholds$0.0050

    Prices are in USDC on Base mainnet. Fetch the live price table at GET /api/billing/x402/config. Agent tooling (x402scan, OpenAI plugins) can also auto-discover all paid endpoints via the curated spec at GET /.well-known/x402/openapi.json.

    How the 402 → pay → retry loop works
    Bash
    # 1. Call any metered endpoint without an API key.
    curl -X POST https://www.cloudworldmodel.ai/api/chaos/run \
    -H "Content-Type: application/json" \
    -d '{"simulationId":"<id>","scenario":"az_outage"}'
    # → 402 Payment Required
    # Body: { "error": "Payment required", "accepts": [{ "scheme": "exact",
    # "network": "base", "maxAmountRequired": "5000",
    # "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    # "payTo": "<wallet>", ... }] }
    # 2. Use an x402-aware client to pay and retry automatically.
    # The client signs a USDC transfer on Base, submits it to the
    # Coinbase facilitator, and retries with X-Payment in the header.
    # The server verifies the receipt and processes the request normally.
    Python — automatic pay-and-retry
    Python
    from x402.client import wrap_httpx_client
    import httpx, os
    # Wrap any httpx client — payments are handled transparently.
    client = wrap_httpx_client(
    httpx.Client(),
    wallet_key=os.environ["AGENT_WALLET_PRIVATE_KEY"],
    )
    # Call the API exactly as you normally would — no API key header needed.
    # If the server returns 402, the wrapper pays and retries automatically.
    response = client.post(
    "https://www.cloudworldmodel.ai/api/simulations/<id>/step-hybrid",
    json={"trafficRPS": 1000},
    )
    data = response.json()
    print(data["metrics"]["cpuUsage"]) # e.g. 0.71
    print(data["metrics"]["latencyP95"]) # e.g. 138.4
    print(data["metrics"]["costPerHour"]) # e.g. 0.096
    TypeScript — automatic pay-and-retry
    TypeScript
    import { wrapFetchWithPayment } from "x402/client";
    import { privateKeyToAccount } from "viem/accounts";
    const account = privateKeyToAccount(process.env.AGENT_WALLET_PRIVATE_KEY as `0x${string}`);
    // Wrap the global fetch — any 402 response triggers automatic payment + retry.
    const payingFetch = wrapFetchWithPayment(fetch, account);
    const res = await payingFetch(
    "https://www.cloudworldmodel.ai/api/chaos/run",
    {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ simulationId: "<id>", scenario: "az_outage" }),
    }
    );
    const data = await res.json();
    console.log(data); // same response shape as the authenticated API

    Machine-readable x402 discovery signal also available in llms.txt and llms-full.txt. The x402 section in llms-full.txt includes the discovery endpoint, network, asset, and per-call price table in a format optimized for agent consumption. See the landing page overview for a human-readable introduction to x402 on this platform.

    Model Context Protocol — lets Claude, GPT, and other AI assistants call our simulation directly via stdio

    Install the MCP server
    Bash
    npm install -g "github:canvascloudai/cwm-mcp"
    Register in Claude Desktop (claude_desktop_config.json)
    JSON
    {
    "mcpServers": {
    "cloud-world-model": {
    "command": "npx",
    "args": ["cwm-mcp"],
    "env": {
    "CWM_API_KEY": "your_api_key_here",
    "CWM_BASE_URL": "https://www.cloudworldmodel.ai"
    }
    }
    }
    }
    Available tools
    create_simulationCreate a new virtual cloud environment with resources and connections.
    simulate_stepAdvance the simulation by one tick and return metrics.
    get_simulation_metricsRead the latest CPU, latency, error rate, and cost metrics.
    list_simulationsList all simulations visible to the current API key.
    rl_create_environmentCreate a Gym-compatible RL training environment linked to a simulation.
    rl_stepExecute one RL action (scale_out, scale_in, etc.) and receive observation/reward.
    rl_resetReset an RL environment to start a new episode.
    list_chaos_scenariosList available chaos engineering scenarios (AZ outage, DB crash, etc.).
    chaos_runStart a chaos experiment and return a job ID.
    chaos_job_statusPoll a running chaos job for completion.
    chaos_job_resultsRetrieve the full resilience report once a chaos job is done.
    multicloud_exploreGenerate and score multi-cloud architecture strategies.
    multicloud_job_statusPoll a multi-cloud exploration job.
    multicloud_job_resultsRetrieve ranked strategy results.
    prediction_validateValidate infrastructure against a traffic forecast.
    prediction_job_statusPoll a running prediction/validation job.
    prediction_job_resultsRetrieve full validation results including bottlenecks and recommendations.
    optimization_runStart an autoscaling threshold optimization job.
    optimization_job_statusPoll a running optimization job.
    optimization_job_resultsRetrieve optimized threshold recommendations once the job is done.

    Monitor active RL environments — episodes, rewards, and status — in the RL Environment Status viewer.

    Official Python client — zero dependencies, uses stdlib urllib

    Install
    Bash
    pip install "git+https://github.com/canvascloudai/cwm-sdk.git"
    Create simulation → simulate step → read metrics
    Python
    from cwm import CloudWorldModel
    client = CloudWorldModel(
    base_url="https://www.cloudworldmodel.ai",
    api_key="your_api_key_here",
    )
    # 1. Create a simulation
    sim = client.create_simulation({
    "name": "prod-replica",
    "resources": [
    {
    "id": "web",
    "type": "compute",
    "name": "Web Server",
    "provider": "aws",
    "characteristics": {"size": "t3.medium"},
    }
    ],
    })
    # 2. Run a simulation step
    result = client.simulate_step(sim["id"], traffic=1500)
    m = result["metrics"]
    print(m["cpuUsage"]) # e.g. 0.72
    print(m["latencyP95"]) # e.g. 143.2
    print(m["costPerHour"]) # e.g. 0.0464
    Aurora Serverless RL episode loop
    aurora-serverless

    Full episode loop using the SDK's higher-level interface — mirrors the Aurora Serverless quickstart without raw HTTP calls.

    Python
    from cwm import CloudWorldModel
    client = CloudWorldModel(
    base_url="https://www.cloudworldmodel.ai/api",
    api_key="your_api_key_here",
    )
    # 1. Create an RL environment linked to a simulation that already contains
    # at least one AWS database resource (the engine clones it for the episode).
    env_result = client.create_rl_environment(
    simulation_id="<sim-id>",
    episode_config={"maxSteps": 40},
    )
    env_id = env_result["environment"]["id"]
    # 2. add_resource action — adds an Aurora Serverless v2 database to the sim.
    # The engine models a 2-4 step ACU scale-out delay for aurora-serverless targets.
    step1 = client.rl_step(env_id, action={
    "type": "add_resource",
    "parameters": {"resourceType": "database", "provider": "aws"},
    })
    # Response keys: observation, reward {total, components, metrics}, done, info
    obs = step1["observation"] # {cpu_util, rps, instances, traffic, currentTime}
    reward = step1["reward"] # {total, components: {performance, cost, stability, sla, connection_pressure?}, metrics}
    # 3. Ramp window (steps 1-4): ACU warming up — cpu_util == 0, cost at minCapacity floor.
    # Only count cost + stability reward components to avoid false latency penalties.
    result = step1
    for _ in range(4):
    result = client.rl_step(env_id, action={
    "type": "adjust_threshold",
    "parameters": {"cpuThreshold": 70},
    })
    obs = result["observation"]
    rc = result["reward"]["components"]
    adj_reward = rc["cost"] + rc["stability"]
    print(f"Ramp cpu_util={obs['cpu_util']:.3f} adj_reward={adj_reward:.3f}")
    # 4. Steady-state training loop — all reward components now meaningful. With a database
    # resource present this is five (performance, cost, stability, sla, connection_pressure).
    done = result["done"]
    while not done:
    result = client.rl_step(env_id, action={
    "type": "adjust_threshold",
    "parameters": {"cpuThreshold": 70},
    })
    done = result["done"]
    obs = result["observation"]
    rw = result["reward"]
    print(f"Train cpu_util={obs['cpu_util']:.3f} "
    f"cost_usd_hr={rw['metrics']['costPerHour']:.4f} "
    f"reward={rw['total']:.3f}")
    # 5. Reset for the next episode.
    client.rl_reset(env_id)
    Size a Kubernetes cluster
    kubernetes

    Provision a managed node pool and bound its autoscaling with nodeCount / minNodes / maxNodes. /step autoscales nodeCount between min and max.

    Python
    from cwm import CloudWorldModel
    client = CloudWorldModel(
    base_url="https://www.cloudworldmodel.ai/api",
    api_key="your_api_key_here",
    )
    # Create a simulation with a Kubernetes node pool and bound its autoscaling.
    sim = client.create_simulation({
    "name": "k8s-cluster",
    "resources": [
    {
    "id": "api-pool",
    "type": "kubernetes",
    "name": "API Node Pool",
    "provider": "aws", # EKS (also gcp=GKE, azure=AKS, oci=OKE, digitalocean=DOKS)
    "characteristics": {
    "nodeCount": 3, # worker nodes to start with
    "minNodes": 2, # autoscaler won't scale below this
    "maxNodes": 10, # autoscaler won't scale above this
    "maxThroughput": 6000, # serving capacity (RPS) at nodeCount
    },
    }
    ],
    })
    # /step autoscales nodeCount between minNodes and maxNodes; maxThroughput
    # and hourly cost scale proportionally with the live node count.
    result = client.simulate_step(sim["id"], traffic=4000)
    print(result["metrics"]["cpuUsage"]) # e.g. 0.68
    print(result["metrics"]["costPerHour"]) # scales with current nodeCount

    TypeScript / JS SDK

    canvascloudai/cwm-ts-sdk

    Typed Node.js client with full IDE autocomplete, uses native fetch

    Install
    Bash
    npm install "github:canvascloudai/cwm-ts-sdk"
    Create simulation → simulate step → read metrics
    JavaScript
    import { CwmClient } from "@cwm/sdk";
    const client = new CwmClient({
    baseUrl: "https://www.cloudworldmodel.ai",
    apiKey: "your_api_key_here",
    });
    // 1. Create a simulation
    const sim = await client.createSimulation({
    name: "prod-replica",
    resources: [
    {
    id: "web",
    type: "compute",
    name: "Web Server",
    provider: "aws",
    characteristics: { size: "t3.medium" },
    },
    ],
    });
    // 2. Run a simulation step and read metrics
    const result = await client.simulateStep(sim.id, { traffic: 1500 });
    console.log(result.metrics.cpuUsage); // e.g. 0.72
    console.log(result.metrics.latencyP95); // e.g. 143.2
    console.log(result.metrics.costPerHour); // e.g. 0.0464
    Aurora Serverless RL episode loop
    aurora-serverless

    Full episode loop using the SDK's higher-level interface — mirrors the Aurora Serverless quickstart without raw HTTP calls.

    JavaScript
    import { CwmClient } from "@cwm/sdk";
    const client = new CwmClient({
    baseUrl: "https://www.cloudworldmodel.ai/api",
    apiKey: "your_api_key_here",
    });
    // 1. Create an RL environment linked to a simulation that already contains
    // at least one AWS database resource (the engine clones it for the episode).
    const { environment } = await client.createRlEnvironment("<sim-id>", {
    episodeConfig: { maxSteps: 40 },
    });
    const envId = environment.id;
    // 2. add_resource action — adds an Aurora Serverless v2 database to the sim.
    // The engine models a 2-4 step ACU scale-out delay for aurora-serverless targets.
    let step1 = await client.rlStep(envId, {
    action: { type: "add_resource", parameters: { resourceType: "database", provider: "aws" } },
    tick_seconds: 60,
    });
    // Response keys: t, obs, metrics, reward, reward_components, done
    let { t, obs, metrics } = step1; // t=1 after first action
    // obs: {cpu_util, rps, instances, traffic, currentTime}
    // metrics: {cost_usd_hr, latency_p95, error_rate, uptime, sla_violations}
    // 3. Ramp window (t = 1-4): obs.cpu_util === 0, metrics.cost_usd_hr at minCapacity floor (~$0.06/hr).
    // Only count cost + stability reward components — skip performance and sla during ACU ramp-up.
    const RAMP_STEPS = 4;
    let result = step1;
    for (let i = 0; i < RAMP_STEPS; i++) {
    result = await client.rlStep(envId, {
    action: { type: "adjust_threshold", parameters: { cpuThreshold: 70 } },
    tick_seconds: 60,
    });
    ({ t, obs, metrics } = result);
    const rc = result.reward_components;
    const adjustedReward = rc.cost + rc.stability;
    console.log(`Ramp t=${String(t).padStart(2)} cpu_util=${obs.cpu_util.toFixed(3)} ` +
    `cost_usd_hr=${metrics.cost_usd_hr.toFixed(4)} adj_reward=${adjustedReward.toFixed(3)}`);
    }
    // 4. Steady-state training loop — all reward components are now meaningful. With a database
    // resource present this is five components — performance, cost, stability, sla, and the
    // connection_pressure DB-pool penalty (see the worked connection-pool example below).
    // metrics.cost_usd_hr climbs over 3-6 steps toward the ACU-proportional steady-state rate.
    let done = result.done;
    while (!done) {
    result = await client.rlStep(envId, {
    action: { type: "adjust_threshold", parameters: { cpuThreshold: 70 } },
    tick_seconds: 60,
    });
    ({ t, obs, metrics } = result);
    const reward = result.reward;
    done = result.done;
    console.log(`Train t=${String(t).padStart(2)} cpu_util=${obs.cpu_util.toFixed(3)} ` +
    `latency_p95=${metrics.latency_p95.toFixed(0)}ms ` +
    `cost_usd_hr=${metrics.cost_usd_hr.toFixed(4)} reward=${reward.toFixed(3)}`);
    }
    // 5. Reset for the next episode.
    await client.rlReset(envId);
    Size a Kubernetes cluster
    kubernetes

    Provision a managed node pool and bound its autoscaling with nodeCount / minNodes / maxNodes. /step autoscales nodeCount between min and max.

    JavaScript
    import { CwmClient } from "@cwm/sdk";
    const client = new CwmClient({
    baseUrl: "https://www.cloudworldmodel.ai/api",
    apiKey: "your_api_key_here",
    });
    // Create a simulation with a Kubernetes node pool and bound its autoscaling.
    const sim = await client.createSimulation({
    name: "k8s-cluster",
    resources: [
    {
    id: "api-pool",
    type: "kubernetes",
    name: "API Node Pool",
    provider: "aws", // EKS (also gcp=GKE, azure=AKS, oci=OKE, digitalocean=DOKS)
    characteristics: {
    nodeCount: 3, // worker nodes to start with
    minNodes: 2, // autoscaler won't scale below this
    maxNodes: 10, // autoscaler won't scale above this
    maxThroughput: 6000, // serving capacity (RPS) at nodeCount
    },
    },
    ],
    });
    // /step autoscales nodeCount between minNodes and maxNodes; maxThroughput
    // and hourly cost scale proportionally with the live node count.
    const result = await client.simulateStep(sim.id, { traffic: 4000 });
    console.log(result.metrics.cpuUsage); // e.g. 0.68
    console.log(result.metrics.costPerHour); // scales with current nodeCount

    Zero-dependency Go client — stdlib only, context-aware, Go 1.21+

    Install
    Bash
    go get github.com/canvascloudai/cwm-go
    Create simulation → simulate step → read metrics
    go
    package main
    import (
    "context"
    "fmt"
    "log"
    "github.com/canvascloudai/cwm-go/cwm"
    )
    func main() {
    client := cwm.New("https://www.cloudworldmodel.ai", "your_api_key_here")
    ctx := context.Background()
    // 1. Create a simulation
    sim, err := client.CreateSimulation(ctx, map[string]interface{}{
    "name": "prod-replica",
    "resources": []map[string]interface{}{
    {
    "id": "web", "type": "compute",
    "name": "Web Server", "provider": "aws",
    "characteristics": map[string]interface{}{"size": "t3.medium"},
    },
    },
    })
    if err != nil {
    log.Fatal(err)
    }
    // 2. Simulate a step and read metrics (cwm.Float64(rps) sets traffic; nil keeps current)
    result, err := client.SimulateStep(ctx, sim.ID, cwm.Float64(1500), false)
    if err != nil {
    log.Fatal(err)
    }
    m := result.Metrics
    fmt.Printf("CPU: %.1f%% P95: %.1fms Cost: $%.4f/hr\n",
    m.CPUUsage*100, m.LatencyP95, m.CostPerHour)
    }
    RL training loop
    reinforcement-learning

    Multi-episode training loop using CreateRLEnvironment, RLStep, and RLReset — context-aware throughout.

    go
    package main
    import (
    "context"
    "fmt"
    "log"
    "github.com/canvascloudai/cwm-go/cwm"
    )
    func main() {
    client := cwm.New("https://www.cloudworldmodel.ai", "your_api_key_here")
    ctx := context.Background()
    sim, _ := client.CreateSimulation(ctx, map[string]interface{}{
    "name": "rl-training",
    "resources": []map[string]interface{}{
    {"id": "web", "type": "compute", "name": "Web Server", "provider": "aws"},
    },
    })
    env, err := client.CreateRLEnvironment(ctx, sim.ID, &cwm.RlEpisodeConfig{
    MaxSteps: 100,
    InitialTraffic: 1000,
    })
    if err != nil {
    log.Fatal(err)
    }
    envID := env.Environment.ID
    for episode := 1; episode <= 5; episode++ {
    if episode > 1 {
    client.RLReset(ctx, envID)
    }
    var totalReward float64
    for step := 0; step < 100; step++ {
    res, err := client.RLStep(ctx, envID, cwm.RlAction{Type: "scale_out"})
    if err != nil {
    log.Fatal(err)
    }
    totalReward += res.Reward.Total
    if res.Done {
    break
    }
    }
    fmt.Printf("Episode %d total_reward=%.3f\n", episode, totalReward)
    }
    client.DeleteSimulation(ctx, sim.ID)
    }
    Go — automatic pay-and-retry
    x402

    Wrap net/http with the x402-go transport — any 402 response is settled in USDC on Base and retried automatically. No API key required.

    go
    package main
    import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "os"
    // Install: go get github.com/coinbase/x402-go
    x402 "github.com/coinbase/x402-go/pkg/httpclient"
    )
    func main() {
    // Wrap the stdlib http.Client — any 402 response triggers automatic
    // USDC payment on Base mainnet and transparent retry. No API key needed.
    client, err := x402.New(os.Getenv("AGENT_WALLET_PRIVATE_KEY"),
    x402.WithFacilitator("https://x402.org/facilitator"),
    )
    if err != nil {
    log.Fatal(err)
    }
    body, _ := json.Marshal(map[string]any{"trafficRPS": 1000})
    resp, err := client.Post(
    "https://www.cloudworldmodel.ai/api/simulations/<id>/step-hybrid",
    "application/json",
    bytes.NewReader(body),
    )
    if err != nil {
    log.Fatal(err)
    }
    defer resp.Body.Close()
    var result map[string]any
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
    log.Fatal(err)
    }
    m := result["metrics"].(map[string]any)
    fmt.Printf("CPU: %.1f%% P95: %.1fms Cost: $%.4f/hr\n",
    m["cpuUsage"].(float64)*100,
    m["latencyP95"].(float64),
    m["costPerHour"].(float64),
    )
    }

    Script any workflow from the terminal — no code required

    Install
    Bash
    # Install globally from GitHub
    npm install -g "github:canvascloudai/cwm-cli"
    # Verify
    cwm --help
    cwm --help output
    Bash
    Usage: cwm <command> [options]
    Commands:
    config Manage CLI configuration (set, show)
    simulate Simulation management (create, get, list, step)
    rl RL environment interactions (create, step, reset)
    chaos Chaos engineering (scenarios, run, status, results)
    multicloud Strategy exploration (explore, status, results)
    keys API key management (create, list, revoke)
    Options:
    --base-url <url> CWM server URL (overrides config)
    --api-key <key> API key (overrides config)
    --output <format> Output format: text | json
    -h, --help Display help for a command
    Key workflows
    Bash
    # Point the CLI at our server and set your key (saved to ~/.cwm/config.json)
    cwm config set --base-url https://www.cloudworldmodel.ai
    cwm config set --api-key your_api_key_here
    # Create a simulation from a JSON spec file
    cwm simulate create --file sim-spec.json
    # Run a simulation step (optionally inject traffic)
    cwm simulate step <sim-id> --traffic 1500
    # List all simulations
    cwm simulate list
    # Run a chaos scenario
    cwm chaos run <sim-id> --scenario zone_failure --duration 300
    # Advance an RL environment
    cwm rl step <env-id> scale_up
    # Explore multi-cloud strategies (pass a workload JSON file)
    cwm multicloud explore --file workload.json

    After creating an RL environment with cwm rl, you can inspect live episode progress, cumulative rewards, and environment health in the RL Environment Status viewer.

    Aurora Serverless RL episode loop
    aurora-serverless

    Full episode loop using shell commands — mirrors the Aurora Serverless quickstart without writing any code.

    Bash
    # 0. Save your key once; the CLI reads it automatically from ~/.cwm/config.json.
    cwm config set --api-key your_api_key_here
    # 1. Create an RL environment linked to a simulation that already contains
    # at least one AWS database resource (the engine clones it for the episode).
    ENV_ID=$(cwm rl create <sim-id> --max-steps 40 --output json | jq -r '.environment.id')
    # 2. add_resource action — adds an Aurora Serverless v2 database to the sim.
    # cwm rl step passes no action parameters, so use curl for this parameterized step.
    # The engine models a 2-4 step ACU scale-out delay for aurora-serverless targets.
    curl -s -X POST https://www.cloudworldmodel.ai/api/rl/environments/$ENV_ID/step \
    -H "Authorization: Bearer your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{"action":{"type":"add_resource","parameters":{"resourceType":"database","provider":"aws"}}}' \
    | jq '{obs: .obs, reward: .reward, done: .done}'
    # Response keys: obs {cpu_util, rps, instances, traffic, currentTime},
    # reward (total scalar), reward_components {performance,cost,stability,sla,connection_pressure?},
    # metrics {cost_usd_hr, latency_p95, error_rate}, done
    # 3. Ramp window (steps 1-4): ACU warming up — obs.cpu_util == 0, cost at minCapacity floor.
    # Only cost + stability reward components are meaningful during ACU ramp-up.
    for i in 1 2 3 4; do
    cwm rl step $ENV_ID adjust_threshold --output json \
    | jq '{cpu_util: .obs.cpu_util, adj_reward: (.reward_components.cost + .reward_components.stability)}'
    done
    # 4. Steady-state training loop — all reward components are now meaningful. With a database
    # resource present this is five (performance, cost, stability, sla, connection_pressure).
    # Loop until the episode is done (done == true in the JSON response).
    while true; do
    RESULT=$(cwm rl step $ENV_ID adjust_threshold --output json)
    echo "$RESULT" | jq '{cpu_util: .obs.cpu_util, cost_usd_hr: .metrics.cost_usd_hr, reward: .reward}'
    DONE=$(echo "$RESULT" | jq -r '.done')
    [ "$DONE" = "true" ] && break
    done
    # 5. Reset for the next episode.
    cwm rl reset $ENV_ID

    Verify Simulation Accuracy

    Before you build on the numbers, see how they hold up. The benchmark report runs the engine head-to-head across AWS, GCP, Azure, and OCI — comparing cost accuracy, latency profiles, and throughput. Every result is reproducible and re-validated in CI.

    Open Benchmark Report

    Ready to get started?

    Get your API key in under two minutes — no waitlist, no credit card. If you have a Canvas Cloud AI account, you already have access.