# AirCoding Provider Capability Matrix V1

Date: 2026-05-27
Status: Canonical provider/model capability contract for V1.0.0 Alpha skeleton

This document defines how AirCoding represents provider/model capabilities, selects models, handles conversion limits, and records fallback behavior.

AirCoding's internal canonical message format is Anthropic content blocks. Provider adapters own conversion.

## 1. Goals

The provider capability matrix must answer:

1. Can this model/tool path execute the requested task?
2. Which capabilities are native vs emulated?
3. What quality/risk tier is acceptable for the task?
4. What conversion or feature loss must be recorded?
5. When should Scheduler force a model vs let an agent choose?

## 2. Provider Identity

```ts
type ProviderKind =
  | "anthropic"
  | "openai"
  | "openrouter"
  | "ollama"
  | "anthropic_compatible"
  | "openai_compatible"
  | "custom"

interface ProviderIdentity {
  provider_id: string
  provider_kind: ProviderKind
  display_name: string
  base_url?: string
  auth_ref?: string
  local: boolean
}
```

Secrets are referenced by `auth_ref`; they are never embedded in session DB events or artifacts.

## 3. Model Capability Matrix

```ts
interface ProviderCapabilityMatrix {
  provider_id: string
  provider_kind: ProviderKind
  model_id: string
  display_name?: string
  enabled: boolean
  quality_tier: "frontier" | "strong" | "standard" | "cheap" | "local" | "unknown"
  cost_tier: "high" | "medium" | "low" | "free" | "unknown"
  context_window_tokens?: number
  max_output_tokens?: number
  supports: {
    text_input: boolean
    text_output: boolean
    streaming: boolean
    tool_use: boolean
    parallel_tool_use: boolean
    structured_output: boolean
    json_mode: boolean
    thinking: boolean
    prompt_cache: boolean
    system_prompt: boolean
    image_input: boolean
    image_output: boolean
    audio_input: boolean
    audio_output: boolean
    file_input: boolean
    computer_use: boolean
    long_context: boolean
    batch: boolean
  }
  conversion: {
    from_anthropic_canonical: "lossless" | "lossy" | "unsupported"
    tool_schema: "native" | "converted" | "emulated" | "unsupported"
    image_input: "native" | "artifact_link" | "unsupported"
    thinking: "native" | "stripped" | "unsupported"
    cache_control: "native" | "ignored" | "unsupported"
  }
  limits?: {
    requests_per_minute?: number
    tokens_per_minute?: number
    concurrent_requests?: number
    max_tool_schema_bytes?: number
    max_image_count?: number
    max_file_bytes?: number
  }
  default_use?: {
    main?: boolean
    architecture?: boolean
    execute?: boolean
    review?: boolean
    debug?: boolean
    compact?: boolean
    mine_experience?: boolean
  }
  notes?: string[]
}
```

## 4. Capability Semantics

### `tool_use`

Native model-driven tool invocation.

If false, agents may still call deterministic internal tools outside model tool-use, but the model cannot choose tool calls directly in a single turn. This is lower quality for coding execution.

### `parallel_tool_use`

Model can request multiple tool calls in one turn. Scheduler/ToolRegistry may still serialize unsafe tools.

### `structured_output` / `json_mode`

Used for WorkerResult, review reports, scheduler decisions, and impact assessments. If unavailable, runtime validates best-effort parsed JSON and may retry with stricter prompt.

### `thinking`

Model supports a distinct reasoning/thinking channel or equivalent. If converted/stripped, the adapter must ensure hidden reasoning is not persisted as user-visible content.

### `prompt_cache`

Provider supports cache-control or equivalent prompt reuse. If unsupported, ContextAssembler still works but cost may be higher.

### `image_input`

Required for screenshot/UI analysis, diagram analysis, and image-based debugging.

### `image_output`

Required for first-class image generation. If unavailable, `ui-design-assets` falls back to SVG/assets/prompts.

### `computer_use`

Post-MVP. V1 uses explicit tools for GUI/screenshot/network rather than opaque computer-use loops.

## 5. Task Capability Requirements

```ts
interface ModelRequirement {
  required: Partial<ProviderCapabilityMatrix["supports"]>
  preferred?: Partial<ProviderCapabilityMatrix["supports"]>
  min_quality_tier?: "frontier" | "strong" | "standard" | "cheap" | "local"
  max_cost_tier?: "high" | "medium" | "low" | "free"
  min_context_window_tokens?: number
  allow_lossy_conversion?: boolean
}
```

Default requirements by task type:

| Task type | Required | Preferred | Quality floor |
|---|---|---|---|
| Main conversation | streaming, tool_use | prompt_cache, long_context | strong |
| Architecture Designer | structured_output, long_context | thinking, prompt_cache | frontier/strong |
| Executor | tool_use, structured_output | thinking, long_context | frontier/strong |
| Reviewer | structured_output | image_input for UI artifacts | strong |
| Debugger | tool_use, structured_output | long_context, image_input | strong |
| Compactor | long_context or large enough context | prompt_cache | standard |
| ExperienceMiner | structured_output | long_context | standard |
| UI screenshot analysis | image_input | structured_output | strong |
| Image generation | image_output | image editing | provider-specific |

## 6. Scheduler Model Assignment

Scheduler chooses one of:

```ts
type ModelAssignmentMode = "scheduler_forced" | "agent_select"

interface ModelAssignment {
  mode: ModelAssignmentMode
  provider_id?: string
  model_id?: string
  allowed_models?: Array<{ provider_id: string; model_id: string }>
  requirement: ModelRequirement
  reason: string
}
```

Guidelines:

1. Use `scheduler_forced` for cross-model review, high-risk tasks, repeated failures, and deterministic comparisons.
2. Use `agent_select` for normal implementation/debug tasks when multiple acceptable models exist.
3. Use strong/frontier models for code-changing tasks where hidden complexity may exist.
4. Use cheaper models for summarization, indexing, and low-risk classification when evidence can be validated.
5. Escalate if no model satisfies required capabilities.

## 7. Provider Adapter Contract

```ts
interface ProviderAdapter {
  provider_id: string
  list_models(): Promise<ProviderCapabilityMatrix[]>
  validate_model(model_id: string): Promise<ProviderCapabilityMatrix>
  complete(input: ProviderCompletionInput): AsyncIterable<ProviderStreamEvent>
  count_tokens?(input: unknown): Promise<number>
}

interface ProviderCompletionInput {
  model_id: string
  canonical_format: "anthropic"
  messages: unknown[]
  tools?: unknown[]
  tool_choice?: unknown
  system?: unknown
  max_output_tokens?: number
  temperature?: number
  metadata?: Record<string, unknown>
}
```

Adapter responsibilities:

1. Convert Anthropic canonical messages to provider format.
2. Convert provider output back to Anthropic canonical content blocks or RuntimeEvents.
3. Validate tool-call and structured-output compatibility.
4. Record conversion omissions/losses.
5. Never leak credentials into logs, events, artifacts, or model-visible messages.

## 8. Conversion Loss Handling

Conversion result:

```ts
interface ProviderConversionReport {
  status: "lossless" | "lossy" | "unsupported"
  omissions: string[]
  warnings: string[]
  required_confirmation?: boolean
}
```

Rules:

1. Lossless conversion continues silently.
2. Lossy conversion may continue only if `allow_lossy_conversion` is true and omitted features are not required.
3. Unsupported required feature blocks before model call.
4. Thinking/cache-control stripping is allowed only when not required by task policy.
5. Tool schema truncation or unsupported required tool use blocks.

## 9. Configuration Locations

Global provider/model config:

```text
~/.air/models.yaml
```

Project override:

```text
<project>/.air/shared/models.yaml
```

Session records store selected `model_provider_id` and `model_id`, but not secrets.

Example config shape:

```yaml
providers:
  - provider_id: anthropic-main
    provider_kind: anthropic
    display_name: Anthropic
    auth_ref: env:ANTHROPIC_API_KEY
    enabled: true
    models:
      - model_id: claude-opus-4-7
        quality_tier: frontier
        cost_tier: high
        default_use:
          architecture: true
          execute: true
          review: true
      - model_id: claude-sonnet-4-6
        quality_tier: strong
        cost_tier: medium
        default_use:
          main: true
          debug: true
          compact: true
```

## 10. Doctor Checks

Doctor validates:

```text
provider config parseability
auth_ref existence without printing secret values
base_url reachability when allowed
model list/validation where provider supports it
required default model coverage by role
capability mismatch warnings
rate-limit metadata if configured
```

Doctor must not persist or print API keys.

## 11. Fallback Policy

Fallback order:

1. Same provider, same quality tier, compatible model.
2. Same provider, higher quality tier if allowed.
3. Different provider with lossless/acceptable conversion.
4. Lower quality tier only for non-code-changing or explicitly allowed tasks.
5. Block and ask Main Agent/user if no safe fallback exists.

Fallback must record:

```text
original provider/model
selected provider/model
reason
capability differences
conversion report
```

## 12. V1.0.0 Alpha Cut Line

V1.0.0 Alpha skeleton must implement:

1. `ProviderCapabilityMatrix` contract.
2. Global/project model config loading.
3. Anthropic and OpenAI-compatible adapter interfaces.
4. Capability-based model selection.
5. Conversion report and omission handling.
6. Scheduler model assignment integration.
7. Doctor provider checks.
8. Session persistence of chosen provider/model IDs.

Post-MVP:

```text
automatic provider benchmarking
cost optimizer
multi-provider speculative review
batch processing
computer-use models
native image-generation providers
local model quality calibration
```
