| name | pi-mono |
| description | Unified LLM API library (@mariozechner/pi-ai) for TypeScript/JavaScript that abstracts provider differences across OpenAI, Anthropic, Google, Azure, Mistral, Groq, xAI, Cerebras, Amazon Bedrock, GitHub Copilot, and OpenAI-compatible services. Use when implementing LLM integrations, building agentic workflows with tool calling, switching between AI providers, managing conversation context, handling streaming responses, implementing vision capabilities, or tracking token usage and costs. Triggers on installing/configuring pi-ai, defining tools with TypeBox schemas, implementing stream/complete calls, handling tool calls and results, cross-provider handoffs, context serialization, or any multi-provider LLM integration work. |
Pi-Mono (@mariozechner/pi-ai) + @mariozechner/pi-agent-core
Unified LLM API that abstracts away provider differences, enabling seamless switching between AI models and providers while maintaining type safety and supporting tool calling for agentic workflows.
Quick Start
Install the library:
npm install @mariozechner/pi-ai
Basic usage pattern (see assets/basic-setup.ts for complete example):
import { stream, getModel, type Context, type Tool } from "@mariozechner/pi-ai";
import { Type } from "@sinclair/typebox";
const tools: Tool[] = [{
name: "get_weather",
description: "Get current weather for a location",
parameters: Type.Object({
location: Type.String({ description: "City name" })
})
}];
const context: Context = {
system: "You are a helpful assistant.",
messages: [{ role: "user", content: "What's the weather in Tokyo?" }]
};
const model = getModel("claude-3-5-sonnet-20241022");
for await (const event of stream(model, context, tools)) {
if (event.type === "text") process.stdout.write(event.text);
if (event.type === "tool_call") {
}
}
Core Capabilities
1. Multi-Provider Support
Switch between providers seamlessly:
const claude = getModel("claude-3-5-sonnet-20241022");
const gpt = getModel("gpt-4o");
const gemini = getModel("gemini-2.0-flash-exp");
const result = await complete(claude, context, tools);
Supported providers: OpenAI, Anthropic, Google, Azure, Mistral, Groq, xAI, Cerebras, Amazon Bedrock, GitHub Copilot, and OpenAI-compatible services (Ollama, vLLM, LM Studio).
2. Tool Calling (Function Calling)
All models in this library support tool calling, essential for agentic workflows:
const tools: Tool[] = [{
name: "search_database",
description: "Search the product database",
parameters: Type.Object({
query: Type.String(),
limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100 }))
})
}];
for await (const event of stream(model, context, tools)) {
if (event.type === "tool_call") {
const result = await executeToolCall(event.name, event.args);
context.messages.push({
role: "assistant",
content: [{ type: "tool_call", id: event.id, name: event.name, args: event.args }]
});
context.messages.push({
role: "user",
content: [{ type: "tool_result", id: event.id, result }]
});
}
}
3. Streaming & Events
Granular event types for real-time processing:
for await (const event of stream(model, context, tools)) {
switch (event.type) {
case "text":
process.stdout.write(event.text);
break;
case "thinking":
console.log("Thinking:", event.text);
break;
case "tool_call":
await handleToolCall(event);
break;
case "done":
console.log("Tokens:", event.usage);
console.log("Cost:", event.cost);
break;
case "error":
console.error(event.error);
break;
}
}
4. Cross-Provider Handoffs
Transfer conversations between providers while preserving context:
const context: Context = {
system: "You are a helpful assistant.",
messages: [{ role: "user", content: "Explain quantum computing" }]
};
const claude = getModel("claude-3-5-sonnet-20241022");
await complete(claude, context);
const gpt = getModel("gpt-4o");
context.messages.push({ role: "user", content: "Now explain it for a 5-year-old" });
await complete(gpt, context);
5. Context Serialization
Persist and resume conversations:
const serialized = JSON.stringify(context);
await fs.writeFile("conversation.json", serialized);
const restored: Context = JSON.parse(await fs.readFile("conversation.json", "utf-8"));
await complete(model, restored, tools);
6. Vision Support
Handle image inputs for vision-capable models:
const context: Context = {
messages: [{
role: "user",
content: [
{ type: "text", text: "What's in this image?" },
{ type: "image", source: { type: "url", url: "https://example.com/image.jpg" } }
]
}]
};
const result = await complete(getModel("gpt-4o"), context);
7. Reasoning/Thinking
Enable extended thinking modes:
const result = await completeSimple(model, "Solve this complex problem", { thinking: true });
const result = await complete(model, context, tools, {
thinking: { type: "enabled", budget_tokens: 10000 }
});
8. Token & Cost Tracking
Automatic usage reporting:
const result = await complete(model, context, tools);
console.log("Input tokens:", result.usage.input_tokens);
console.log("Output tokens:", result.usage.output_tokens);
console.log("Total cost:", result.cost);
Common Workflows
Agentic Loop with Tool Calling
async function agenticLoop(model: Model, initialPrompt: string, tools: Tool[]) {
const context: Context = {
system: "You are a helpful assistant with access to tools.",
messages: [{ role: "user", content: initialPrompt }]
};
let continueLoop = true;
while (continueLoop) {
continueLoop = false;
for await (const event of stream(model, context, tools)) {
if (event.type === "text") {
process.stdout.write(event.text);
} else if (event.type === "tool_call") {
const result = await executeToolCall(event.name, event.args);
context.messages.push({
role: "assistant",
content: [{ type: "tool_call", id: event.id, name: event.name, args: event.args }]
});
context.messages.push({
role: "user",
content: [{ type: "tool_result", id: event.id, result }]
});
continueLoop = true;
}
}
}
}
Provider Fallback
async function completeWithFallback(context: Context, tools: Tool[]) {
const providers = ["claude-3-5-sonnet-20241022", "gpt-4o", "gemini-2.0-flash-exp"];
for (const modelId of providers) {
try {
const model = getModel(modelId);
return await complete(model, context, tools);
} catch (error) {
console.error(`${modelId} failed:`, error);
}
}
throw new Error("All providers failed");
}
Authentication
Set environment variables for providers:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export GOOGLE_API_KEY="..."
export AZURE_OPENAI_API_KEY="..."
export AZURE_OPENAI_ENDPOINT="https://..."
Or pass explicitly:
const model = getModel("gpt-4o", { apiKey: "sk-..." });
@mariozechner/pi-agent-core Integration
@mariozechner/pi-agent-core
Stateful agent with tool execution and event streaming. Built on @mariozechner/pi-ai.
Installation
npm install @mariozechner/pi-agent-core
Quick Start
import { Agent } from "@mariozechner/pi-agent-core";
import { getModel } from "@mariozechner/pi-ai";
const agent = new Agent({
initialState: {
systemPrompt: "You are a helpful assistant.",
model: getModel("anthropic", "claude-sonnet-4-20250514"),
},
});
agent.subscribe((event) => {
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
await agent.prompt("Hello!");
Core Concepts
AgentMessage vs LLM Message
The agent works with AgentMessage, a flexible type that can include:
- Standard LLM messages (
user, assistant, toolResult)
- Custom app-specific message types via declaration merging
LLMs only understand user, assistant, and toolResult. The convertToLlm function bridges this gap by filtering and transforming messages before each LLM call.
Message Flow
AgentMessage[] → transformContext() → AgentMessage[] → convertToLlm() → Message[] → LLM
(optional) (required)
- transformContext: Prune old messages, inject external context
- convertToLlm: Filter out UI-only messages, convert custom types to LLM format
Reference Documentation
For detailed API documentation, examples, and advanced features, see:
Key sections in the reference:
- Tool calling with partial JSON streaming
- Error handling and abort patterns
- Custom model configuration
- OAuth provider setup
- Browser usage considerations
- OpenAI compatibility settings
Resources
- references/pi-ai-docs.md - Full official documentation from the pi-ai repository
- references/pi-agent-core-docs.md - Full official documentation from the pi-agent-core repository