Overview

mallcop.yaml lives in the root of your deployment repo. It controls which connectors to use, how findings are routed through the actor chain, budget ceilings, and self-improvement settings.

# Generated by mallcop init - edit as needed
version: "1"

connectors:
  - id: azure
    type: azure
    subscriptions: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"]

  - id: github
    type: github
    org: "3dl-dev"

routing:
  default:
    - triage
    - investigate
    - notify-teams

budget:
  max_tokens_per_finding: 20000
  max_tokens_per_run: 100000
  circuit_breaker_findings_threshold: 50

baseline:
  learning_days: 14
  window_days: 90

Connectors

Each connector entry specifies an id (your name for it), type (the plugin), and connector-specific options.

connectors:
  # Azure Activity Log, Container Apps, Cosmos DB, Defender
  - id: azure-prod
    type: azure
    subscriptions:
      - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    resource_groups: []        # empty = all resource groups
    include_container_logs: true

  # AWS CloudTrail
  - id: aws-prod
    type: aws-cloudtrail
    region: us-east-1
    lookback_hours: 8

  # GitHub org
  - id: github-3dl
    type: github
    org: "3dl-dev"

  # Microsoft 365
  - id: m365-corp
    type: m365
    tenant_id: "${M365_TENANT_ID}"  # env var reference

  # Vercel
  - id: vercel-main
    type: vercel
    team_id: "team_xxxxxxxx"

  # Container logs (Azure Log Analytics)
  - id: container-logs
    type: container-logs
    workspace_id: "${LOG_ANALYTICS_WORKSPACE_ID}"

Connector auth is always via environment variables or the configured secret backend. See the Connector Catalog for per-connector auth requirements.

Routing & actor chains

The routing section defines actor chains - ordered lists of actors that handle findings. You can route by severity, source, or detector.

routing:
  # Default chain for all findings
  default:
    - triage
    - investigate
    - notify-teams

  # Override for specific severities
  overrides:
    - match:
        severity: critical
      chain:
        - triage
        - investigate
        - investigate-deep   # custom deep-investigation actor
        - notify-teams

    - match:
        severity: info
      chain:
        - triage
        # no escalation for info findings

    - match:
        source: container-logs
      chain:
        - triage
        - notify-slack       # container issues go to Slack, not Teams

Actors are resolved from the built-in plugins, then from plugins/actors/ in your deployment repo.

Budget controls

Mallcop has hard budget ceilings that fire regardless of what the AI decides. These protect you from runaway actor chains during volume spikes or unusual finding patterns.

budget:
  # Per-finding: max tokens an actor chain can spend on one finding
  max_tokens_per_finding: 20000

  # Per-run: total tokens across all findings in one watch invocation
  max_tokens_per_run: 100000

  # Circuit breaker: if a single run generates N+ new findings,
  # skip actor invocations entirely (events still collected)
  circuit_breaker_findings_threshold: 50

  # Per-actor overrides
  actor_overrides:
    investigate:
      max_tokens_per_finding: 15000

When the circuit breaker fires, findings are marked uninvestigated and the next run will process them. Nothing is lost - collection continues, investigation pauses.

Secret backends

By default, mallcop reads secrets from environment variables. For production deployments, use a secret backend to avoid storing credentials in .env files.

secrets:
  backend: env   # default: read from environment

  # GitHub Secrets (for Actions deployments)
  # backend: github

  # Azure Key Vault
  # backend: azure-keyvault
  # vault_url: https://my-vault.vault.azure.net/

  # Env var references in connector config use ${VAR_NAME} syntax
  # These are resolved through the configured backend

Baseline tuning

The baseline stores what "normal" looks like for your environment. Mallcop learns from your actual activity - no manual configuration required. But you can tune the parameters.

baseline:
  # How long to collect data before flagging anomalies
  learning_days: 14

  # Rolling window: how far back the "normal" model looks
  window_days: 90

  # Minimum event count before an actor is considered "known"
  actor_min_events: 5

  # Volume anomaly multiplier - flag when volume exceeds NĂ— baseline
  volume_anomaly_multiplier: 5.0

  # Timing window - hours of day considered "unusual"
  # (derived from per-actor baseline, but this is the default)
  unusual_hours_start: 22   # 10pm
  unusual_hours_end: 6      # 6am

Self-improvement

Mallcop can propose improvements to its own prompts and plugins when it detects persistent weaknesses. This section controls which artifacts are eligible and what approval is required.

self_improvement:
  enabled: true

  # Approval levels per artifact tier:
  #   autonomous: apply without human review
  #   gated: require shakedown pass, then apply
  #   human: require human review before applying
  #   disabled: never modify this artifact type
  tiers:
    prompts: autonomous       # Tier 1: POST.md files
    parser_templates: autonomous  # Tier 2: parser YAML
    declarative_detectors: gated  # Tier 3: detector YAML
    event_classification: human   # Tier 4: Python code
    new_detectors: human          # Tier 5: new Python plugins

  # Max donuts per improvement cycle (prevents runaway spend)
  max_donuts_per_cycle: 10

See Self-Improvement for the full loop description.

Full example

# Complete mallcop.yaml for a typical small-team setup
version: "1"

connectors:
  - id: azure
    type: azure
    subscriptions: ["${AZURE_SUBSCRIPTION_ID}"]
    include_container_logs: true

  - id: github
    type: github
    org: "my-org"

routing:
  default:
    - triage
    - investigate
    - notify-teams

budget:
  max_tokens_per_finding: 20000
  max_tokens_per_run: 100000
  circuit_breaker_findings_threshold: 50

baseline:
  learning_days: 14
  window_days: 90

secrets:
  backend: env

self_improvement:
  enabled: true
  tiers:
    prompts: autonomous
    parser_templates: autonomous
    declarative_detectors: gated
    event_classification: human
    new_detectors: human