Skip to main content

Availability

Tyk AI Studio provides a Unified Plugin SDK that works seamlessly in both AI Studio and Edge Gateway contexts with a single API. This guide covers the core SDK concepts, capabilities, and patterns.

Unified SDK Overview

The Unified SDK (pkg/plugin_sdk) is the modern, recommended approach for all plugin development. It provides:
  • Single Import: One SDK works in both AI Studio and Edge Gateway
  • Automatic Runtime Detection: SDK detects the execution environment
  • Capability-Based Design: Implement only what you need
  • Type-Safe: Clean Go types, no manual proto handling
  • Service Access: Built-in KV storage, logging, events, and management APIs
  • Context-Rich: Access to app, user, LLM metadata in every call

Installation

From v2.2.1, the module uses the go 1.26.5 directive with toolchain go1.26.6. Build plugins with Go 1.26.6 or later. If your plugin module uses a replace directive for the AI Studio module, update its go directive to match.
Changes for Go plugin authors in v2.2.1:
  • The gateway plugin interfaces moved to pkg/gatewayplugin (for example github.com/TykTechnologies/midsommar/v2/pkg/gatewayplugin/sdk). The old microgateway/plugins paths forward to the new location.
  • The enterprise module path is now github.com/TykTechnologies/ai-studio-enterprise/v2.
  • The Go StudioServices interface has thirteen new methods. If you wrote a custom fake of this interface for tests, add the new methods. Plugins that you already built continue to work.

Basic Plugin Structure

Expandable

Plugin Capabilities

Plugins implement one or more capability interfaces. The SDK supports 15 distinct capabilities:

Multi-Capability Plugins

A single plugin can implement multiple capabilities. For example, a rate limiter might implement:
  • PostAuthHandler - Check limits before request
  • ResponseHandler - Update counters after response
  • UIProvider - Provide management UI
Expandable

Core Interfaces

1. PreAuthHandler

Process requests before authentication. Useful for IP filtering, request validation, etc.
Example:

2. AuthHandler

Custom authentication with credential lookup. This interface requires three methods to fully integrate with the access control system.

Why App Linking Is Critical

A valid credential alone is not enough. The system requires an associated App object because Apps provide the access control context:
  • Policy enforcement - Rate limits, usage quotas, and restrictions
  • Tool/Datasource permissions - Which tools and datasources the credential can access
  • LLM restrictions - Which LLMs the credential is allowed to use
  • Budget controls - Cost tracking and spending limits
Without a valid App association, authenticated requests will fail even if the credential itself is valid.

Authentication Flow

  1. HandleAuth() - Validates the credential and returns an App ID and User ID
  2. GetAppByCredential() - System calls this to fetch the full App object for access control
  3. GetUserByCredential() - System calls this to fetch the User object for identity context

Example Implementation

Expandable

Delegated Identity

Return Authenticated: true with the AppId that the caller acts as. From v2.2.1, the gateway refuses an authenticated response without a valid AppId. In earlier versions, it used App 1. You can also set these values for audit:
  • UserId: The user that the call is for. For example, the subject of a delegated token.
  • Claims["auth_actor"]: The agent that acts for the user, for example the act or azp claim of the token
The gateway passes them to post-auth plugins and custom endpoints. It also records them as on_behalf_of and acting_agent in the proxy log and chat record. The App and LLM proxy logs show them as For and Agent. They are for audit only. The grants of the App control what the request can reach.

Where Auth Plugins Run

From v2.2.1, every gateway endpoint has an ordered list of auth plugins:
  • When an endpoint has auth plugins, only these plugins authenticate its requests. The gateway asks them in order, and the first plugin that authenticates the request wins. Each plugin that refuses adds its time to the request, so put the plugin that accepts most requests first. If all plugins refuse, the request gets 401 invalid credential. The gateway logs the plugin’s reason, but does not send it to the caller.
  • The endpoint refuses App keys. Studio OAuth access tokens for MCP still work on tools.
  • If none of the attached plugins can load, the request gets 503. The gateway does not fall back to App keys.
  • An endpoint without auth plugins authenticates with App keys, and no auth plugin sees its traffic.
  • Auth plugin lists apply on Edge Gateways only. The embedded gateway in AI Studio does not run gateway auth plugins.

Common Pitfalls

See the working example at examples/plugins/studio/custom-auth-ui/ for a complete implementation.

3. PostAuthHandler

Process requests after authentication. Most common capability for request enrichment, policy enforcement, etc.
Example:
Expandable

4. ResponseHandler

Modify response headers and body. Two methods allow phased processing:
Example:
Expandable

5. DataCollector

Collect telemetry data (analytics, budgets, proxy logs).
Example:
Expandable

6. AgentPlugin

Conversational AI agent with streaming support. See Agent Plugins Guide for details.

7. ObjectHookHandler

Intercept CRUD operations on AI Studio objects (LLMs, Datasources, Tools, Users). See Object Hooks Guide for complete details.
Object types are llm, datasource, tool, user, and (Enterprise Edition, from v2.2.0) governed_metadata. For governed_metadata:
  • The object JSON is the metadata record (object_type, object_id, values, and so on).
  • Only before_update, after_update, before_delete, and after_delete fire.
  • A rejection blocks the metadata save.
  • A modification can change values. AI Studio validates the new values against the schema again.

8. UIProvider

Serve web UI assets for AI Studio plugins. See UI Plugins Guide for details.
To receive the calling administrator on admin RPC calls, also implement UserAwareRPCHandler. The user context includes the RBAC permissions of the caller:
Every plugin with pages or resource types has a row in the role editor (plugin:<manifest id>: read, write, execute). To declare more rows and the permission of each method, use the rbac block of the manifest. To register resources at runtime, use RegisterPermissionResources. Refer to Permissions (RBAC) Block and Permission Resources.

9. ConfigProvider

Provide JSON Schema for plugin configuration.
Example:
Expandable

10. ManifestProvider

Provide plugin manifest for gateway-only plugins (no UI).

11. SchedulerPlugin

Execute tasks on cron-based schedules.
Example:

12. EdgePayloadReceiver

Receive data from edge (Edge Gateway) plugins. This enables the hub-and-spoke communication pattern where edge plugins can send data back to the control plane. See Edge-to-Control Communication for complete details.
Example:
Expandable

Context and Services

Every handler receives a Context that provides access to runtime information and services.

Context Fields

Runtime Detection

Plugins can adapt behavior based on runtime:

Service Broker

The context provides access to services through ctx.Services:

Universal Services (Both Runtimes)

KV Storage:
Note on KV Storage:
  • Studio: PostgreSQL-backed, shared across hosts, durable
  • Gateway: Local database, per-instance, ephemeral
Logging:
Events:
Expandable
Note on Events:
  • Events enable real-time communication between plugins and across the hub-spoke architecture
  • Direction controls routing: DirLocal (stays local), DirUp (edge→control), DirDown (control→edge)
  • See Service API Reference for complete documentation

Runtime-Specific Services

Gateway Services (ctx.Services.Gateway()):
Expandable
Studio Services (ctx.Services.Studio()):
Expandable

Initialization Pattern

Plugins should extract the service broker ID during initialization for Service API access:
Expandable

BasePlugin Convenience Struct

The SDK provides BasePlugin to reduce boilerplate:
Expandable
BasePlugin provides default implementations for common methods, which you can override as needed.

Error Handling

Blocking Requests

Return a response with Block: true:
A blocking plugin can return its own StatusCode, Headers, and Body, for example for a cache hit. The gateway sets Content-Length and Transfer-Encoding from the body that it writes, and ignores the plugin’s values for these headers. It also ignores the connection headers (Connection, Keep-Alive, Trailer, and Upgrade). Set Content-Type to match the body.
In v2.2.0 and earlier, the Edge Gateway copied these framing headers from the plugin response without changes. An incorrect Content-Length gave the client an empty body. v2.2.1 fixes this.

Non-Blocking Errors

Log the error and continue:

Agent Errors

Send ERROR chunks for streaming agents:

Complete Example: Multi-Capability Plugin

Expandable

Testing Plugins

Unit Testing

Expandable

Integration Testing

See working examples in examples/plugins/ for integration test patterns.

Best Practices

Configuration

  • Validate configuration in Initialize()
  • Extract broker ID for Service API access
  • Set sensible defaults
  • Return errors for invalid config

Service API Usage

  • Always check runtime before calling runtime-specific services
  • Use context timeouts for external calls
  • Cache frequently accessed data in KV storage
  • Handle service errors gracefully
  • Use Events for cross-plugin and edge-to-control communication
  • Unsubscribe from events in Shutdown() to prevent leaks

Performance

  • Minimize Service API calls in request path
  • Use KV storage for caching
  • Avoid blocking operations in handlers
  • Use goroutines for async work (clean up in Shutdown)

Resource Management

  • Clean up resources in Shutdown() method
  • Close connections and file handles
  • Cancel background goroutines
  • Clear caches

Security

  • Validate all inputs
  • Sanitize log output (no secrets)
  • Use secure defaults
  • Follow least privilege principle

Session-Based Broker Pattern

Plugins running in AI Studio use a session-based broker pattern for Service API access. Understanding this pattern is critical for plugins that need to call host APIs (like ai_studio_sdk.CreateLLM(), ai_studio_sdk.ListApps(), etc.).

How It Works

  1. Plugin loads: The host creates a long-lived gRPC broker connection
  2. Session opens: The host calls OpenSession on the plugin, providing the broker ID
  3. OnSessionReady callback: For plugins implementing SessionAware, this signals the broker is ready
  4. Service API available: The plugin can now dial the broker and call host APIs

The SessionAware Interface

Plugins that need early access to Service APIs should implement SessionAware:

Connection Warmup Pattern (Critical!)

Important: The go-plugin broker only accepts ONE connection per broker ID. If your plugin uses both the Event Service and the Management Service API, whichever dials first will succeed, and the connection must be shared. The SDK handles this automatically, but you should warm up the connection early in OnSessionReady to ensure it’s established before any RPC calls come in:
Expandable

Why Warmup Is Important

Without warmup, you may encounter “timeout waiting for connection info” errors when your plugin tries to use the Service API during an RPC call. This happens because:
  1. The broker connection is time-sensitive
  2. Dialing late (during RPC) may fail if the broker has timed out
  3. Event subscriptions and Service API calls share the same connection

Complete Example: Plugin with Service API and Events

Expandable

Troubleshooting Connection Issues

Error: “timeout waiting for connection info”
  • Plugin is trying to dial the broker too late
  • Solution: Implement SessionAware and warm up the connection in OnSessionReady
Error: “service broker ID not set”
  • The broker ID wasn’t extracted from config
  • Solution: The SDK handles this automatically via OpenSession, but verify your plugin isn’t overriding the broker setup
Error: “SDK not initialized”
  • ai_studio_sdk.Initialize() wasn’t called or failed
  • Solution: Check logs for initialization errors during plugin startup