Skip to content

API Reference ​

SDK Exports ​

Import from openpets-sdk:

typescript
import {
  // Core
  z,
  createPlugin,
  createLazyPlugin,
  createSingleTool,
  createLogger,
  loadEnv,
  getEnv,
  setEnv,
  clearEnv,
  getConfig,
  getPetsConfig,
  syncEnvToConfig,

  // Read-Only Mode
  isReadOnly,
  setReadOnly,
  getReadOnlyStatus,
  filterToolsForReadOnly,

  // Error Handling
  ToolError,

  // Retry & Rate Limiting
  withRetry,
  withRateLimit,

  // Caching
  LocalCache,
  SingleValueCache,
  withCache,
  createCache,

  // Testing
  createTestHarness,

  // Advanced Tools
  createBatchTool,
  createPaginatedTool,
  createCodeExecutionTool,

  // Sessions & Artifacts
  useSession,
  createArtifact,
  getArtifact,

  // API Client
  BaseAPIClient,
  createAPIClientConfig,

  // Web Search
  webSearch,
  codeSearch,
  webSearchWithFallback,
  ExaProvider,

  // OAuth
  startOAuthFlow,
  refreshAndSaveTokens,
  getOAuthStatus,
  createOAuthTools,

  // TOON Format
  jsonToToon,
  formatResponseAsToon,

  // Prompts
  loadPrompts,
  ensurePromptsFolder,

  // Interceptors
  createLoggingInterceptor,
  createTimingInterceptor,
  createRedactionInterceptor,

  // Provider Validation
  validateProviders,

  // Schema Helpers
  stringField,
  optionalString,
  numberField,
  booleanField,
  stringEnum,
  withPagination,

  // Kennel (Pet Management)
  createKennel,
  discoverPets,
  loadPetConfig,
  savePetConfig,
  setEnvForPet,

  // Types
  type ToolDefinition,
  type ToolErrorCode,
  type ToolRecord,
  type PluginInstance,
  type CreatePluginOptions,
  type RetryConfig,
  type RateLimitConfig,
  type OAuthConfig,
  type APIClientConfig,
  type TestHarness,
  type SessionStore,
  type ArtifactRecord,
  type PetPrompt
} from "openpets-sdk"

Core Functions ​

createPlugin(tools) ​

Creates a multi-tool plugin from an array of tool definitions.

typescript
function createPlugin(tools: ToolDefinition[]): { tool: Record<string, any> }

Parameters:

  • tools - Array of ToolDefinition objects

Returns: An object with a tool record keyed by tool name.

Example:

typescript
const tools: ToolDefinition[] = [
  {
    name: "my-pet-list-items",
    description: "List all items",
    schema: z.object({}),
    execute: async () => JSON.stringify({ items: [] })
  }
]

return createPlugin(tools)

createLazyPlugin(tools, options?) ​

Creates a plugin where tool execute functions are only initialized when first called. Useful for pets with many tools to reduce startup time.

typescript
function createLazyPlugin(
  tools: ToolDefinition[],
  options?: CreatePluginOptions
): PluginInstance

createSingleTool(tool) ​

Creates a single OpenPets-compatible tool definition.

typescript
function createSingleTool(tool: Omit<ToolDefinition, "name">): {
  description: string
  args: ZodObject<any>
  execute: (args: any, context?: any) => Promise<string>
}

Example:

typescript
return createSingleTool({
  description: "Does one thing",
  schema: z.object({ input: z.string() }),
  execute: async (args) => args.input.toUpperCase()
})

createLogger(namespace) ​

Creates a namespaced logger instance.

typescript
function createLogger(namespace: string): Logger

Logger Methods:

  • debug(message, context?) - Debug level
  • info(message, context?) - Info level
  • warn(message, context?) - Warning level
  • error(message, context?) - Error level

Example:

typescript
const logger = createLogger("my-pet")
logger.info("Starting up", { version: "1.0.0" })
logger.error("Failed to connect", { error: err.message })

Environment Variables:

  • ENABLE_LOGGING=true - Enable logging
  • LOG_LEVEL=debug|info|warn|error - Set log level
  • DEBUG=true - Enable debug mode

loadEnv(petId) ​

Loads environment variables for a pet.

typescript
function loadEnv(petId?: string): Record<string, string>

Load Order:

  1. .pets/config.json values (furthest directories first, nearest last)
  2. .env values (furthest directories first, nearest last)

loadEnv() does not automatically merge arbitrary process.env values.

Example:

typescript
const env = loadEnv("my-pet")
const apiKey = env.MY_PET_API_KEY

Types ​

ToolDefinition<T> ​

typescript
interface ToolDefinition<T extends Record<string, any> = any> {
  name: string
  description: string
  schema: z.ZodObject<any>
  execute: (args: T) => Promise<string>
  deprecated?: ToolDeprecation
  hints?: ToolHints
  search?: ToolSearchMetadata
  cache?: ToolCacheConfig
  coreFields?: CoreFieldsSpec
  stream?: (args: T) => AsyncIterable<string>
}

ToolError ​

Structured error class for classifiable tool failures.

typescript
class ToolError extends Error {
  code: ToolErrorCode
  retryable: boolean
  retryAfter?: number
  statusCode?: number
}

type ToolErrorCode =
  | "RATE_LIMITED"
  | "NOT_FOUND"
  | "UNAUTHORIZED"
  | "FORBIDDEN"
  | "TIMEOUT"
  | "VALIDATION_ERROR"
  | "UPSTREAM_ERROR"
  | "NOT_CONFIGURED"

Example:

typescript
throw new ToolError({
  code: "RATE_LIMITED",
  message: "Exceeded API limit",
  retryable: true,
  retryAfter: 30
})

PluginInstance ​

typescript
interface PluginInstance {
  tool: ToolRecord
}

type ToolRecord = Record<string, {
  description: string
  args: z.ZodObject<any>
  execute: (args: any, context?: any) => Promise<string>
}>

Schema Helpers ​

Available Helpers ​

typescript
import {
  stringField,
  optionalString,
  numberField,
  booleanField,
  stringEnum,
  withPagination
} from "openpets-sdk"

stringField(description) ​

typescript
const schema = z.object({
  query: stringField("Search query")
})

withPagination(schema) ​

Adds perPage and page fields:

typescript
const schema = withPagination(z.object({
  status: z.string()
}))
// Adds: perPage?: number, page?: number

Zod Instance ​

Always use the z export from the SDK:

typescript
import { z } from "openpets-sdk"

const schema = z.object({
  name: z.string(),
  count: z.number().optional(),
  type: z.enum(["a", "b", "c"])
})

Allowed Schema Types ​

TypeExample
Stringz.string()
Numberz.number()
Booleanz.boolean()
String Arrayz.array(z.string())
Number Arrayz.array(z.number())
Objectz.object({ key: z.string() })
Enumz.enum(["a", "b"])
Optionalz.string().optional()

Not Allowed ​

  • z.array(z.object({...})) - Nested objects in arrays
  • z.record() - Record types
  • z.union() with objects

Cache Utilities ​

LocalCache<T> ​

typescript
import { LocalCache } from "openpets-sdk"

const cache = new LocalCache<MyData>({
  ttl: 60000,  // 1 minute
  maxSize: 100
})

cache.set("key", data)
const value = cache.get("key")
cache.delete("key")
cache.clear()

withCache(cache, key, fetcher) ​

Reads from cache and falls back to fetcher() when needed:

typescript
const cache = new LocalCache<any>({ ttl: 30000 })
const data = await withCache(cache, "users:list", async () => {
  return fetch("https://api.example.com/users").then(r => r.json())
})

Retry & Rate Limiting ​

withRetry(operation, config?) ​

Retries an async operation with exponential backoff and jitter.

typescript
async function withRetry<T>(
  operation: () => Promise<T>,
  config?: RetryConfig
): Promise<T>
typescript
interface RetryConfig {
  maxRetries?: number          // default: 3
  baseDelayMs?: number         // default: 500
  maxDelayMs?: number          // default: 10000
  jitterMs?: number | { min: number; max: number }
  retryableErrorCodes?: ToolErrorCode[]
  retryableStatusCodes?: number[]
  shouldRetry?: (error: unknown) => boolean
  onRetry?: (event: RetryEvent) => void
}

Example:

typescript
const data = await withRetry(() => fetchAPI("/users"), {
  maxRetries: 5,
  baseDelayMs: 1000
})

withRateLimit(operation, config?) ​

Wraps an operation with rate-limit awareness and automatic retry on 429 responses.

typescript
async function withRateLimit<T>(
  operation: () => Promise<T>,
  config?: RateLimitConfig
): Promise<T>
typescript
interface RateLimitConfig extends RetryConfig {
  key?: string
  getRetryAfter?: (error: unknown) => number | undefined
}

Testing ​

createTestHarness(factory) ​

Creates a test harness for unit testing pet plugins without real API calls.

typescript
function createTestHarness(factory: () => Promise<PluginInstance>): TestHarness
typescript
interface TestHarness {
  setEnv: (vars: Record<string, string>) => void
  mockFetch: (url: string, response: MockFetchResponse) => void
  clearFetchMocks: () => void
  listTools: () => Promise<string[]>
  executeTool: (name: string, args?: Record<string, any>) => Promise<any>
  validateSchemas: () => Promise<SchemaValidationResult>
  reset: () => void
  dispose: () => void
}

Example:

typescript
const harness = createTestHarness(MyPlugin)
harness.setEnv({ MY_API_KEY: "test-key" })
harness.mockFetch("https://api.example.com/users", { users: [] })

const tools = await harness.listTools()
const result = await harness.executeTool("my-pet-list-users")

harness.dispose()

Advanced Tool Builders ​

createBatchTool(config) ​

Creates a tool that processes multiple items in a single invocation.

typescript
function createBatchTool<TArgs>(config: BatchToolConfig): ToolDefinition

createPaginatedTool(config) ​

Creates a tool with built-in pagination support (offset, cursor, or link-based).

typescript
function createPaginatedTool<TArgs, TItem>(
  config: PaginatedToolConfig<TArgs, TItem>
): ToolDefinition
typescript
type PaginationMode = "offset" | "cursor" | "link"

createCodeExecutionTool(options) ​

Creates a sandboxed code execution tool.

typescript
function createCodeExecutionTool(options: CreateCodeExecutionToolOptions): ToolDefinition

Sessions & Artifacts ​

useSession(petName, options?) ​

Creates a session store for maintaining state across tool calls.

typescript
function useSession(petName: string, options?: SessionOptions): SessionStore
typescript
interface SessionStore {
  get: (key: string) => any
  set: (key: string, value: any) => void
  delete: (key: string) => boolean
  clear: () => void
  keys: () => string[]
  has: (key: string) => boolean
}

createArtifact(ref, data, options?) ​

Stores an artifact (large result, file, etc.) for later retrieval.

typescript
function createArtifact(
  ref: string,
  data: any,
  options?: ArtifactOptions
): ArtifactRecord

getArtifact(ref, options?) ​

Retrieves a stored artifact by reference.

typescript
function getArtifact(ref: string, options?: ArtifactOptions): ArtifactRecord | null

API Client ​

BaseAPIClient ​

Abstract base class for building typed API clients with built-in retry, rate limiting, and connection testing.

typescript
abstract class BaseAPIClient {
  constructor(config: APIClientConfig)
  abstract testConnection(): Promise<ConnectionTestResult>
}
typescript
interface APIClientConfig {
  baseUrl: string
  apiKey: string
  timeout?: number    // default: 30000
  retries?: number    // default: 3
  debug?: boolean
  headers?: Record<string, string>
}

createAPIClientConfig(options) ​

Factory for creating APIClientConfig with defaults applied.

typescript
function createAPIClientConfig(options: Partial<APIClientConfig> & { baseUrl: string; apiKey: string }): APIClientConfig

OAuth ​

startOAuthFlow(config, options?) ​

Runs a complete OAuth 2.0 authorization code flow: starts a local callback server, opens the browser, exchanges the code for tokens, and saves them to pets.json.

typescript
async function startOAuthFlow(
  config: OAuthConfig,
  options?: OAuthFlowOptions
): Promise<OAuthResult>

refreshAndSaveTokens(config) ​

Refreshes an expired access token using a stored refresh token.

typescript
async function refreshAndSaveTokens(config: OAuthConfig): Promise<OAuthResult>

getOAuthStatus(config) ​

Returns the current authentication status for an OAuth-configured pet.

typescript
function getOAuthStatus(config: OAuthConfig): {
  authenticated: boolean
  hasRefreshToken: boolean
  expiresAt?: number
}

createOAuthTools(config) ​

Creates a set of tools for managing OAuth from within a pet (authenticate, status, refresh, disconnect).

typescript
function createOAuthTools(config: OAuthConfig): ToolDefinition[]

TOON Format ​

Token-optimized output format for LLM consumption (~24% token reduction vs JSON).

jsonToToon(data, indent?) ​

Converts any JSON-serializable value to TOON format.

typescript
function jsonToToon(data: any, indent?: string): string

formatResponseAsToon(response) ​

Converts a tool response (string or object) to TOON format.

typescript
function formatResponseAsToon(response: any): string

webSearch(query, options?) ​

Searches the web using configured search providers.

typescript
async function webSearch(
  query: string,
  options?: WebSearchOptions
): Promise<WebSearchResponse>

codeSearch(query, options?) ​

Searches code repositories.

typescript
async function codeSearch(
  query: string,
  options?: CodeSearchOptions
): Promise<CodeSearchResponse>

webSearchWithFallback(query, options?) ​

Web search with automatic fallback between providers.

typescript
async function webSearchWithFallback(
  query: string,
  options?: WebSearchOptions
): Promise<WebSearchResponse>

Read-Only Mode ​

isReadOnly(petId) ​

Returns true if read-only mode is enabled for the given pet.

typescript
function isReadOnly(petId: string): boolean

filterToolsForReadOnly(tools, writePatterns, readOnly, logger?) ​

Filters out write tools when read-only mode is active.

typescript
function filterToolsForReadOnly(
  tools: ToolDefinition[],
  writePatterns: string[],
  readOnly: boolean,
  logger?: Logger
): ToolDefinition[]

Example:

typescript
const WRITE_PATTERNS = ["create", "update", "delete", "add-", "remove-"]
const tools = filterToolsForReadOnly(allTools, WRITE_PATTERNS, isReadOnly("my-pet"), logger)

Interceptors ​

Interceptors wrap tool executions to add cross-cutting concerns.

createLoggingInterceptor(options?) ​

Logs every tool invocation and result.

createTimingInterceptor(options?) ​

Measures and reports execution time for each tool call.

createRedactionInterceptor(options?) ​

Redacts sensitive values from tool arguments and results before logging.


Prompts ​

loadPrompts(petName, options?) ​

Loads prompt files from a pet's prompts/ directory.

typescript
function loadPrompts(petName: string, options?: LoadPromptsOptions): PetPrompt[]
typescript
interface PetPrompt {
  name: string
  content: string
  when: "always" | "on-demand"
  metadata?: Record<string, any>
}

ensurePromptsFolder() ​

Creates the prompts/ directory structure if it doesn't exist.


Provider Validation ​

validateProviders(packageJson, pluginDir) ​

Validates that a pet's package.json provider declarations match the actual implementation.

typescript
function validateProviders(packageJson: any, pluginDir: string): ProviderValidationReport

Environment & Config ​

getEnv(key, petId?) ​

Gets a single environment variable value.

typescript
function getEnv(key: string, petId?: string): string | undefined

setEnv(key, value, options?) ​

Sets an environment variable in pets.json or .env.

setConfig(petId, configValues, projectDir?) ​

Sets non-secret project configuration values in pets.json under petConfig.<petId>.

typescript
function setConfig(petId: string, configValues: Record<string, unknown>, projectDir?: string): { success: boolean; message: string }

clearEnv(key, options?) ​

Removes an environment variable from the config.

getConfig(petId, key, fallback?, projectDir?) ​

Gets a typed configuration value from pets.json.

typescript
function getConfig<T>(petId: string, key: string, fallback?: T, projectDir?: string): T | undefined

syncEnvToConfig(projectDir?) ​

Migrates .env variables to pets.json format.


Next Steps ​