Skip to content

LLM models

LLM-backed enrichers share a common configuration type that specifies the provider and model. maat abstracts over providers so enrichers stay portable — the same model can often be reached through more than one provider (its own first-party API, Vertex AI, or OpenRouter) without changing anything else in your config.

Configuration shape

ts
type LLMConfig = {
  provider: string
  model: string
  extra?: Record<string, unknown>
  timeoutMs?: number
}

This config is passed directly to the enricher in maat.config.ts:

ts
import { defineConfig } from '@maat-tools/core'

export default defineConfig({
  collectors: [['@maat-tools/collector-ts', { tsConfigFilePath: './tsconfig.json' }]],
  enrichers: [
    ['@maat-tools/enricher-llm/com', {
      provider: 'anthropic',
      model: 'claude-haiku-4-5',
      extra: { apiKey: process.env.ANTHROPIC_API_KEY },
    }],
  ],
  rules: [['@maat-tools/connascence-rules/com-semantic', { threshold: '0.8' }]],
})

The provider selects how the model is reached and which credentials it needs; the model is the stable maat model id. maat resolves the right provider-specific model string internally (for example claude-opus-4-8 becomes anthropic/claude-opus-4.8 on OpenRouter).

Supported providers

ProviderproviderAuthModels
Google Vertex AIvertexADC (project + location)Gemini, Claude, Grok
Google AIgoogleAPI keyGemini
AnthropicanthropicAPI keyClaude
xAIxaiAPI keyGrok
OpenAIopenaiAPI keyGPT
OpenRouteropenrouterAPI keyAll of the above

Supported models

ModelmodelProvidersMax outputCost (in / out per Mtok)
Gemini 3.5 Flashgemini-3-5-flashvertex, google, openrouter65,536$1.50 / $9.00
Gemini 3.1 Pro Previewgemini-3-1-pro-previewvertex, google, openrouter64,000$2.00 / $12.00
Claude Sonnet 4.6claude-sonnet-4-6anthropic, vertex, openrouter64,000$3.00 / $15.00
Claude Opus 4.8claude-opus-4-8anthropic, vertex, openrouter128,000$5.00 / $25.00
Claude Haiku 4.5claude-haiku-4-5anthropic, vertex, openrouter64,000$1.00 / $5.00
Grok 4.3grok-4-3xai, vertex, openrouter131,000$1.25 / $2.50
GPT 5.4gpt-5-4openai, openrouter128,000$2.50 / $15.00
GPT 5.5gpt-5-5openai, openrouter128,000$5.00 / $30.00

All models expose a 1,000,000-token input window except Claude Haiku 4.5, which is 200,000.

JSON output and schemas

Enrichers that need structured data ask the model for JSON. maat enforces this with the strongest mechanism each provider supports, and always returns the same shape to the enricher:

Provider / pathEnforcement
Gemini (native)Native responseSchema
Claude (native)output_config.format JSON-schema structured outputs
OpenAI · Grok · OpenRouter · Claude-via-OpenRouterresponse_format: json_schema with strict: true

When a response schema is provided, maat wraps it into a strict, object-rooted schema for the provider (array roots are rejected by structured-output APIs) and unwraps the result before handing it back — so enrichers always receive a plain array. Strict structured outputs make every field in the schema required. For extraction-style enrichers this is the desired behavior; if a schema has genuinely optional fields, express them as nullable types.

If no schema is supplied, JSON mode falls back to a plain "valid JSON object" request plus a system-prompt instruction.

Determinism

maat asks for the most reproducible output each provider allows. Gemini requests are sent with temperature: 0. The Claude and GPT/Grok model families no longer accept sampling parameters (temperature, top_p, top_k) on these model versions — sending them is a hard error — so maat omits them and relies on the providers' deterministic defaults. See Repeatable results.

Cache and cost

Every LLM response is cached at .maat/enricher-cache/ by default, keyed by content hash, provider, model, and prompt instructions. Only items whose code actually changed trigger new calls. Commit .maat/enricher-cache/ to share the cache across CI environments.

Set the MAAT_ENRICHER_CACHE_DIR environment variable to override the cache location.

To bypass the cache for a single run, use maat check --no-cache.