Use the Opper Node/TypeScript SDK (opperai) for AI task completion, structured output with JSON Schema or Zod, knowledge base semantic search, streaming responses, and tracing. Activate when building TypeScript or JavaScript applications that need LLM-powered task completion, RAG pipelines, or AI function orchestration with the Opper platform.
Install
npx skillscat add opper-ai/opper-skills/opper-node-sdk Install via the SkillsCat registry.
Opper Node SDK
Build AI-powered applications in TypeScript with declarative task completion, structured outputs, knowledge bases, streaming, and full observability.
Installation
npm add opperai
# or: pnpm add opperai / yarn add opperai / bun add opperaiSet your API key:
export OPPER_HTTP_BEARER="your-api-key"Get your API key from platform.opper.ai.
Core Pattern: Task Completion
The opper.call() method is the primary interface. Describe a task and get structured results:
import { Opper } from "opperai";
const opper = new Opper({
httpBearer: process.env["OPPER_HTTP_BEARER"] ?? "",
});
// Simple call with structured output
const result = await opper.call({
name: "extractRoom",
instructions: "Extract details about the room from the provided text",
input: "The Grand Hotel offers a luxurious suite with 3 rooms and an ocean view.",
outputSchema: {
type: "object",
properties: {
room_count: { type: "number" },
view: { type: "string" },
hotel_name: { type: "string" },
},
required: ["room_count", "view", "hotel_name"],
},
});
console.log(result.jsonPayload);
// { room_count: 3, view: "ocean", hotel_name: "The Grand Hotel" }Structured Output with JSON Schema
Define input and output schemas for type-safe interactions:
const result = await opper.call({
name: "analyze_sentiment",
instructions: "Analyze the sentiment of the given text",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "Text to analyze" },
},
required: ["text"],
},
outputSchema: {
type: "object",
properties: {
label: { type: "string", enum: ["positive", "negative", "neutral"] },
confidence: { type: "number", description: "0.0 to 1.0" },
reasoning: { type: "string" },
},
required: ["label", "confidence"],
},
input: { text: "I love this product!" },
});
console.log(result.jsonPayload);
// { label: "positive", confidence: 0.95, reasoning: "..." }Model Selection
Control which LLM to use with the model parameter:
const result = await opper.call({
name: "generate",
instructions: "Write a haiku about the given topic",
input: "autumn leaves",
model: "anthropic/claude-4-sonnet",
});Available models include providers like openai/, anthropic/, google/, and more.
Few-Shot Examples
Guide model behavior with input/output examples:
const result = await opper.call({
name: "classify_ticket",
instructions: "Classify the support ticket category",
input: { text: "My payment was declined" },
examples: [
{ input: { text: "I can't log in" }, output: "authentication" },
{ input: { text: "Charged twice" }, output: "billing" },
{ input: { text: "App crashes" }, output: "bug", comment: "Technical issues" },
],
});Streaming
Stream responses token-by-token using opper.stream():
const outer = await opper.stream({
name: "write_story",
instructions: "Write a short story about the given topic",
input: "a robot learning to paint",
outputSchema: {
type: "object",
properties: {
title: { type: "string" },
story: { type: "string" },
},
required: ["title", "story"],
},
});
// Access the result stream directly
const stream = outer.result;
for await (const event of stream) {
const delta = event.data?.delta;
if (delta) {
process.stdout.write(delta);
}
}Tracing with Spans
Track operations by passing parentSpanId:
// Create a span for grouping related calls
const result = await opper.call({
name: "step_one",
instructions: "First step of the pipeline",
input: "data",
parentSpanId: "123e4567-e89b-12d3-a456-426614174000",
tags: {
project: "my_project",
user: "user_123",
},
});Tags and Metadata
Add metadata for filtering and cost attribution:
const result = await opper.call({
name: "translate",
instructions: "Translate to French",
input: "Hello world",
tags: {
project: "website",
environment: "production",
user_id: "usr_123",
},
});Error Handling
import { Opper } from "opperai";
import * as errors from "opperai/models/errors";
try {
const result = await opper.call({ name: "task", instructions: "...", input: "..." });
} catch (error) {
if (error instanceof errors.OpperError) {
console.error(`Status ${error.statusCode}: ${error.message}`);
if (error instanceof errors.BadRequestError) {
console.error("Details:", error.data$.detail);
}
}
}Common Mistakes
- Missing
httpBearer: The SDK won't authenticate without it. Use environment variableOPPER_HTTP_BEARER. - Forgetting
requiredin schemas: JSON Schema fields are optional by default. Always specifyrequired. - Not awaiting calls: All SDK methods are async. Always
awaitthem.
Additional Resources
- For function CRUD operations and versioning, see references/FUNCTIONS.md
- For knowledge base operations and RAG, see references/KNOWLEDGE.md
- For tracing and span operations, see references/TRACING.md
- For advanced streaming patterns, see references/STREAMING.md
- For migrating from OpenRouter, see references/MIGRATION.md
Related Skills
- opper-node-agents: Use when you need autonomous agents with tool use, reasoning loops, and multi-step execution rather than single-shot task completion.
- opper-python-sdk: Use when building with Python instead of TypeScript.
Upstream Sources
When this skill's content may be outdated, resolve using this priority:
- Installed package source â check the user's project first, as it reflects the exact version in use:
node_modules/opperai/ - Source code: https://github.com/opper-ai/opper-node
- Documentation: https://docs.opper.ai