Skip to content

Best Practices

Guidelines for creating and maintaining high-quality pets.

Pet Development

1. Always Include a Health Check

Every pet should have a {pet-name}-test-connection tool:

typescript
{
  name: "my-pet-test-connection",
  description: "Test connection and return status",
  schema: z.object({}),
  async execute() {
    try {
      const result = await testApiConnection()
      return JSON.stringify({
        success: true,
        status: "connected",
        message: "Connected successfully"
      }, null, 2)
    } catch (error) {
      return JSON.stringify({
        success: false,
        status: "error",
        message: error.message
      }, null, 2)
    }
  }
}

2. Graceful Degradation

Return a limited toolset when not fully configured:

typescript
export const MyPet = async () => {
  const env = loadEnv("my-pet")
  
  if (!env.API_KEY) {
    return createPlugin([
      // Only return test-connection tool
      testConnectionTool
    ])
  }
  
  // Return full toolset when configured
  return createPlugin(allTools)
}

3. Consistent Error Handling

Always return structured JSON errors:

typescript
try {
  const result = await apiCall()
  return JSON.stringify({ success: true, data: result }, null, 2)
} catch (error) {
  return JSON.stringify({ 
    success: false, 
    error: error.message,
    code: error.code 
  }, null, 2)
}

4. Use the SDK Utilities

Import from openpets-sdk, not direct dependencies:

typescript
// Good
import { z, createPlugin, createLogger, loadEnv } from "openpets-sdk"

// Avoid
import { z } from "zod"

Schema Design

Allowed Types

Only use these Zod types:

  • z.string()
  • z.number()
  • z.boolean()
  • z.array(z.string())
  • z.array(z.number())
  • z.object({ field: z.string() })
  • z.enum(["value1", "value2"])

Complex Data Workaround

For complex nested data, use JSON strings:

typescript
schema: z.object({
  filtersJson: z.string().describe("JSON string of filter options")
}),
execute(args) {
  const filters = JSON.parse(args.filtersJson)
}

Naming Conventions

Tool Names

Use kebab-case with pet prefix:

  • jira-list-issues
  • jira-get-issue
  • jira-create-issue

Environment Variables

Use SCREAMING_SNAKE_CASE with pet prefix:

  • JIRA_API_KEY
  • JIRA_BASE_URL

Documentation

Required Documentation

  1. README.md with:

    • What the pet does
    • Setup instructions
    • Example queries
    • Environment variables
  2. package.json with:

    • queries array with example prompts
    • scenarios for workflow testing
    • faq for common questions

Testing

Before Publishing

  1. Run pets validate
  2. Start the pet locally: pets run my-pet
  3. Verify connectivity with the OpenPets harness: bun test:pet my-pet --query "test connection"
  4. Test all tools manually
  5. Run scenarios if defined

Next Steps