Agent skill

LLM Provider

by caliber-ai-org in caliber-ai-org/ai-setup

Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods.

MITAuto-check passedTesting & QA

Install LLM Provider

skills CLI
$ npx skills add caliber-ai-org/ai-setup --skill llm-provider -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install caliber-ai-org/ai-setup llm-provider --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/caliber-ai-org/ai-setup.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/llm-provider .claude/skills/llm-provider && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
llm-provider
GitHub stars
1.3k
Token cost
~2.7k tokens
SKILL.md length
670 words
Files
1
Skills in repo
8
Repo updated
First seen
Licence
MIT

At a glance

Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods.

  • Works in 7 steps: Create provider class file → Add to ProviderType union → Add config fields → …
  • Adding a new model backend
  • SKILL.md covers Critical, Instructions, Examples and Common Issues
  • Calls npm and npx

What it does

LLM Provider is an agent skill from caliber-ai-org/ai-setup. Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods. Integrates with provider factory in src/llm/index.ts, config detection in src/llm/config.ts, and error handling via tracking and recovery. Use when adding a new model backend, integrating a third-party LLM API, or extending LLM platform support. Do NOT use for fixing bugs in existing providers, modifying existing provider behavior, or changing the LLMProvider interface.

Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering LLM API integration and Error handling. It works with OpenAI. The repository describes itself as: Continuously sync your AI setups with one command. Codebase tailor suited agent skills, MCPs and config files for Claude Code, Cursor, and Codex. The licence is MIT.

When your agent uses it

  • Adding a new model backend
  • Integrating a third-party LLM API
  • Extending LLM platform support
  • Fixing bugs in existing providers

Example prompts

  • “/llm-provider”

Requirements

  • Node.js
  • A credential in YOUR_PROVIDER_API_KEY

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. Create provider class file
  2. Add to ProviderType union
  3. Add config fields
  4. Update config.ts
  5. Register in factory
  6. Write tests
  7. Integration test

What it can do on your machine

Read from SKILL.md and the folder at commit f5dbc00. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npm
    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npm and npx, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

LLM Provider loads about 2.7k tokens when it runs. Until then it costs about 120 tokens; SKILL.md has 670 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~120
When it runs · the whole SKILL.md, loaded when a task matches
~2.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from caliber-ai-org/ai-setup at commit f5dbc00, republished under its MIT licence (© caliber-ai-org). 670 words, ~2,711 tokens.

Download SKILL.mdSave it as .claude/skills/llm-provider/SKILL.md (or your agent's skills folder).
name
llm-provider
description
Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods. Integrates with provider factory in src/llm/index.ts, config detection in src/llm/config.ts, and error handling via tracking and recovery. Use when adding a new model backend, integrating a third-party LLM API, or extending LLM platform support. Do NOT use for fixing bugs in existing providers, modifying existing provider behavior, or changing the LLMProvider interface.
paths
src/llm/**/*.ts, src/llm/__tests__/**/*.ts

LLM Provider

Critical

  1. All providers MUST implement the LLMProvider interface from src/llm/types.ts with three methods:

    • call(options: LLMCallOptions): Promise<string> — single non-streaming call returning text
    • stream(options: LLMStreamOptions, callbacks: LLMStreamCallbacks): Promise<void> — streaming call invoking callbacks
    • listModels?(): Promise<string[]> — optional; list available models from the API
  2. Initialize client in constructor and store defaultModel from config. Example: this.client = new YourSDK({ apiKey: config.apiKey }). Never lazy-initialize on first call — providers are instantiated once and cached in src/llm/index.ts.

  3. For EVERY response in call() and stream(), invoke trackUsage(model, usage) from src/llm/usage.js before returning/ending. This is mandatory — it captures token metrics for CLI telemetry and cost analysis. If the API doesn't return usage data, estimate via estimateTokens(text), which assumes ~4 chars per token.

  4. Both call() and stream() must respect the model parameter using pattern: options.model || this.defaultModel. Never hardcode model names. Callers supply model overrides via LLMCallOptions.model.

  5. Error handling: catch all errors, preserve error messages unchanged. The retry logic in src/llm/index.ts handles transient errors (ECONNRESET, socket hang up, 529 overload). For seat-based providers (Cursor, Claude CLI), wrap stderr via parseSeatBasedError() for user-friendly messages.

  6. Always update ProviderType union (Step 2), DEFAULT_MODELS (Step 4), and createProvider() switch case (Step 5) in lock-step. Missing any one breaks the build or causes runtime Unknown provider error.

Instructions

Step 1: Create provider class file

Verify directory exists: ls -la src/llm/. Create src/llm/your-provider.ts. Match existing provider patterns (src/llm/anthropic.ts, src/llm/openai-compat.ts).

Minimal structure:

typescript
import type { LLMProvider, LLMCallOptions, LLMStreamOptions, LLMStreamCallbacks, LLMConfig, TokenUsage } from './types.js';
import { trackUsage } from './usage.js';
import { estimateTokens } from './utils.js';

export class YourProviderProvider implements LLMProvider {
  private client: YourSDKType;
  private defaultModel: string;

  constructor(config: LLMConfig) {
    if (!config.apiKey) throw new Error('API key required');
    this.client = new YourSDK({ apiKey: config.apiKey, ...(config.baseUrl && { baseURL: config.baseUrl }) });
    this.defaultModel = config.model;
  }

  async call(options: LLMCallOptions): Promise<string> {
    const model = options.model || this.defaultModel;
    const response = await this.client.messages.create({ model, max_tokens: options.maxTokens || 4096, system: options.system, messages: [{ role: 'user', content: options.prompt }] });
    trackUsage(model, { inputTokens: response.usage?.input_tokens || 0, outputTokens: response.usage?.output_tokens || 0 });
    return response.content?.[0]?.text || '';
  }

  async stream(options: LLMStreamOptions, callbacks: LLMStreamCallbacks): Promise<void> {
    const model = options.model || this.defaultModel;
    const messages = [...(options.messages || []), { role: 'user' as const, content: options.prompt }];
    try {
      const stream = await this.client.stream({ model, max_tokens: options.maxTokens || 10240, system: options.system, messages });
      let stopReason: string | undefined, usage: TokenUsage | undefined;
      for await (const chunk of stream) {
        if (chunk.delta?.text) callbacks.onText(chunk.delta.text);
        if (chunk.delta?.stop_reason) stopReason = chunk.delta.stop_reason;
        if (chunk.usage) usage = { inputTokens: chunk.usage.input_tokens, outputTokens: chunk.usage.output_tokens };
      }
      if (usage) trackUsage(model, usage);
      callbacks.onEnd({ stopReason, usage });
    } catch (error) { callbacks.onError(error instanceof Error ? error : new Error(String(error))); }
  }
}

Verify: File exports the class; imports match existing providers.

Step 2: Add to ProviderType union

Edit src/llm/types.ts line 1. Add your provider in kebab-case:

typescript
export type ProviderType = 'anthropic' | 'vertex' | 'openai' | 'cursor' | 'claude-cli' | 'your-provider';

Verify: npx tsc --noEmit shows no ProviderType errors.

Step 3: Add config fields

If your provider needs fields beyond apiKey, model, baseUrl, extend LLMConfig in src/llm/types.ts:

typescript
export interface LLMConfig {
  provider: ProviderType;
  model: string;
  fastModel?: string;
  apiKey?: string;
  baseUrl?: string;
  yourProviderSecret?: string;
}
Step 4: Update config.ts

Edit src/llm/config.ts:

Line 9: Add to DEFAULT_MODELS:

typescript
export const DEFAULT_MODELS: Record<ProviderType, string> = {
  anthropic: 'claude-sonnet-4-6',
  vertex: 'claude-sonnet-4-6',
  openai: 'gpt-5.4-mini',
  cursor: 'sonnet-4.6',
  'claude-cli': 'default',
  'your-provider': 'your-provider/default-model',
};

Line 17: Add to MODEL_CONTEXT_WINDOWS if known:

typescript
export const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
  'your-provider/model-name': 128_000,
};

Line 59: In resolveFromEnv(), add env detection before final return null:

typescript
if (process.env.YOUR_PROVIDER_API_KEY) {
  return {
    provider: 'your-provider',
    apiKey: process.env.YOUR_PROVIDER_API_KEY,
    model: process.env.CALIBER_MODEL || DEFAULT_MODELS['your-provider'],
    baseUrl: process.env.YOUR_PROVIDER_BASE_URL,
  };
}

Line 115: In readConfigFile() validation, add 'your-provider' to includes list.

Verify: npm run test -- src/llm/__tests__/ -t config confirms env var detection works.

Step 5: Register in factory

Edit src/llm/index.ts. Add import (line ~4):

typescript
import { YourProviderProvider } from './your-provider.js';

In createProvider() switch (line ~24), add before default case:

typescript
case 'your-provider':
  return new YourProviderProvider(config);

Verify: npx tsc --noEmit passes; no type errors on switch cases.

Step 6: Write tests

Create src/llm/__tests__/your-provider.test.ts:

typescript
import { describe, it, expect, beforeEach } from 'vitest';
import { YourProviderProvider } from '../your-provider.js';

describe('YourProviderProvider', () => {
  let provider: YourProviderProvider;
  beforeEach(() => {
    provider = new YourProviderProvider({ provider: 'your-provider', model: 'test', apiKey: 'test' });
  });

  it('implements LLMProvider interface', () => {
    expect(typeof provider.call).toBe('function');
    expect(typeof provider.stream).toBe('function');
  });

  it('call() returns string', async () => {
    const result = await provider.call({ system: 'helpful', prompt: 'hi' });
    expect(typeof result).toBe('string');
  });

  it('stream() invokes callbacks', async () => {
    const texts: string[] = [];
    let ended = false;
    await provider.stream({ system: 'helpful', prompt: 'hi' }, {
      onText: (t) => texts.push(t),
      onEnd: () => { ended = true; },
      onError: () => {},
    });
    expect(ended).toBe(true);
  });
});

Verify: npm run test -- src/llm/__tests__/your-provider.test.ts passes.

Step 7: Integration test

Run factory tests with your provider env var:

bash
YOUR_PROVIDER_API_KEY=test npm run test -- src/llm/__tests__/index.test.ts

Verify: getProvider() instantiates your provider; llmCall() dispatches correctly.

Examples

Show full SKILL.md (276 more words)Show less
Example 1: Local LM Studio server

User says: "I need caliber to use my local LM Studio instance."

Actions: Create src/llm/lm-studio.ts extending OpenAICompatProvider. Add 'lm-studio' to ProviderType. In config.ts:

typescript
if (process.env.LM_STUDIO_BASE_URL) {
  return { provider: 'lm-studio', apiKey: '', model: 'local', baseUrl: process.env.LM_STUDIO_BASE_URL };
}

Register in createProvider() case. User: export LM_STUDIO_BASE_URL=http://localhost:8000/v1. Result: caliber uses local LM Studio; tokens estimated via estimateTokens().

Example 2: Ollama (seat-based)

User says: "Ollama is auto-detected; no API key needed."

Actions: Create src/llm/ollama.ts extending OpenAICompatProvider. Add 'ollama' to ProviderType and SEAT_BASED_PROVIDERS. In config.ts:

typescript
if (process.env.OLLAMA_HOST) {
  return { provider: 'ollama', model: 'mistral', baseUrl: process.env.OLLAMA_HOST || 'http://localhost:11434/v1' };
}

Result: Offline per-machine LLM without API keys.

Common Issues

Unknown provider: your-provider

  • Cause: ProviderType updated but createProvider() case missing.
  • Fix: Add case in src/llm/index.ts and import the class.

Cannot find module './your-provider.js'

  • Cause: File named your_provider.ts (underscore) not your-provider.ts (kebab).
  • Fix: Rename file to use kebab-case.

API key is required for YourProvider

  • Cause: Env var YOUR_PROVIDER_API_KEY not set; resolveFromEnv() didn't detect it.
  • Fix: Verify env var name in config.ts matches. Test: YOUR_PROVIDER_API_KEY=test npm run test -- src/llm/__tests__/index.test.ts.

LLM response did not include usage tokens

  • Cause: Provider API doesn't return usage (local models).
  • Fix: Estimate tokens: trackUsage(model, { inputTokens: estimateTokens(options.system + options.prompt), outputTokens: estimateTokens(response.text) });

Stream callbacks never fire; onEnd not called

  • Cause: Async iterator not fully consumed before method returns.
  • Fix: Ensure iteration completes before onEnd(): for await (const chunk of stream) { } callbacks.onEnd({ stopReason, usage });

My model parameter is ignored

  • Cause: call()/stream() doesn't use options.model || this.defaultModel.
  • Fix: Replace hardcoded model: const model = options.model || this.defaultModel; const response = await this.client.create({ model, ... });

trackUsage() is never called

  • Cause: Forgot to call trackUsage() in call() or stream().
  • Fix: Add after every response: trackUsage(model, { inputTokens: ..., outputTokens: ... });

Type error: Provider doesn't implement LLMProvider

  • Cause: Missing method or wrong signature.
  • Fix: Verify all required methods exist with exact signatures from src/llm/types.ts. Copy-paste from anthropic.ts as reference.

© caliber-ai-org, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/llm-provider of caliber-ai-org/ai-setup.

Open the folder on GitHubat commit f5dbc00

Compare with similar skills

LLM Provider next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

LLM Provider compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
LLM Provider this skillcaliber-ai-org/ai-setup1.3k—~2.7kAutomated safety check: PassMIT
Reasoning Serialization Teststailcallhq/forgecode7.6k—~1kAutomated safety check: PassApache-2.0
Visual QARandallLiuXin/GodotMaker550—~1.8kAutomated safety check: PassCustom licence
ModLens Image Vision Bridgeliustack/modlens4.2k—~1.3kAutomated safety check: NotesMIT
9Router AI Gateway Setupdecolua/9router31k—~744Automated safety check: PassMIT
Mem0 Provider for Vercel AI SDKmem0ai/mem067k—~2.3kAutomated safety check: PassApache-2.0

Similar skills

  • Reasoning Serialization Tests

    tailcallhq/forgecode

    Checks that ReasoningConfig fields are serialized into the right provider-specific JSON for OpenRouter, Anthropic, GitHub Copilot and Codex requests.

    7.6k GitHub stars~1k tokensUpdated today
    Testing & QAAuto-check passed
  • Visual QA

    RandallLiuXin/GodotMaker

    Visual quality assurance: analyze game screenshots for defects, compare against reference, check motion in frame sequences.

    550 GitHub stars~1.8k tokensUpdated 23 days ago
    Testing & QAAuto-check passed
  • Gives text-only models sight by running the modlens CLI on an image path or URL and returning structured JSON evidence with transcribed text, layout and semantics.

    4.2k GitHub stars~1.3k tokensUpdated 6 days ago
    AI & LLM EngineeringAuto-check: notes
  • Sets up access to the 9Router AI gateway, an OpenAI-compatible REST endpoint for chat, images, speech, embeddings, web search and web fetch, and indexes its capability skills.

    31k GitHub stars~744 tokensUpdated 2 days ago
    AI & LLM EngineeringAuto-check passed
  • Adds persistent memory to Vercel AI SDK apps with the Mem0 provider, using a wrapped model or standalone retrieve and store utilities.

    67k GitHub stars~2.3k tokensUpdated yesterday
    AI & LLM EngineeringAuto-check passed
  • Sends chat and code-generation requests through a 9Router gateway using OpenAI or Anthropic message formats, with streaming and auto-fallback combos.

    31k GitHub stars~635 tokensUpdated 2 days ago
    AI & LLM EngineeringAuto-check passed

More from caliber-ai-org/ai-setup

All 8 skills in this repo
  • Adding A Command

    caliber-ai-org/ai-setup

    Creates a new CLI command following the Commander.js pattern in src/commands/.

    1.3k GitHub stars~2k tokensUpdated 16 days ago
    Auto-check passed
  • Caliber Testing

    caliber-ai-org/ai-setup

    Writes Vitest tests following project patterns: tests/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment…

    1.3k GitHub stars~3.2k tokensUpdated 16 days ago
    Auto-check passed
  • Find Skills

    caliber-ai-org/ai-setup

    Discovers and installs community skills from the public registry.

    1.3k GitHub stars~593 tokensUpdated 16 days ago
    Auto-check passed
  • Save Learning

    caliber-ai-org/ai-setup

    Saves user instructions as persistent learnings for future sessions.

    1.3k GitHub stars~626 tokensUpdated 16 days ago
    Auto-check passed
  • Scoring Checks

    caliber-ai-org/ai-setup

    Add a new deterministic scoring check in src/scoring/checks/ that evaluates config quality.

    1.3k GitHub stars~3k tokensUpdated 16 days ago
    Auto-check passed
  • Setup Caliber

    caliber-ai-org/ai-setup

    Sets up Caliber for automatic AI agent context sync. An agent skill from caliber-ai-org/ai-setup.

    1.3k GitHub stars~1.9k tokensUpdated 16 days ago
    Auto-check passed

Works with

Questions about LLM Provider

What does LLM Provider do?

Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods. LLM Provider is an agent skill from caliber-ai-org/ai-setup. Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods.

When should I use LLM Provider?

LLM Provider fits situations like: adding a new model backend; integrating a third-party LLM API; extending LLM platform support; fixing bugs in existing providers.

How do I install LLM Provider in Claude Code?

Run `npx skills add caliber-ai-org/ai-setup --skill llm-provider -a claude-code`. Or copy the skill folder (skills/llm-provider in caliber-ai-org/ai-setup) into .claude/skills/llm-provider in your project. Claude Code loads it when a task matches its description.

How do I install LLM Provider in Codex?

Run `npx skills add caliber-ai-org/ai-setup --skill llm-provider -a codex`. Or copy the skill folder (skills/llm-provider in caliber-ai-org/ai-setup) into .agents/skills/llm-provider in your project. Codex loads it when a task matches its description.

Can I use LLM Provider in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add caliber-ai-org/ai-setup --skill llm-provider -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/llm-provider, .gemini/skills/llm-provider, .github/skills/llm-provider and .opencode/skills/llm-provider in your project.

What does LLM Provider need to run?

Going by SKILL.md and its folder, LLM Provider needs the command-line tools its instructions call (npm and npx). Our summary lists: Node.js; A credential in YOUR_PROVIDER_API_KEY.

Does LLM Provider access the network?

SKILL.md contains no URLs. Its commands use npm and npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is LLM Provider safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does LLM Provider use?

LLM Provider is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does LLM Provider use?

About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to LLM Provider?

Skills that share tags, products or a category with LLM Provider: Reasoning Serialization Tests (tailcallhq/forgecode, 7.6k stars), Visual QA (RandallLiuXin/GodotMaker, 550 stars), ModLens Image Vision Bridge (liustack/modlens, 4.2k stars) and 9Router AI Gateway Setup (decolua/9router, 31k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains LLM Provider?

caliber-ai-org (a GitHub organization) maintains it in caliber-ai-org/ai-setup, which has 1,302 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on September 24, 2026.

Source: caliber-ai-org/ai-setup on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.