Mattermost AI Plugin - LLM Bridge Client¶
Go client library for Mattermost plugins and the server to interact with the AI plugin’s LLM Bridge API.
Quick Start¶
From a Plugin¶
import "github.com/mattermost/mattermost-plugin-ai/public/bridgeclient"
type MyPlugin struct {
plugin.MattermostPlugin
llmClient *bridgeclient.Client
}
func (p *MyPlugin) OnActivate() error {
p.llmClient = bridgeclient.NewClient(p.API)
return nil
}
func (p *MyPlugin) handleCommand() {
// Get the bot ID first (e.g., from discovery or configuration)
botID := "bot-user-id-here"
response, err := p.llmClient.AgentCompletion(botID, bridgeclient.CompletionRequest{
Posts: []bridgeclient.Post{
{Role: "user", Message: "What is the capital of France?"},
},
})
// Handle response...
}
From Mattermost Server¶
import "github.com/mattermost/mattermost-plugin-ai/public/bridgeclient"
type MyService struct {
app *app.App
llmClient *bridgeclient.Client
}
func NewMyService(app *app.App, userID string) *MyService {
return &MyService{
app: app,
llmClient: bridgeclient.NewClientFromApp(app, userID),
}
}
func (s *MyService) process() {
response, err := s.llmClient.ServiceCompletion("anthropic", bridgeclient.CompletionRequest{
Posts: []bridgeclient.Post{
{Role: "user", Message: "Write a haiku"},
},
})
// Handle response...
}
API Methods¶
Non-Streaming¶
// Request by agent Bot ID
response, err := client.AgentCompletion("bot-user-id", request)
// Request by service name
response, err := client.ServiceCompletion("openai", request)
Streaming¶
import "github.com/mattermost/mattermost-plugin-ai/llm"
// Start streaming request (using Bot ID)
result, err := client.AgentCompletionStream("bot-user-id", request)
if err != nil {
return err
}
// Process events
for event := range result.Stream {
switch event.Type {
case llm.EventTypeText:
fmt.Print(event.Value.(string))
case llm.EventTypeError:
return event.Value.(error)
case llm.EventTypeEnd:
return nil
}
}
Multi-turn Conversations¶
request := bridgeclient.CompletionRequest{
Posts: []bridgeclient.Post{
{Role: "system", Message: "You are a helpful assistant"},
{Role: "user", Message: "What is AI?"},
{Role: "assistant", Message: "AI stands for..."},
{Role: "user", Message: "Can you give examples?"},
},
}
Permission Checking¶
By default, the bridge does not check permissions. To enable permission checking, include UserID and optionally ChannelID in your request:
request := bridgeclient.CompletionRequest{
Posts: []bridgeclient.Post{
{Role: "user", Message: "Hello"},
},
UserID: userID, // Checks user-level permissions
ChannelID: channelID, // Also checks channel-level permissions
}
// Returns 403 Forbidden if user lacks permission
response, err := client.AgentCompletion("bot-user-id", request)
If not using built-in permission checks, your plugin must verify permissions before making requests.
Token Usage Dimensions¶
Bridge callers can optionally provide Operation and OperationSubType in CompletionRequest to customize token usage categorization in logs.
If omitted, the bridge keeps current defaults:
Operation:bridge_agentorbridge_service(based on endpoint)OperationSubType:streamingornostream(based on request mode)
request := bridgeclient.CompletionRequest{
Posts: []bridgeclient.Post{
{Role: "user", Message: "Summarize incident timeline"},
},
Operation: "playbooks_summary",
OperationSubType: "incident_report",
}
Agent vs Service¶
Agent: Target a specific bot by its Bot ID (the immutable Mattermost Bot User ID)
Uses bot’s custom configuration, tools, and prompts
Get bot IDs via the
GetAgents()discovery endpoint
Service: Target an LLM service by ID or name (e.g., “openai”, “anthropic”)
Uses any bot configured with that service
Useful when bot-specific configuration doesn’t matter
Discovery Endpoints¶
The bridge API provides discovery endpoints to help clients find available agents and services before making completion requests.
Get Available Agents¶
// Get all agents
agents, err := client.GetAgents("")
if err != nil {
return err
}
for _, agent := range agents {
fmt.Printf("Agent: %s (ID: %s, Username: %s) - Service: %s (%s)\n",
agent.DisplayName, agent.ID, agent.Username, agent.ServiceID, agent.ServiceType)
// Use agent.ID when making completion requests
// response, err := client.AgentCompletion(agent.ID, request)
}
Get Available Services¶
// Get all services
services, err := client.GetServices("")
if err != nil {
return err
}
for _, service := range services {
fmt.Printf("Service: %s (%s) - Type: %s\n",
service.Name, service.ID, service.Type)
}
Discovery with User Permissions¶
Like completion endpoints, discovery endpoints support optional user filtering:
// Get agents accessible to a specific user
agents, err := client.GetAgents(userID)
// Get services accessible to a specific user (via their permitted agents)
services, err := client.GetServices(userID)
This is useful for showing users only the agents and services they have permission to use.