mg-cli

star 101

Generate YAML configuration files and run CLI commands to onboard organizations into ModelGuide. Use this skill when the user asks to set up an org, create agents, import SOPs, add connectors, prepare onboarding YAML, provision a customer, seed demo data, or anything related to the `mg` CLI tool. Also trigger when the user mentions "mg setup", "mg import", "mg add", "onboard", "provision org", "create YAML for CLI", "prepare config files", or asks how to get a new organization running in ModelGuide.

modelguide By modelguide schedule Updated 4/20/2026

name: mg-cli description: > Generate YAML configuration files and run CLI commands to onboard organizations into ModelGuide. Use this skill when the user asks to set up an org, create agents, import SOPs, add connectors, prepare onboarding YAML, provision a customer, seed demo data, or anything related to the mg CLI tool. Also trigger when the user mentions "mg setup", "mg import", "mg add", "onboard", "provision org", "create YAML for CLI", "prepare config files", or asks how to get a new organization running in ModelGuide.

ModelGuide CLI Onboarding Tool

The mg CLI is a thin orchestration layer over ModelGuide's service layer. It reads YAML files, validates them with Zod, and calls existing @features/* services in dependency order. All business logic lives in the services — the CLI handles parsing, validation, orchestration, and output.

When to Use This Skill

  • User wants to onboard a new organization (customer, demo, test)
  • User wants to prepare YAML config files for the CLI
  • User wants to run individual CLI commands or the full mg setup pipeline
  • User wants to import SOPs, guardrails, evals, sessions, or other entities
  • User asks about available connectors, SOP templates, or schema fields

Workflow Overview

There are two ways to use the CLI:

Option A: Full Setup (recommended for new orgs)

Create a directory with YAML files anywhere on disk, then run one command:

cd modelguide-api
bun run src/cli/mg.ts setup /path/to/my-org/           # provision everything
bun run src/cli/mg.ts setup /path/to/my-org/ --dry-run  # validate and preview without changes

The directory can live anywhere — it does not need to be inside the modelguide repo. Pass an absolute or relative path.

Required file: org.yaml Optional files: users.yaml, secrets.yaml, connectors.yaml, agents.yaml, sops.yaml, guardrails.yaml, evals.yaml (or evals-*.yaml for multi-agent orgs), sessions.yaml

Flags:

  • --dry-run — validate all YAML files against schemas and print the plan without touching the database. Use this to verify files are correct before running for real.
  • --skip-secrets — use placeholder values (useful for CI/testing)
  • --skip-compile — skip agent compilation step
  • --skip-evals — skip eval import
  • --skip-sessions — skip demo session import

Option B: Individual Commands

Run each step separately (useful for adding to an existing org):

cd modelguide-api
bun run src/cli/mg.ts create-org --from /path/to/org.yaml
bun run src/cli/mg.ts add-users --org acme --from /path/to/users.yaml
bun run src/cli/mg.ts add-secrets --org acme --from /path/to/secrets.yaml
bun run src/cli/mg.ts add-connectors --org acme --from /path/to/connectors.yaml
bun run src/cli/mg.ts add-agents --org acme --from /path/to/agents.yaml
bun run src/cli/mg.ts import-sops --org acme /path/to/sops.yaml
bun run src/cli/mg.ts import-guardrails --org acme /path/to/guardrails.yaml
bun run src/cli/mg.ts import-evals --org acme /path/to/evals.yaml
bun run src/cli/mg.ts compile-agents --org acme
bun run src/cli/mg.ts import-sessions --org acme /path/to/sessions.yaml

Pipeline Dependency Order

The order matters because later steps reference entities created earlier:

1. org.yaml        — organization (everything scoped to this)
2. users.yaml      — users (agents need a createdBy user)
3. secrets.yaml    — standalone secrets (connectors may reference these)
4. connectors.yaml — connectors + connector-scoped secrets
5. agents.yaml     — agents + tool assignments (references connectors)
6. sops.yaml       — SOPs (references agents + connector tools)
7. guardrails.yaml — guardrails (references agents)
8. evals.yaml     — eval suites, evaluators, test cases (references agents + SOPs)
9. compile-agents  — compiles each agent against its active SOPs (skipped with --skip-compile)
10. sessions.yaml  — demo sessions (references agents)

The mg setup command handles this order automatically and threads an IdRegistry (slug-to-UUID map) across all steps so cross-references resolve without extra DB queries.

Idempotency

Re-running is safe:

  • Orgs: upsert on slug (updates settings if exists, warns)
  • Users/Agents/Connectors/SOPs/Guardrails: duplicate errors are caught and counted as "existing"
  • Evals: suites deduped by (agent, SOP) pair; test cases by externalId in JSONB; eval configs by name
  • Sessions: deduped by externalId (explicit or derived from payload hash)
  • Secrets: append-only (no stable dedup key — use --skip-secrets on re-runs)

Quick Schema Reference

Each YAML file has a specific structure. For the complete field-by-field reference with types, defaults, constraints, and edge cases, read references/schemas.md.

org.yaml

name: "Acme Corp"
slug: "acme"                    # lowercase + hyphens only
timezone: "America/Chicago"     # optional
features: [voice-agents]        # optional
demoEnabled: false              # optional, default false

users.yaml

users:
  - email: admin@acme.example.com
    name: "Alice Admin"
    role: admin                 # admin | support

secrets.yaml

secrets:
  - name: OpenAI API Key
    type: platform_api_key      # api_key | oauth_token | credentials | platform_api_key | webhook_secret
    scope: agent                # connector | agent (optional)
    # value: omitted = prompted interactively (or placeholder with --skip-secrets)

connectors.yaml

# Real connector — references a registered TypeScript manifest
connectors:
  - name: "Acme Store"
    slug: "acme_store"          # lowercase + underscores
    catalogSlug: "medusa"       # must match a catalog entry — see references/catalog.md
    config:
      baseUrl: "https://api.acme.example.com"
    secrets:                    # connector-scoped secrets created automatically
      - field: "secretApiKey"    # field name in connector config
        name: "Acme Store API Key"
        type: api_key

  # Mocked connector — DB-driven fixtures, no TypeScript handler (ADR-013)
  - name: "Bank Nowa Banking (Mock)"
    slug: "banknowa_banking"
    isMocked: true              # switches schema branch
    iconUrl: "/logos/bank-nowa.svg"   # optional
    tools:                       # inline tool defs — each returns `mock_response` verbatim
      - name: "Verify Customer"
        description: "Verify identity."
        input_schema:
          type: object
          properties: { name: {type: string} }
          required: [name]
        mock_response:
          success: true
          customer_id: "CUST-001"

Edit mock_response in YAML and re-run mg add-connectors — existing tool rows are reconciled (no delete-then-reimport needed). See references/schemas.md for full field tables.

agents.yaml

agents:
  - name: "Acme Voice Agent"
    slug: "acme-voice-agent"
    description: "Handles phone orders"
    modality: voice             # voice | text (default: voice)
    platform: custom            # custom | elevenlabs | livekit (default: custom)
    tools:
      - connectorSlug: "acme_store"           # all tools from this connector
      - connectorSlug: "acme_support"
        toolSlugs: [create_ticket, get_ticket] # specific tools only

For platform: livekit (voice-test + outbound dispatch require this):

agents:
  - name: "Acme Voice Agent"
    slug: "acme-voice-agent"
    modality: voice
    platform: livekit
    config:
      # Only url + agentName are valid for livekit. llmModel is rejected
      # (baked into the worker image).
      url: "wss://your-project.livekit.cloud"
      agentName: "acme_voice_agent"   # must match the profile key in the worker's config/agents.yaml
    tools:
      - connectorSlug: "acme_store"
    secrets:
      # No `value:` → `mg setup` prompts once per field. These exact field
      # names are read by agents.service.ts:getAgentSecretByType when
      # dispatching the worker.
      - field: livekit_api_key
        name: "LiveKit API Key"
        type: api_key
      - field: livekit_api_secret
        name: "LiveKit API Secret"
        type: api_key

sops.yaml — two modes

Inline SOP (define steps directly):

sops:
  - name: "Order Lookup"
    slug: "order-lookup"
    status: active              # draft | active | archived (default: draft)
    agents: ["acme-voice-agent"]
    trigger:
      type: intent_detected          # see references/schemas.md for all trigger types
      config:
        patterns: ["where is my order", "track my order", "order status"]
    steps:
      - id: greet
        instruction: "Greet and ask for order number"
        required: true
      - id: lookup
        instruction: "Look up the order"
        required: true
        tool:
          connectorSlug: "acme_store"
          toolSlug: "get_order"

Template fork (fork from a global SOP template):

sops:
  - name: "Order Lookup"
    templateSlug: "order-lookup"   # must match a template — see references/catalog.md
    status: active
    agents: ["acme-voice-agent"]
    connectorMapping:
      medusa: "acme_store"         # maps template's catalog refs to org's connector slugs

Cannot specify both templateSlug and steps.

guardrails.yaml

guardrails:
  - name: "No Medical Claims"
    slug: "no-medical-claims"
    content: |
      Never claim any product treats, cures, or prevents a medical condition.
    description: "FDA compliance"
    config: { priority: critical, category: compliance }
    agents: ["acme-voice-agent", "acme-chat-assistant"]

evals.yaml

One file per agent. For multi-agent orgs, use multiple files: evals-insurance.yaml, evals-booking.yaml, etc. The mg setup pipeline globs for evals*.yaml.

agentSlug: acme-voice-agent

evaluators:
  - name: confirms-order-id
    criterion: Agent confirms the order ID back to the customer
    tags: [accuracy]                    # optional
  - name: does-not-fabricate
    criterion: Agent does NOT make up order details or tracking information
    tags: [compliance, accuracy]        # optional

test_cases:
  - id: order-lookup-happy-path-01
    sop_slug: order-lookup
    scenario_key: order_status          # optional
    tags: [order-lookup, happy-path]    # optional
    evaluators:                         # references by name
      - confirms-order-id
      - does-not-fabricate
    input:
      customer_message: Hi, I placed an order last week, number ACM-12345.
      conversation_history:
        - role: assistant
          content: Thanks for calling Acme Corp. How can I help you today?

Also supports standalone import via JSON (eval-scenarios.json) with --agent flag:

bun run src/cli/mg.ts import-evals --org acme --agent acme-voice-agent /path/to/eval-scenarios.json

sessions.yaml

sessions:
  - agentSlug: "acme-voice-agent"
    channel: voice              # voice | web | api | slack | widget | sms | whatsapp | email
    status: completed           # active | completed | abandoned (default: completed)
    userIdentifier: "sarah@example.com"
    hoursAgo: 2                 # how far back to timestamp messages (default: 1)
    messages:
      - role: user
        content: "Hi, I want to check on my order ORD-1234."
      - role: assistant
        content: "Let me look that up for you."
    feedback:                   # optional
      verdict: good             # good | bad
      comment: "Very helpful"
      source: customer          # customer | support | system
    links:                      # optional
      - url: "https://store.acme.com/orders/1234"
        title: "Order ORD-1234"
        resourceType: "order"

How to Prepare Files for a New Organization

When the user describes their organization, follow this process:

  1. Gather requirements: What connectors do they need? What agents? What workflows (SOPs)?
  2. Create the directory: anywhere the user wants (e.g., ~/onboarding/my-customer/)
  3. Write files in dependency order: org → users → secrets → connectors → agents → sops → guardrails → evals → sessions
  4. Validate with dry-run: cd modelguide-api && bun run src/cli/mg.ts setup /path/to/dir --dry-run
  5. Run the import: add --skip-secrets for testing, or run without flags for production

For the full schema reference with every field, type, and constraint, read references/schemas.md. For available connector catalog entries and SOP templates, read references/catalog.md. For a complete working example (Acme Corp), read references/examples.md.

Running the CLI

All commands must be run from the modelguide-api/ directory:

cd modelguide-api
bun run src/cli/mg.ts <command> [options]

Running against Railway (from your local machine):

cd modelguide-api
railway run --service api -- sh -c \
  'DATABASE_URL=postgresql://modelguide_app:$APP_DB_PASSWORD@$POSTGRES_TCP_PROXY_DOMAIN:$POSTGRES_TCP_PROXY_PORT/$PGDATABASE \
   bun run src/cli/mg.ts setup /path/to/my-org/ --skip-secrets'

railway run injects all env vars (secrets, encryption keys, etc.). DATABASE_URL is overridden with the public TCP proxy since the private hostname isn't reachable locally. Requires TCP proxy vars from railway/DEPLOY.md step 6.

Common Patterns

Add a single agent to an existing org:

bun run src/cli/mg.ts add-agents --org acme name="New Agent" slug=new-agent modality=voice

Compile only one agent:

bun run src/cli/mg.ts compile-agents --org acme --agent acme-voice-agent

Import SOPs without activating (review first): Set status: draft in sops.yaml, import, review in dashboard, then activate manually.

Re-run after fixing a YAML error: Safe to re-run — duplicates are skipped. Only new entities get created.

Install via CLI
npx skills add https://github.com/modelguide/modelguide --skill mg-cli
Repository Details
star Stars 101
call_split Forks 4
navigation Branch main
article Path SKILL.md
More from Creator