API Reference
SDK Exports
Import from openpets-sdk:
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.
function createPlugin(tools: ToolDefinition[]): { tool: Record<string, any> }Parameters:
tools- Array ofToolDefinitionobjects
Returns: An object with a tool record keyed by tool name.
Example:
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.
function createLazyPlugin(
tools: ToolDefinition[],
options?: CreatePluginOptions
): PluginInstancecreateSingleTool(tool)
Creates a single OpenPets-compatible tool definition.
function createSingleTool(tool: Omit<ToolDefinition, "name">): {
description: string
args: ZodObject<any>
execute: (args: any, context?: any) => Promise<string>
}Example:
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.
function createLogger(namespace: string): LoggerLogger Methods:
debug(message, context?)- Debug levelinfo(message, context?)- Info levelwarn(message, context?)- Warning levelerror(message, context?)- Error level
Example:
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 loggingLOG_LEVEL=debug|info|warn|error- Set log levelDEBUG=true- Enable debug mode
loadEnv(petId)
Loads environment variables for a pet.
function loadEnv(petId?: string): Record<string, string>Load Order:
.pets/config.jsonvalues (furthest directories first, nearest last).envvalues (furthest directories first, nearest last)
loadEnv() does not automatically merge arbitrary process.env values.
Example:
const env = loadEnv("my-pet")
const apiKey = env.MY_PET_API_KEYTypes
ToolDefinition<T>
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.
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:
throw new ToolError({
code: "RATE_LIMITED",
message: "Exceeded API limit",
retryable: true,
retryAfter: 30
})PluginInstance
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
import {
stringField,
optionalString,
numberField,
booleanField,
stringEnum,
withPagination
} from "openpets-sdk"stringField(description)
const schema = z.object({
query: stringField("Search query")
})withPagination(schema)
Adds perPage and page fields:
const schema = withPagination(z.object({
status: z.string()
}))
// Adds: perPage?: number, page?: numberZod Instance
Always use the z export from the SDK:
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
| Type | Example |
|---|---|
| String | z.string() |
| Number | z.number() |
| Boolean | z.boolean() |
| String Array | z.array(z.string()) |
| Number Array | z.array(z.number()) |
| Object | z.object({ key: z.string() }) |
| Enum | z.enum(["a", "b"]) |
| Optional | z.string().optional() |
Not Allowed
z.array(z.object({...}))- Nested objects in arraysz.record()- Record typesz.union()with objects
Cache Utilities
LocalCache<T>
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:
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.
async function withRetry<T>(
operation: () => Promise<T>,
config?: RetryConfig
): Promise<T>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:
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.
async function withRateLimit<T>(
operation: () => Promise<T>,
config?: RateLimitConfig
): Promise<T>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.
function createTestHarness(factory: () => Promise<PluginInstance>): TestHarnessinterface 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:
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.
function createBatchTool<TArgs>(config: BatchToolConfig): ToolDefinitioncreatePaginatedTool(config)
Creates a tool with built-in pagination support (offset, cursor, or link-based).
function createPaginatedTool<TArgs, TItem>(
config: PaginatedToolConfig<TArgs, TItem>
): ToolDefinitiontype PaginationMode = "offset" | "cursor" | "link"createCodeExecutionTool(options)
Creates a sandboxed code execution tool.
function createCodeExecutionTool(options: CreateCodeExecutionToolOptions): ToolDefinitionSessions & Artifacts
useSession(petName, options?)
Creates a session store for maintaining state across tool calls.
function useSession(petName: string, options?: SessionOptions): SessionStoreinterface 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.
function createArtifact(
ref: string,
data: any,
options?: ArtifactOptions
): ArtifactRecordgetArtifact(ref, options?)
Retrieves a stored artifact by reference.
function getArtifact(ref: string, options?: ArtifactOptions): ArtifactRecord | nullAPI Client
BaseAPIClient
Abstract base class for building typed API clients with built-in retry, rate limiting, and connection testing.
abstract class BaseAPIClient {
constructor(config: APIClientConfig)
abstract testConnection(): Promise<ConnectionTestResult>
}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.
function createAPIClientConfig(options: Partial<APIClientConfig> & { baseUrl: string; apiKey: string }): APIClientConfigOAuth
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.
async function startOAuthFlow(
config: OAuthConfig,
options?: OAuthFlowOptions
): Promise<OAuthResult>refreshAndSaveTokens(config)
Refreshes an expired access token using a stored refresh token.
async function refreshAndSaveTokens(config: OAuthConfig): Promise<OAuthResult>getOAuthStatus(config)
Returns the current authentication status for an OAuth-configured pet.
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).
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.
function jsonToToon(data: any, indent?: string): stringformatResponseAsToon(response)
Converts a tool response (string or object) to TOON format.
function formatResponseAsToon(response: any): stringWeb Search
webSearch(query, options?)
Searches the web using configured search providers.
async function webSearch(
query: string,
options?: WebSearchOptions
): Promise<WebSearchResponse>codeSearch(query, options?)
Searches code repositories.
async function codeSearch(
query: string,
options?: CodeSearchOptions
): Promise<CodeSearchResponse>webSearchWithFallback(query, options?)
Web search with automatic fallback between providers.
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.
function isReadOnly(petId: string): booleanfilterToolsForReadOnly(tools, writePatterns, readOnly, logger?)
Filters out write tools when read-only mode is active.
function filterToolsForReadOnly(
tools: ToolDefinition[],
writePatterns: string[],
readOnly: boolean,
logger?: Logger
): ToolDefinition[]Example:
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.
function loadPrompts(petName: string, options?: LoadPromptsOptions): PetPrompt[]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.
function validateProviders(packageJson: any, pluginDir: string): ProviderValidationReportEnvironment & Config
getEnv(key, petId?)
Gets a single environment variable value.
function getEnv(key: string, petId?: string): string | undefinedsetEnv(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>.
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.
function getConfig<T>(petId: string, key: string, fallback?: T, projectDir?: string): T | undefinedsyncEnvToConfig(projectDir?)
Migrates .env variables to pets.json format.