Availability
| Edition | Deployment Type |
|---|---|
| Community & Enterprise | Self-Managed, Hybrid |
Context.Services interface.
Overview
Service API access is available to all plugins using the unified SDK (pkg/plugin_sdk), with different capabilities depending on the runtime:
Universal Services (Both Runtimes)
- KV Storage: Key-value storage (PostgreSQL in Studio, local DB in Gateway)
- Logger: Structured logging
Runtime-Specific Services
- Gateway Services: App management, LLM info, budget status, credential validation
- Studio Services: Full management API (LLMs, tools, apps, filters, tags, CallLLM)
Access Pattern
All services are accessed through theContext.Services interface provided to your plugin handlers:
Expandable
Initialization and Connection Warmup
For Service API access in AI Studio, plugins use a session-based broker pattern. The SDK handles most of the setup automatically, but there’s a critical pattern you must follow for reliable Service API access.The Connection Warmup Pattern
Critical: 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 service dials first will succeed, and the connection is shared between them. To ensure reliable Service API access, implementSessionAware and warm up the connection in OnSessionReady:
Expandable
Why Warmup Is Required
Without the warmup pattern, 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:- The broker connection is time-sensitive and must be established early
- Dialing late (during an RPC call from the UI) may fail if timing is off
- Event subscriptions and Service API calls share the same underlying connection
Legacy Pattern (Still Supported)
The older pattern of extracting the broker ID manually duringInitialize still works but is not recommended:
Expandable
OpenSession. You only need to implement SessionAware and warm up the connection.
Universal Services
These services are available in both Studio and Gateway runtimes.KV Storage
Key-value storage for plugin data:- Studio: PostgreSQL-backed, shared across hosts, durable
- Gateway: Local database, per-instance, ephemeral
Write Data
Read Data
Delete Data
List Keys
Logger
Structured logging with key-value pairs:Expandable
Event Service
The Event Service enables plugins to publish and subscribe to events using the Event Bridge system. This allows plugins to communicate across the distributed architecture (edge ↔ control) using a pub/sub pattern. Key Features:- Publish events to the local event bus
- Subscribe to events by topic or all events
- Events can flow across the hub-spoke architecture based on direction
- Automatic cleanup of subscriptions when plugin disconnects
Event Directions
Events have a direction that controls routing:| Direction | Constant | Description |
|---|---|---|
| Local | plugin_sdk.DirLocal | Stays on local bus only, never forwarded |
| Up | plugin_sdk.DirUp | Flows from edge (Edge Gateway) to control (AI Studio) |
| Down | plugin_sdk.DirDown | Flows from control (AI Studio) to edge(s) |
Publish Event
Publish an event with a JSON-serializable payload:Expandable
Publish Raw Event
Publish an event with pre-serialized JSON payload (avoids double-serialization):Subscribe to Events
Subscribe to events on a specific topic:Expandable
Subscribe to All Events
Subscribe to all events regardless of topic:Unsubscribe
Remove a subscription:Shutdown().
Event Structure
Events have the following fields:Complete Example: Event-Driven Cache Invalidation
Expandable
Event Service Best Practices
-
Use Appropriate Directions:
DirLocalfor metrics and debugging within a single nodeDirUpfor edge plugins sending data to controlDirDownfor control pushing updates to edges
- Handle Payload Parsing Errors: Always validate and handle JSON unmarshaling errors in event handlers.
- Avoid Blocking in Handlers: Event handlers should be fast. For heavy processing, spawn a goroutine or queue work.
-
Clean Up Subscriptions: Unsubscribe in
Shutdown()for explicit cleanup. -
Use Meaningful Topics: Use dot-separated topic names for clarity (e.g.,
cache.invalidate,config.updated,metrics.report). - Include Context in Payloads: Add timestamps, correlation IDs, or source info to payloads for debugging.
System CRUD Events
AI Studio emits built-in system events when core objects are created, updated, or deleted. These events are published to the local event bus (control-plane only) and can be subscribed to by any plugin.Available System Events
| Topic | Object Type | Action | Description |
|---|---|---|---|
system.llm.created | LLM | created | Emitted when an LLM is created |
system.llm.updated | LLM | updated | Emitted when an LLM is updated |
system.llm.deleted | LLM | deleted | Emitted when an LLM is deleted |
system.app.created | App | created | Emitted when an App is created |
system.app.updated | App | updated | Emitted when an App is updated |
system.app.deleted | App | deleted | Emitted when an App is deleted |
system.app.approved | App | approved | Emitted when an App’s credential is activated |
system.datasource.created | Datasource | created | Emitted when a Datasource is created |
system.datasource.updated | Datasource | updated | Emitted when a Datasource is updated |
system.datasource.deleted | Datasource | deleted | Emitted when a Datasource is deleted |
system.user.created | User | created | Emitted when a User is created |
system.user.updated | User | updated | Emitted when a User is updated |
system.user.deleted | User | deleted | Emitted when a User is deleted |
system.group.created | Group | created | Emitted when a Group is created |
system.group.updated | Group | updated | Emitted when a Group is updated |
system.group.deleted | Group | deleted | Emitted when a Group is deleted |
system.tool.created | Tool | created | Emitted when a Tool is created |
system.tool.updated | Tool | updated | Emitted when a Tool is updated |
system.tool.deleted | Tool | deleted | Emitted when a Tool is deleted |
Event Payload Structure
All system CRUD events use a consistent payload structure:Subscribing to System Events
Expandable
Example: Audit Log Plugin
Expandable
DirLocal direction, meaning they stay on the control plane and are not forwarded to edge instances.
Studio Services
Available whenctx.Runtime == plugin_sdk.RuntimeStudio.
LLM Operations
Requires:llms.read, llms.write, or llms.proxy scope
List LLMs
Expandable
Get LLM
Call LLM (Streaming)
Requires:llms.proxy scope
Expandable
Call LLM (Simple)
Convenience method for simple calls:Get LLMs Count
examples/plugins/studio/service-api-test/.
Gateway Services
Available whenctx.Runtime == plugin_sdk.RuntimeGateway.
Gateway Services provide read-only access to essential gateway information.
Get App
*gwmgmt.GetAppResponse.
Example:
List Apps
*gwmgmt.ListAppsResponse.
Get LLM
*gwmgmt.GetLLMResponse.
List LLMs
*gwmgmt.ListLLMsResponse.
Get Budget Status
*gwmgmt.GetBudgetStatusResponse.
Example:
Expandable
Get Model Price
*gwmgmt.GetModelPriceResponse.
Validate Credential
*gwmgmt.ValidateCredentialResponse.
Example:
Tool Operations (Studio Only)
Requires:tools.read, tools.write, or tools.execute scope
List Tools
Get Tool by ID
Execute Tool
Requires:tools.execute scope
Plugin Operations
Requires:plugins.read or plugins.write scope
List Plugins
Get Plugin by ID
Get Plugins Count
App Operations
Requires:apps.read or apps.write scope
List Apps
List Apps with Filters
ListAppsOptions supports filtering by:
IsActive *bool— Filter by active/inactive statusNamespace string— Filter by namespace (empty = all namespaces)UserID *uint32— Filter by owner user ID
ListApps(ctx, page, limit) function is still available for backward compatibility and returns all apps without filtering.
Get App by ID
Patch App Metadata
UpdateAppWithMetadata for concurrent modifications since it uses database-level transactions with row locking.
Set a metadata key (value must be JSON-encoded):
apps.write scope.
KV Storage Operations
Requires:kv.read or kv.readwrite scope
Write Data
true if created, false if updated. Pass nil for expireAt for no expiration.
Example:
Expandable
Write Data with TTL
Read Data
Delete Data
List Keys
Data Types
LLMMessage
LLMTool (for tool calling)
Tool
Plugin
App
Error Handling
Service API calls return standard Go errors:- Permission denied: Missing required scope
- Not found: Resource doesn’t exist
- Invalid argument: Bad request parameters
- Unavailable: Service not ready
Rate Limiting
Service API calls are subject to rate limiting:- Default: 1000 requests/minute per plugin
- Configurable via platform settings
- Implement exponential backoff for retries
Expandable
Context and Timeouts
Always use contexts with timeouts:Best Practices
-
Check SDK Initialization:
-
Handle Pagination:
Expandable
-
Cache Results:
-
Error Logging:
Scope Requirements Summary
| Operation | Required Scope |
|---|---|
| ListLLMs, GetLLM | llms.read |
| CallLLM | llms.proxy |
| CreateLLM, UpdateLLM | llms.write |
| ListTools, GetTool | tools.read |
| ExecuteTool | tools.execute |
| CreateTool, UpdateTool | tools.write |
| ListApps, ListAppsWithFilters, GetApp | apps.read |
| CreateApp, UpdateApp, PatchAppMetadata | apps.write |
| ListPlugins, GetPlugin | plugins.read |
| ReadPluginKV, ListPluginKVKeys | kv.read |
| WritePluginKV, DeletePluginKV | kv.readwrite |
| ListDatasources, GetDatasource | datasources.read |
| CreateDatasource, UpdateDatasource, DeleteDatasource | datasources.write |
| GenerateEmbedding, StoreDocuments, ProcessAndStoreDocuments | datasources.embeddings |
| QueryDatasource, QueryDatasourceByVector | datasources.query |
| CreateSchedule, GetSchedule, ListSchedules, UpdateSchedule, DeleteSchedule | scheduler.manage |
RAG & Embedding Services
AI Studio provides comprehensive RAG (Retrieval-Augmented Generation) capabilities through the Service API, enabling plugins to build custom document ingestion and semantic search workflows.Overview
The RAG Service APIs allow plugins to:- Generate embeddings using configured embedders (OpenAI, Ollama, Vertex, etc.)
- Store pre-computed embeddings with custom chunking strategies
- Query vector stores with semantic search
- Build complex ingestion plugins (GitHub, Confluence, custom document processors)
Core RAG APIs
GenerateEmbedding
Generate embeddings for text chunks without storing them.Expandable
datasources.embeddings
Use Case: Custom chunking workflows where you generate embeddings first, then decide what to store.
StoreDocuments
Store pre-computed embeddings in the vector store without regenerating them.Expandable
datasources.embeddings
Use Case: Complete control over embeddings - use custom models, external services, or cached embeddings.
Supported Vector Stores:
- ✅ Pinecone
- ✅ PGVector
- ✅ Chroma (v0.2.5+)
- ✅ Weaviate
- ⚠️ Qdrant (requires SDK installation)
- ⚠️ Redis (requires RediSearch configuration)
ProcessAndStoreDocuments
Convenience method that generates embeddings and stores in one step.Expandable
datasources.embeddings
Use Case: Simplified workflow when you don’t need to inspect or cache embeddings.
QueryDatasource
Semantic search using a text query (embedding generated automatically).Expandable
datasources.query
Use Case: Standard semantic search - plugin provides text, system handles embedding.
QueryDatasourceByVector
Semantic search using a pre-computed embedding vector.Expandable
datasources.query
Use Case: Advanced workflows with custom query embeddings or hybrid search strategies.
Supported Vector Stores:
- ✅ Pinecone
- ✅ PGVector
- ✅ Chroma
- ✅ Weaviate
- ⚠️ Qdrant (requires SDK)
- ⚠️ Redis (requires RediSearch)
Complete Custom Ingestion Example
Building a GitHub repository documentation ingestion plugin:Expandable
Datasource Configuration
For RAG APIs to work, datasources must be configured with: Embedder Configuration:EmbedVendor: Embedder provider ("openai","ollama","vertex","googleai")EmbedModel: Model name (e.g.,"text-embedding-3-small"for OpenAI,"nomic-embed-text"for Ollama)EmbedAPIKey: API key if required by embedderEmbedUrl: Embedder endpoint URL
DBSourceType: Vector store type ("pinecone","chroma","pgvector","qdrant","redis","weaviate")DBConnString: Connection URL for vector storeDBConnAPIKey: API key if requiredDBName: Collection/namespace/table name
EmbedModel must be the actual model name (e.g., "text-embedding-3-small"), NOT the vendor name!
RAG Workflow Patterns
Pattern 1: Separate Generate & Store (Full Control)
Pattern 2: Process & Store (Convenience)
Pattern 3: Hybrid Search
Datasource Management APIs
For managing datasources programmatically:Expandable
datasources.read (list/get/search), datasources.write (create/update/delete)
Error Handling
Expandable
"datasource does not have embedder configured"- Set EmbedVendor/EmbedModel/EmbedAPIKey"datasource does not have vector store configured"- Set DBSourceType/DBConnString/DBName"failed to generate embeddings with openai/openai"- EmbedModel should be model name, not vendor!"vector store connection failed"- Ensure vector store is running and accessible
Advanced Datasource Operations
These operations provide fine-grained control over vector store data through metadata filtering and namespace management.Delete Documents by Metadata
Delete specific documents from vector stores using metadata filters:Expandable
metadataFilter: map of metadata key-value pairs to matchfilterMode:"AND"(all conditions must match) or"OR"(any condition matches)dryRun: iftrue, returns count without deleting
datasources.write
Query by Metadata Only
Query documents using only metadata filters (no vector similarity):Expandable
metadataFilter: metadata key-value pairs to matchfilterMode:"AND"or"OR"limit: max results per page (1-100, default: 10)offset: pagination offset
datasources.query
List Namespaces
List all namespaces/collections in a vector store:datasources.read
Note: Document count may be -1 if not supported by the vector store.
Delete Namespace
Delete an entire namespace/collection (bulk operation):namespace: namespace/collection name to deleteconfirm: must betrueto proceed (safety check)
datasources.write
Warning: This is a destructive operation that deletes all documents in the namespace. Use with caution.
Supported Vector Stores:
- ✅ Full support: Chroma, PGVector, Pinecone, Weaviate
- ⚠️ Limited: Redis (delete/query by metadata not fully supported)
- ⚠️ Partial: Qdrant (namespace management only)
Schedule Management
Scope Required:scheduler.manage
Available in: AI Studio only
Plugins can programmatically manage their scheduled tasks using the Schedule Management API. This complements manifest-based schedule declarations.
Overview
Schedules can be created in two ways:- Manifest Schedules: Declared in
plugin.manifest.json, auto-registered when plugin loads - API Schedules: Created programmatically via SDK during
Initialize()or at runtime
ExecuteScheduledTask() capability method.
CreateSchedule
Create a new schedule for your plugin:*mgmtpb.ScheduleInfo with schedule details
Errors: AlreadyExists if schedule_id already exists for this plugin
GetSchedule
Retrieve schedule details by manifest schedule ID:*mgmtpb.ScheduleInfo
Errors: NotFound if schedule doesn’t exist
ListSchedules
Get all schedules for your plugin:[]*mgmtpb.ScheduleInfo array
UpdateSchedule
Update schedule fields (all fields optional):*mgmtpb.ScheduleInfo with updated schedule
Errors: NotFound if schedule doesn’t exist
DeleteSchedule
Remove a schedule:NotFound if schedule doesn’t exist
Complete Example
Expandable
Manifest vs API Schedules
Use Manifest When:- Schedule is core to plugin functionality
- Configuration is static
- Want schedules registered automatically
- Schedules are dynamic (based on external data)
- Need runtime modification
- Want conditional schedule creation
- Building schedule management UI
Best Practices Summary
- Connection Warmup: Implement
SessionAwareand warm up Service API inOnSessionReady- this is critical for reliable API access - Runtime Detection: Always check
ctx.Runtimebefore calling runtime-specific services - Type Assertions: Gateway and Studio services return
interface{}, type assert to correct response types - Error Handling: Always check errors from Service API calls
- Logging: Use
ctx.Services.Logger()for consistent structured logging - KV Storage: Understand storage differences between Studio (durable) and Gateway (ephemeral)
- Shared Connections: Event Service and Management Service API share the same broker connection - one warmup establishes both
- Context Timeouts: Use context timeouts for external calls
- Caching: Cache frequently accessed data in KV storage to reduce API calls
Complete Examples
For complete working examples of Service API usage:- Studio:
examples/plugins/studio/service-api-test/- Comprehensive Studio Services testing - Gateway:
examples/plugins/gateway/gateway-service-test/- Gateway Services examples - Rate Limiter:
examples/plugins/studio/llm-rate-limiter-multiphase/- Multi-capability plugin with KV storage - Scheduler:
examples/plugins/studio/scheduler-demo/- Scheduled tasks with manifest and API patterns