К основному содержанию
скилл CX Codex

extension-inference — скилл для Claude Code: LLM в Caffeine-приложении

Скилл задаёт единственный поддерживаемый способ подключить LLM к Caffeine-приложению: через пакет caffeineai-inference-client и Config.fromEnv, без ключа от пользователя.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add caffeinelabs/skills --skill extension-inference -a claude-code
Открыть на GitHub

Что делает extension-inference

Скилл нужен, когда в Caffeine-приложении появляется чат, суммаризация или классификация через LLM. Он описывает маршрут по умолчанию: Caffeine Inference — OpenAI-совместимый эндпоинт, который платформа хостит, аутентифицирует и оплачивает. Канистра получает учётные данные в рантайме, ключ никто не вставляет, приложение его не хранит и не возвращает.

Внутри — рецепт для бэкенда на Motoko. В mops.toml добавляется [email protected], нужен Mops ≥ 2.13. Конфиг берётся из fromEnv, поле is_replicated = ?false уже выставлено и переопределять его нельзя: реплицированный вызов шлёт bearer со всех реплик, умножает расходы на размер подсети и ломает консенсус из-за сэмплинга. Модель всегда "router" — платформа сама подбирает размер под сложность запроса, поэтому селектор модели в интерфейсе не нужен.

Ручной ic.http_request к inference.caffeine.ai или api.openai.com здесь считается антипаттерном. Из API доступны только chat completions (POST /v1/chat/completions); эмбеддингов, изображений, аудио и прочего на этом хосте нет. Если спецификация прямо требует вставленный пользователем ключ sk-... к api.openai.com, берите extension-openai. Ошибку от fromEnv не прячьте: предварительные проверки переменных и пустой ответ вместо ошибки превращают сломанный вызов в вид работающей функции.

Какие задачи решает

  • подключить LLM к Caffeine-приложению без ключа от пользователя
  • добавить caffeineai-inference-client в mops.toml и собрать конфиг из окружения
  • вызвать chat completions из Motoko-канистры
  • не платить за инференс многократно из-за реплицированного вызова
  • отличить случай, когда нужен extension-openai

Примеры запросов агенту

  • Добавь в приложение чат с LLM на Caffeine Inference: подключи caffeineai-inference-client и сделай вызов через ChatApi.createChatCompletion.
  • Сделай на бэкенде функцию, которая суммаризирует текст через model = "router", и не добавляй поле выбора модели.
  • Проверь мой код: не ходит ли он напрямую в inference.caffeine.ai через ic.http_request?

Как установить extension-inference

1Через Skills CLI (Vercel)

npx skills add caffeinelabs/skills --skill extension-inference -a claude-code

2Вручную: положить файлы

~/.claude/skills/extension-inference/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/extension-inference/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора25

extension-oql Открывает данные канистры Motoko для запросов агента Caffeine Data Intelligence через эндпоинты schema() и execute(). Пригодится для поиска по картам и массивам на естественном языке. CX Codex +1 27 700установок connector-googlemail Инструкция по отправке писем из канистры от имени личного аккаунта Gmail пользователя через Motoko и Mops. Защищает от сырых HTTP-запросов к Google API. CX Codex +1 25 000установок extension-querying-oql Шпаргалка по составлению OQL-запросов к канистре backend через консольную утилиту icp. Помогает агенту считывать схему, фильтровать записи и разбирать Candid-ответы. CX Codex +1 24 700установок connector-slack Скилл учит агента отправлять сообщения в канал Slack из Caffeine-канистры через пакет slack-client. Рецепт помечен как экспериментальный. CX Codex +1 14 300установок connector-twilio Скилл для отправки SMS и MMS из Caffeine-канистры через пакет twilio-client. Экспериментальный: ни один вызов ещё не проверяли на живом Twilio. CX Codex +1 11 200установок connector-googledrive Скилл подключает Google Drive к сборкам на Caffeine: списки файлов, папки, доступы и комментарии через готовые mops-пакеты. CX Codex +1 9 100установок connector-weatherapi Скилл задаёт правильный способ читать погоду в Caffeine-сборках: через mops-пакет weatherapi-client, а не самодельные вызовы ic.http_request. CX Codex +1 7 300установок connector-spotify Скилл для Caffeine-сборок на Motoko: подключает Spotify Web API через пакет spotify-client и запрещает самодельные HTTP-вызовы. CX Codex +1 6 500установок

Похожие

gke-inference официальный google Готовит Kubernetes-манифесты для AI/ML-инференса на GKE и помогает выбрать модельный профиль и ускоритель для нового сервинга. CX Codex 6 791установок inference-sh inference-sh Набор скиллов, которые дают агенту доступ к генерации картинок и видео, вызову языковых моделей и веб-поиску через CLI inference.sh. ★ 777звёзд репо omni-inference cheaper-inference Скилл подключает эндпоинты для чат-комплишенов, эмбеддингов, аудио и изображений в стиле OpenAI. Пригодится агентам для прямого доступа к API вывода моделей. CX Codex +1 1 100установок spring-boot-cache giuseppe-trisciuoglio Помогает настроить кэширование в Spring Boot через Caffeine, Redis или Ehcache. Пригодится для аннотирования сервисов, задания TTL и поиска причин промахов кэша. CX Codex +1 3 800установок agent-platform-inference официальный google Скилл запускает инференс моделей Google Cloud Agent Platform и помогает подготовить код для Gemini и OpenMaaS. Нужен для тестовых запросов и чат-комплишенов. CX Codex 8 138установок tao-run-inference-service NVIDIA Corporation Скилл развёртывает микросервис инференса моделей NVIDIA TAO в контейнере и останавливает его. Пригодится для работы с контрольными точками и отправки запросов к эндпоинту. CX Codex +1 1 600установок

Рядом в теме «ИИ и ML»

Всё по теме «ИИ и ML» →

Вопросы о extension-inference

Как установить extension-inference в Claude?

Выполните npx skills add caffeinelabs/skills --skill extension-inference -a claude-code. Скилл окажется в ~/.claude/skills/extension-inference/SKILL.md.

Что делает extension-inference?

Описывает, как подключить LLM к Caffeine-приложению через Caffeine Inference: пакет caffeineai-inference-client, конфиг из fromEnv, модель "router". Ключ от пользователя не нужен.

Чем это отличается от extension-openai?

extension-openai берут, только когда спецификация прямо требует вставленный пользователем или админом ключ sk-... к api.openai.com. Для обычного LLM в Caffeine-приложении он не нужен.

Исходный текст

SKILL.md · Apache-2.0
---
name: extension-inference
description: >-
  MANDATORY recipe for every Caffeine build that calls an LLM, chatbot,
  GPT, or ChatGPT **on Caffeine Inference** (no user-pasted OpenAI key).
  The ONLY supported path is the `caffeineai-inference-client` mops package
  authenticated config — the app never asks for, stores, or returns a key.
  Hand-rolling `ic.http_request` to `inference.caffeine.ai` (or
  `api.openai.com`) is a FORBIDDEN anti-pattern. Load this skill whenever
  the user, spec, or any prior task wants an LLM in a Caffeine app — and
  BEFORE writing any code that talks to an LLM host. Use `extension-openai`
  only when the spec explicitly requires a user- or admin-pasted `sk-...`
  key against `api.openai.com`.
version: 0.1.3
compatibility:
  mops:
    caffeineai-inference-client: "~0.2.0"
caffeineai-subscription: [none]
---

# Caffeine Inference
LLM extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).

## Orchestrator routing notes

Treat “use an LLM / GPT / chatbot / summarise with AI” as a first-class
platform feature. The default path is **Caffeine Inference**: an
OpenAI-compatible chat endpoint that Caffeine hosts, authenticates, and bills
for the app. The canister gets its credentials from the platform at runtime;
nobody pastes an API key, and the app never stores or returns one.

| User intent | Capability |
| --- | --- |
| Chat / summarise / classify with an LLM in a Caffeine app | `caffeineai-inference-client` `ChatApi.createChatCompletion` via this skill |
| Call `api.openai.com` with a user-pasted `sk-...` | [`extension-openai`](../extension-openai/SKILL.md) only |

Do **not** load `extension-openai` for a normal Caffeine-app LLM. Do **not**
ask the user for an OpenAI API key. Do **not** add `setApiKey` endpoints, a
key-settings page, or a model picker.

# Backend

## 1. Add `caffeineai-inference-client` to `mops.toml`

```bash
mops add [email protected]
```

Requires Mops ≥ 2.13. **Minimum version:** `caffeineai-inference-client ≥ 0.2.0`.

## 2. Config comes from the platform

`is_replicated = ?false` — from the credentials the platform provisions for the
app. There is no key to collect and nothing to configure.

  `let config = fromEnv` will not compile, and a cached `Config` can go stale
  when the platform rotates credentials on a running canister.
- It traps when the app has no inference credentials. Let that error reach
  the caller; hiding it makes a failed AI call look like a working feature:
  - Never pre-check `CAFFEINE_INFERENCE_API_KEY` (or any other environment
    variable) and never guard `fromEnv` with a check that skips the call.
  - Never turn a failed call into an empty success, such as an empty string,
    an empty list, or placeholder text. Trap or return the error so the
    frontend can show it and offer a retry.
  - Do not add a "configure AI" empty state or a key-input fallback.
- Never log the `Config`, never copy its `auth` into actor state, and never
  return it (or any part of it) from a `query` / `shared` function.

## 3. `is_replicated = ?false` is REQUIRED

`fromEnv` already sets this. Do not override it to `?true` or `null`.

1. **Security.** A replicated outcall sends the bearer from every replica.
2. **Billing.** Replicated outcalls multiply inference spend by subnet size.
3. **Determinism.** LLM bodies are sampled; consensus would fail.

## 4. Canonical layout

```motoko filepath=src/backend/main.mo
import Inference "lib/inference";

actor {
  public shared func chat(prompt : Text) : async Text {
  };
};
```

```motoko filepath=src/backend/lib/inference.mo
import { fromEnv } "mo:caffeineai-inference-client/Config";
import ChatApi "mo:caffeineai-inference-client/Apis/ChatApi";
import ChatCompletionRequest "mo:caffeineai-inference-client/Models/ChatCompletionRequest";
import ChatCompletionRequestMessageOneOf2 "mo:caffeineai-inference-client/Models/ChatCompletionRequestMessageOneOf2";
import Runtime "mo:core/Runtime";

module {
    let userMessage = ChatCompletionRequestMessageOneOf2.JSON.init({
      content = #string(prompt);
      role = #user;
    });
    let req = ChatCompletionRequest.JSON.init({
      messages = [#user(userMessage)];
      model = "router";
    });
    let resp = await* ChatApi.createChatCompletion(config, req);
    if (resp.choices.size() == 0) {
      Runtime.trap("Inference returned no choices");
    };
    resp.choices[0].message.content
      ?? Runtime.trap("Inference returned no text content");
  };
};
```

## 5. `model = "router"` — the platform picks the model

`"router"` is the only public model id, and it is a routing tier rather than a
model name. Caffeine Inference sizes each request to the complexity of the
query — a small fast model for simple prompts, a stronger one for hard
reasoning — and reports `"router"` back as the response `model`, so provider
names never reach the app.

- Always send `model = "router"`.
- Do not add a model dropdown, a "use GPT-4" toggle, or a `model` parameter on
  the backend endpoint. There is nothing for the user to choose.
- Steer quality with the prompt and with the declared sampling fields
  (`temperature`, `top_p`, `max_completion_tokens`), not with model selection.

## 6. Call shapes

- **Function form:** `ChatApi.createChatCompletion(config, req) : async*` — use `await*`.
- **Suite form:** `let api = ChatApi(config); api.createChatCompletion(req) : async`.

## 7. Available API surface — chat completions

`[email protected]` is generated from
[`public-api-v0.1.0`](https://github.com/caffeinelabs/inference/releases/tag/public-api-v0.1.0):

| Module | Entry point | Route |
| --- | --- | --- |
| `ChatApi` | `createChatCompletion` | `POST /v1/chat/completions` |
| `ModelsApi` | `listModels` | `GET /v1/models` — catalog only; the model is always `"router"`, so an app never needs this |

<!-- motoko-check:skip -->
```motoko
import ChatApi "mo:caffeineai-inference-client/Apis/ChatApi";
import { fromEnv } "mo:caffeineai-inference-client/Config";
```

Chat completions are the whole product surface. **Not available** on this host
(404, and not in the package): embeddings, images, audio, moderations, files,
legacy completions, Assistants, Responses, and raw `ic.http_request`. If the
spec genuinely needs an OpenAI-only API with a pasted `sk-...`, switch to
[`extension-openai`](../extension-openai/SKILL.md).

## 8. Cycles

Leave `cycles` unset (`null`): each call attaches the fee the IC charges for
that request, which is zero on subnets where outcalls are free. `?n` attaches exactly `n` cycles: the IC rejects the call when `n` is below its fee, and the call traps on a subnet where the canister holds fewer than `n`.

Streaming (`stream = ?true`) is unsupported — management-canister HTTP returns
the full body. Leave `stream = null`.

## 9. Things that will bite you

- Surface failures. No credential pre-checks, no guard around `fromEnv`, and no empty result in place of an error. See §2.
- `model = "router"` — not `"gpt-4o-mini"`. See §5.
- User turns are `#user(ChatCompletionRequestMessageOneOf2.JSON.init({ content = #string(prompt); role = #user }))`.
- `JSON.init` for required fields; layer optionals with record update. Do not hand-list every `null`.
- `resp.choices[0].message.content` is `?Text`. Check `choices.size()` first.
- One chat call is one HTTP outcall inside an update call: budget seconds, not milliseconds.

# Frontend

The app is ready to chat on first load — there is nothing to configure.

1. **No API-key UI.** No settings page, no password input, no "configured?"
   indicator, no localStorage. If a spec or mock shows an "AI settings"
   screen, drop it.
2. **No model picker.** See §5.
3. Call the backend chat endpoint (`chat(prompt)`) and render the returned
   text. There is no frontend LLM SDK — the canister is the client, so the
   credentials never reach the browser.
4. Show a pending state while the call is in flight (an outcall round-trip
   takes seconds) and surface a retry on trap.

© caffeinelabs · Apache-2.0 · caffeinelabs/skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой