A unified JavaScript/TypeScript library for calling AI language models — with zero boilerplate, automatic provider fallback, agentic tool loops, and custom AI personas.
- One import, every provider — Gemini, Groq, Anthropic, Mistral, Cohere, OpenAI, Ollama, OpenRouter, and any OpenAI-compatible API
- Zero boilerplate — retries, rate limit backoff, message history, tool formatting handled automatically
- Provider-agnostic — swap models by changing one config line
- TypeScript native — full type safety, works seamlessly in JS and TS projects
- Zero runtime dependencies — lightweight, auditable, no bloat
npm install aivokimport { createAivok } from 'aivok'
### One-line setup (auto-detects API keys from `.env`)
```js
import 'dotenv/config'
import { createAivok } from 'aivok'
const ai = createAivok()
const answer = await ai.ask('Explain async/await in JavaScript')
console.log(answer)import { createAivok } from 'aivok'
const ai = createAivok({
provider: 'gemini',
model: 'gemini-2.0-flash',
apiKey: process.env.GEMINI_API_KEY,
})| Provider | Description |
|---|---|
| Gemini | Google Gemini — large context window |
| Groq | Groq — fast inference |
| Anthropic | Anthropic Claude — careful reasoning |
| Mistral | Mistral AI — multilingual |
| Cohere | Cohere — enterprise, RAG |
| OpenAI | OpenAI GPT models |
| OpenAI-compatible | Ollama, OpenRouter, DeepSeek, xAI |
See docs/providers.md for setup guides and API key instructions.
const reply = await ai.ask('What is the capital of France?')const session = ai.chat()
await session.send('Explain closures in JavaScript')
await session.send('Give me a real-world example')await ai.stream('Write a story', (chunk) => process.stdout.write(chunk))const data = await ai.json('List 5 JS frameworks with name and year')
// Returns parsed JavaScript objectconst ai = createAivok({
provider: 'gemini',
persona: {
name: 'Nova',
role: 'a helpful portfolio assistant',
tone: 'friendly and concise',
rules: ['keep answers short', 'only discuss my projects'],
},
})const ai = createAivok({
providers: [
{ name: 'gemini', model: 'gemini-2.0-flash', apiKey: process.env.GEMINI_API_KEY, primary: true },
{ name: 'groq', model: 'llama-3.3-70b-versatile', apiKey: process.env.GROQ_API_KEY },
],
})
// Tries Gemini first, automatically falls back to Groq on rate limitconst result = await ai.agent({
goal: 'Read package.json, bump the patch version, save it back',
tools: {
readFile: { description: 'Read a file', params: { path: 'string' }, run: async ({ path }) => fs.readFileSync(path, 'utf8') },
writeFile: { description: 'Write a file', params: { path: 'string', content: 'string' }, run: async ({ path, content }) => { fs.writeFileSync(path, content); return 'done' } },
},
maxSteps: 5,
})
console.log(result.answer) // final response
console.log(result.steps) // audit trailimport { createAivok, personas } from 'aivok'
const ai = createAivok({ ..., persona: personas.coder })
// personas.support | personas.tutor | personas.writer | personas.coder| Guide | Description |
|---|---|
| API Reference | Every function, parameter, and return type |
| Providers | Setup guides and API key instructions |
| Agents | Tool loop, tool definition format, examples |
| Personas | Custom AI identities, presets |
| Examples | Annotated copy-paste examples |
All methods throw errors with a code property:
try {
const reply = await ai.ask('Hello')
} catch (err) {
if (err.code === 'RATE_LIMIT') console.log('All providers rate limited')
if (err.code === 'AUTH_ERROR') console.log('Invalid API key')
if (err.code === 'MAX_STEPS') console.log('Agent exceeded maxSteps')
if (err.code === 'PARSE_ERROR') console.log('Invalid JSON response')
}Built by @tyecode