Skip to Content

Model providers

Choose a model provider, keep keys in .env, and reach any other provider.

Set model in plico.config.ts. plico validate fails when model.provider is not one of the providers below and the project has no matching file in providers/.

providerKey variablePackage to install
anthropicANTHROPIC_API_KEY@ai-sdk/anthropic
googleGOOGLE_GENERATIVE_AI_API_KEY@ai-sdk/google
openaiOPENAI_API_KEY@ai-sdk/openai
openai-compatibleOPENAI_API_KEYnone

The adapter packages are optional peer dependencies, so install only the one you use: pnpm add @ai-sdk/anthropic. A run that needs a missing package fails with that command.

plico.config.ts
export default defineConfig({
  schemaVersion: 1,
  name: "My agent",
  model: { provider: "anthropic", name: "claude-sonnet-5-5" },
});

Keys and .env

plico run, plico serve and plico readiness load .env from the project folder. A variable already set in the shell wins over the file. Values are never logged, and plico readiness says when a .env was loaded. Keep .env out of git.

Set model.apiKeyEnv to read the key from another variable. Set model.baseURL to change the endpoint. For openai and openai-compatible, OPENAI_BASE_URL is the fallback.

Long conversations

When a thread outgrows the model's context window, the run fails with a clear message to start a new thread or choose a model with a larger context. Plico does not retry this error.

Other providers

openai-compatible reaches any server that speaks the OpenAI chat API:

plico.config.ts
// OpenRouter
model: { provider: "openai-compatible", name: "anthropic/claude-sonnet-5-5",
  baseURL: "https://openrouter.ai/api/v1", apiKeyEnv: "OPENROUTER_API_KEY" }

// LiteLLM proxy
model: { provider: "openai-compatible", name: "my-model",
  baseURL: "http://localhost:4000/v1", apiKeyEnv: "LITELLM_API_KEY" }

// Ollama (any non-empty key works)
model: { provider: "openai-compatible", name: "llama3.2",
  baseURL: "http://localhost:11434/v1", apiKeyEnv: "OLLAMA_API_KEY" }

// Vercel AI Gateway
model: { provider: "openai-compatible", name: "anthropic/claude-sonnet-5-5",
  baseURL: "https://ai-gateway.vercel.sh/v1", apiKeyEnv: "AI_GATEWAY_API_KEY" }

// Groq
model: { provider: "openai-compatible", name: "openai/gpt-oss-20b",
  baseURL: "https://api.groq.com/openai/v1", apiKeyEnv: "GROQ_API_KEY" }

Reasoning models return their reasoning text. Plico sends it back after a tool call, because some servers need it. A server that rejects it (Groq does) gets one retry without it, and Plico leaves it out for the rest of that run.

For anything else, name the provider after a file in providers/. It exports a function that returns an AI SDK language model:

providers/acme.ts
import { defineProvider } from "@plico-ai/sdk";
import { createAcme } from "@acme/ai-sdk-provider";

export default defineProvider(({ model, apiKey, baseURL }) =>
  createAcme({ apiKey, baseURL })(model),
);
plico.config.ts
model: { provider: "acme", name: "acme-large", apiKeyEnv: "ACME_API_KEY" }

Plico wraps the model behind its own model port, so no AI SDK type enters the project contract. Retries stay off inside the adapter; the engine retries the step.

On this page