Skip to content
Loom Documentation

Ai Providers

Supported out of the box

Provider Default model Notes
Anthropic claude-opus-5 Official SDK; adaptive thinking and schema-enforced output
OpenAI gpt-5 Chat completions with strict JSON schema
Google Gemini gemini-2.5-pro Schema is filtered to Gemini's supported subset
xAI grok-4 OpenAI dialect
OpenAI-compatible operator-set OpenRouter, Together, Groq, Ollama, vLLM, LM Studio

The compatible adapter is how you run this at near-zero marginal cost: point it at a model on your own hardware and generation costs nothing per run.

Where keys come from

Resolved most-specific first:

  1. The team's own key (Settings → AI providers)
  2. A platform-wide key (Admin → AI credentials, no workspace set)
  3. .env

Letting teams bring their own key is what makes this viable to operate without funding every generation yourself.

Keys are encrypted at rest with APP_KEY and never rendered back into a form.

Pricing and credits

Rates live in config/ai.php, in USD per million tokens, and are operator-maintained — providers change list prices and your account may be on negotiated rates.

credits = ceil(usd_cost × AI_CREDITS_PER_USD × AI_MARGIN)

Cached input is priced at a tenth of the standard rate. A run never costs zero.

Adding a provider

Implement App\Services\Ai\Contracts\LlmProvider:

final class MyProvider extends AbstractProvider
{
    public function name(): string { return 'mine'; }

    public function chat(LlmRequest $request): LlmResponse { /* … */ }
}

Then add a config/ai.php entry with the adapter class, key, default model and per-model rates. Nothing else in the application changes — orchestration talks only to the interface.

Structured output

Providers that can enforce a JSON schema get the generation contract on the wire. The rest get it in the prompt. Either way PlanParser validates the result before a single byte reaches a project, so a weaker provider degrades in reliability — never in safety.