rkspace to manage prompts as versioned templates. The core workflow involves defining prompts with typed variables, publishing versions, and invoking them via the SDK with compile-time safety.
Architecture Decision: Wrapper Pattern
While the SDK can be used directly, production systems benefit from a wrapper layer. This abstracts the client initialization, enforces environment-specific configurations, and provides a clean interface for domain services.
Implementation: Dynamic Support Response Generator
We will implement a service that generates customer support responses. This example demonstrates typed variables, version pinning, and integration with the Anthropic API.
1. Define the Prompt Template
In the PromptCache dashboard, create a prompt with the following template. Variables are auto-detected and configured with types and defaults.
Analyze support ticket #{{ticket_id}}.
Category: {{category}}.
Priority Level: {{priority}}.
Customer: {{customer_name}}
Issue Summary: {{issue_summary}}
Draft a response that addresses the core issue.
Maintain a {{tone}} tone.
Limit response to {{max_length}} words.
Variable Schema:
ticket_id: string, Required.
category: enum (billing, technical, general), Required.
priority: number, Required.
customer_name: string, Required.
issue_summary: string, Required.
tone: string, Optional, Default: "empathetic".
max_length: number, Optional, Default: 150.
2. SDK Integration and Type Safety
Install the SDK and create a typed interface that mirrors the prompt schema. This enables IntelliSense and compile-time validation.
npm install @optiqlabs/promptcache-sdk
import { PromptCacheClient } from '@optiqlabs/promptcache-sdk';
import Anthropic from '@anthropic-ai/sdk';
// Define strict interface matching PromptCache variables
interface SupportResponseVars {
ticket_id: string;
category: 'billing' | 'technical' | 'general';
priority: number;
customer_name: string;
issue_summary: string;
tone?: string;
max_length?: number;
}
// Production client wrapper
class PromptService {
private client: PromptCacheClient;
private anthropic: Anthropic;
constructor() {
this.client = new PromptCacheClient({
apiKey: process.env.PROMPTCACHE_READ_KEY!,
baseUrl: 'https://api.promptcache.app',
});
this.anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY!,
});
}
async generateResponse(
promptId: string,
vars: SupportResponseVars,
options?: { version?: string }
): Promise<string> {
// Invoke prompt with typed variables
// SDK validates required fields at compile time
const { rendered } = await this.client.prompts.invoke(promptId, vars, options);
// Send resolved prompt to LLM
const message = await this.anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: rendered }],
});
return message.content[0].text;
}
}
3. Usage and Version Pinning
Invoke the service with specific variables. For critical paths, pin to a version to ensure stability during A/B tests or gradual rollouts.
const promptService = new PromptService();
async function handleSupportTicket() {
const response = await promptService.generateResponse(
'support-responder-v1',
{
ticket_id: 'TK-9921',
category: 'technical',
priority: 2,
customer_name: 'Acme Industries',
issue_summary: 'API rate limiting errors on endpoint /v2/data',
tone: 'urgent',
max_length: 100,
},
{ version: '4' } // Pin to version 4 for audit stability
);
console.log(response);
}
4. Dynamic Variable Injection
For UI-driven workflows, use the getVariables method to identify missing fields. This enables dynamic form generation without hardcoding field lists in the frontend.
const { missingVariables } = await promptService.client.prompts.getVariables('support-responder-v1');
// Returns array of variable names not yet provided
// Use this to render form inputs dynamically
Pitfall Guide
Production adoption of prompt management requires avoiding common implementation errors.
-
The Master Key Anti-Pattern
- Mistake: Using a single API key with full permissions across all services.
- Risk: If a key leaks, attackers can modify or delete prompts across the organization.
- Fix: Use scoped keys. Production services should only use
read-scoped keys. CI/CD pipelines use write keys. Rotate keys regularly via the dashboard.
-
Implicit Type Coercion Failures
- Mistake: Passing loose types to variables expecting strict schemas (e.g., passing
"high" to a number variable).
- Risk: Runtime errors or unexpected prompt rendering.
- Fix: Rely on the TypeScript SDK's type definitions. Validate inputs against the interface before invocation. The SDK will surface type mismatches during development.
-
Version Ambiguity in Production
- Mistake: Always invoking the latest version without pinning.
- Risk: A published prompt change can immediately alter behavior in production, causing regressions without warning.
- Fix: Pin versions for stable features. Use unpinned invocations only for experimental features where rapid iteration is desired. Implement a staging environment to test new versions before promotion.
-
Over-Engineering Variable Granularity
- Mistake: Creating dozens of micro-variables for every word in the prompt.
- Risk: Complex invocation logic, high cognitive load, and difficult maintenance.
- Fix: Group related context. Use variables for semantic blocks (e.g.,
issue_summary rather than issue_type, issue_detail, issue_context). Keep the variable count minimal and meaningful.
-
Ignoring Inject Mode for UX
- Mistake: Hardcoding form fields in the UI instead of querying prompt metadata.
- Risk: UI drifts out of sync with prompt changes. Adding a variable requires frontend code updates.
- Fix: Use
getVariables to drive dynamic forms. This ensures the UI always matches the current prompt schema.
-
Caching Rendered Prompts Incorrectly
- Mistake: Caching the rendered prompt string indefinitely.
- Risk: Stale prompts persist even after updates are published.
- Fix: Cache based on prompt ID and version. Invalidate cache when a new version is published. Use short TTLs if version pinning is not used.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| TypeScript Backend | Use TypeScript SDK | Provides type safety, IntelliSense, and reduced boilerplate. | Lowers development time and reduces runtime errors. |
| Non-TS Backend (Python/Go) | Use REST API | Language-agnostic access to prompt resolution. | Requires manual type validation; higher maintenance overhead. |
| Stable Production Feature | Pin Specific Version | Prevents unexpected behavior changes from prompt updates. | Requires manual promotion for updates; higher operational control. |
| Experimental Feature | Use Latest Version | Enables rapid iteration without code changes. | Risk of regression; requires monitoring. |
| Dynamic UI Forms | Use getVariables | Ensures UI stays in sync with prompt schema. | Reduces frontend maintenance; improves UX consistency. |
Configuration Template
Use this template to standardize prompt service implementation across your codebase.
// src/services/prompt-service.ts
import { PromptCacheClient } from '@optiqlabs/promptcache-sdk';
export class PromptService {
private client: PromptCacheClient;
constructor() {
this.client = new PromptCacheClient({
apiKey: process.env.PROMPTCACHE_API_KEY!,
baseUrl: 'https://api.promptcache.app',
});
}
async invoke<T extends Record<string, any>>(
promptId: string,
variables: T,
options?: { version?: string }
): Promise<string> {
const { rendered } = await this.client.prompts.invoke(promptId, variables, options);
return rendered;
}
async getMissingVariables(promptId: string): Promise<string[]> {
const { missingVariables } = await this.client.prompts.getVariables(promptId);
return missingVariables;
}
}
Quick Start Guide
- Install SDK: Run
npm install @optiqlabs/promptcache-sdk.
- Initialize Client: Create a
PromptCacheClient instance with your scoped API key.
- Invoke Prompt: Call
client.prompts.invoke() with your prompt ID and typed variables.
- Send to LLM: Pass the
rendered string to your LLM provider (e.g., Anthropic, OpenAI).
- Verify: Check the dashboard to confirm version usage and monitor invocation metrics.