This page covers the fastest way to develop and test plugins locally. The key insight: use file:// paths and the reload API for instant iteration without reinstalling the plugin.
func (p *MyPlugin) HandlePostAuth(ctx plugin_sdk.Context, req *pb.EnrichedRequest) (*pb.PluginResponse, error) { // Debug logging - shows in AI Studio logs ctx.Services.Logger().Debug("Request details", "method", req.Request.Method, "path", req.Request.Path, "headers", req.Request.Headers, "body_length", len(req.Request.Body), ) // Add more detailed logging during development ctx.Services.Logger().Info("Processing request", "app_id", ctx.AppID, "user_id", ctx.UserID, "runtime", ctx.Runtime, ) return &pb.PluginResponse{Modified: false}, nil}
Check Plugin Status
# Get plugin statuscurl http://localhost:3000/api/v1/plugins/$PLUGIN_ID/status \ -H "Authorization: Bearer $TOKEN" | jq .# List all loaded pluginscurl http://localhost:3000/api/v1/plugins/loaded \ -H "Authorization: Bearer $TOKEN" | jq .
Test Plugin Standalone
Before registering, test your plugin runs:
# This should start and wait for gRPC connection./my-plugin# If it crashes immediately, check for:# - Missing dependencies# - Invalid manifest# - Initialization errors
Symptoms: Reload returns success but changes aren’t reflectedSolutions:
# 1. Verify build succeededgo build -o my-plugin . && echo "Build OK"# 2. Check the binary was actually updatedls -la my-plugin# 3. Verify reload endpoint returned successcurl -X POST .../reload -H "..." | jq .status# 4. Check AI Studio logs for errorstail -100 /path/to/logs | grep -i error
"Permission Denied" on Reload
Symptoms: Reload fails with permission errorSolutions:
# Make binary executablechmod +x my-plugin# Check file ownership (Docker)ls -la my-plugin# May need: chown 1000:1000 my-plugin (for Docker user)
Changes Not Taking Effect
Symptoms: Old behavior persists after reloadSolutions:
# 1. Verify you're building to the right pathwhich my-plugin # vs ./my-plugin# 2. Check plugin command points to your binarycurl http://localhost:3000/api/v1/plugins/$PLUGIN_ID | jq .command# 3. Force deactivate and reactivatecurl -X PATCH .../plugins/$PLUGIN_ID -d '{"is_active": false}'curl -X PATCH .../plugins/$PLUGIN_ID -d '{"is_active": true, "load_immediately": true}'
Manifest Changes Not Applied
Symptoms: New UI components or permissions not appearingSolutions:
# Manifest requires explicit re-parsing after reloadcurl -X POST http://localhost:3000/api/v1/plugins/$PLUGIN_ID/manifest/parse \ -H "Authorization: Bearer $TOKEN"# Or update the plugin entirelycurl -X PATCH http://localhost:3000/api/v1/plugins/$PLUGIN_ID \ -H "Authorization: Bearer $TOKEN" \ -d '{"manifest": {...}}'