* feat: add prometheus monitoring wrapper Reintroduces the Prometheus metrics wrapper previously available in the plugins repository, updated for go-micro v5. Exposes request count and latency histograms for handlers, subscribers, and outgoing client calls via NewHandlerWrapper, NewSubscriberWrapper, NewCallWrapper and NewClientWrapper, labelled with service/endpoint/status. Options cover namespace, subsystem, const labels, histogram buckets and a custom registerer; duplicate collectors (e.g. from multiple wrappers sharing the same config) are reused transparently via a cached metrics bundle. Fixes #2893 * fix(registry/etcd): clear lease/register caches on KeepAlive channel closure When the etcd client's long-lived KeepAlive channel closes (e.g. because the lease expired on the server side during a network partition), the previous cleanup only removed the channel bookkeeping. The stale entries in `leases` and `register` caused the next registerNode() heartbeat to hit the "unchanged hash" short-circuit and skip re-registration entirely, so the service permanently disappeared from etcd. Extract the cleanup into handleKeepAliveClosed and also drop the cached lease id and hash so the next heartbeat performs a full Grant+Put and the service recovers within one RegisterInterval. Regression introduced by #2822; fix is symmetric with the existing synchronous KeepAliveOnce recovery path that propagates rpctypes.ErrLeaseNotFound. * docs: add AI provider integration guide and Supported AI Providers section Add a step-by-step guide for AI infrastructure companies to implement ai.Model and contribute a provider to go-micro. Covers the full lifecycle: skeleton, tool call handling, tests, registration, and PR checklist. Add a "Supported AI Providers" section to the project README that lists current providers (Anthropic, OpenAI) in a table and links to the integration guide with a call-to-action for new providers and sponsors. Streamline the "Adding a New Provider" section in ai/README.md to point to the new guide instead of duplicating a full code listing. * Update contribution guidelines in README.md Removed Discord contact information for platform contributions. --------- Co-authored-by: Claude <noreply@anthropic.com>
AI Package
The ai package provides a simple, high-level interface for AI model providers like Anthropic Claude and OpenAI GPT.
Interface
The Model interface follows the same patterns as other go-micro packages (Registry, Client, Broker):
type Model interface {
Init(...Option) error
Options() Options
Generate(ctx context.Context, req *Request, opts ...GenerateOption) (*Response, error)
Stream(ctx context.Context, req *Request, opts ...GenerateOption) (Stream, error)
String() string
}
Quick Start
import (
"context"
"go-micro.dev/v5/ai"
_ "go-micro.dev/v5/ai/anthropic"
_ "go-micro.dev/v5/ai/openai"
)
// Create a model
m := ai.New("openai",
ai.WithAPIKey("your-api-key"),
ai.WithModel("gpt-4o"),
)
// Generate a response
req := &ai.Request{
Prompt: "What is Go?",
SystemPrompt: "You are a helpful programming assistant",
}
resp, err := m.Generate(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Reply)
Options
Configure the model using functional options:
m := ai.New("anthropic",
ai.WithAPIKey("your-key"), // Required
ai.WithModel("claude-sonnet-4-20250514"), // Optional, uses provider default
ai.WithBaseURL("https://api.anthropic.com"), // Optional, uses provider default
)
You can also update options after creation:
m.Init(
ai.WithModel("gpt-4o-mini"),
ai.WithAPIKey("new-key"),
)
Using Tools
The model can automatically execute tool calls when provided with a tool handler:
// Define a tool handler
toolHandler := func(name string, input map[string]any) (result any, content string) {
// Execute the tool and return results
switch name {
case "get_weather":
return map[string]string{"temp": "72F"}, `{"temp": "72F"}`
default:
return nil, `{"error": "unknown tool"}`
}
}
// Create model with tool handler
m := ai.New("openai",
ai.WithAPIKey("your-key"),
ai.WithToolHandler(toolHandler),
)
// Provide tools in the request
req := &ai.Request{
Prompt: "What's the weather?",
SystemPrompt: "You are a helpful assistant",
Tools: []ai.Tool{
{
Name: "get_weather",
Description: "Get current weather",
Properties: map[string]any{
"location": map[string]any{
"type": "string",
"description": "City name",
},
},
},
},
}
// Generate will automatically call tools and return final answer
resp, err := m.Generate(context.Background(), req)
fmt.Println(resp.Answer) // Final answer after tool execution
Response Structure
type Response struct {
Reply string // Initial reply from model
ToolCalls []ToolCall // Tools the model wants to call
Answer string // Final answer (after tool execution if handler provided)
}
Reply: The model's first responseToolCalls: List of tools the model requested (if any)Answer: The final answer after tools are executed (only set if ToolHandler is provided)
Supported Providers
Anthropic Claude
m := ai.New("anthropic",
ai.WithAPIKey("sk-ant-..."),
ai.WithModel("claude-sonnet-4-20250514"), // default
)
Default model: claude-sonnet-4-20250514
Default base URL: https://api.anthropic.com
OpenAI GPT
m := ai.New("openai",
ai.WithAPIKey("sk-..."),
ai.WithModel("gpt-4o"), // default
)
Default model: gpt-4o
Default base URL: https://api.openai.com
Auto-Detection
Use AutoDetectProvider() to detect the provider from a base URL:
provider := ai.AutoDetectProvider("https://api.anthropic.com")
// Returns "anthropic"
m := ai.New(provider, ai.WithAPIKey("..."))
Adding a New Provider
See the full AI Provider Integration Guide for a step-by-step walkthrough, checklist, and design notes.
Quick summary:
- Create
ai/yourprovider/yourprovider.goimplementingai.Model. - Call
ai.Register("yourprovider", ...)ininit(). - Add tests in
ai/yourprovider/yourprovider_test.go. - Users enable the provider with a blank import:
import _ "go-micro.dev/v5/ai/yourprovider"
We welcome contributions and sponsorships from AI infrastructure companies — see the guide for details.
Comparison with Other Packages
The ai package follows the same patterns as other go-micro packages:
Registry:
r := registry.NewRegistry(registry.Addrs("..."))
r.Register(service)
Client:
c := client.NewClient(client.Retries(3))
c.Call(ctx, req, rsp)
AI:
m := ai.New("openai", ai.WithAPIKey("..."))
m.Generate(ctx, req)
All use:
Init()to update optionsOptions()to get current optionsString()to get the implementation name- Functional options pattern
Testing
go test ./ai/...
Examples
See the server implementation for a complete example of using the ai package with tool execution.