agentplane

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

agent-plane-sdk-go

Go SDK for building Agent Plane runtimes.

An Agent Plane runtime never talks to the Kubernetes API server for its configuration. It:

  1. pulls resolved config from the Registry — one-shot or as a hot-reload stream (agentplane.Client), and
  2. reads only Secret values through its own RBAC — model API keys, memory connection strings (secrets.Reader). The Registry serves Secret coordinates, never values.

This SDK is both halves of that contract, plus optional reference building blocks. The Registry server imports the same wire types, so the contract cannot drift between server and runtimes.

Packages

Package What it is Required?
agentplane (root) Wire types (AgentConfig, Tool, Model, …) + Registry client (FetchConfig, Watch) yes
secrets Secret reader via the pod's own RBAC (in-cluster config, kubeconfig fallback) yes, unless you read Secrets yourself
agentloop Reference OpenAI-compatible tool-calling loop (http + mcp tools, multi-turn sessions) optional
memory Reference conversation store for the Memory CRD (Redis, zero deps) optional
retriever Reference RAG retrieval for http-source KnowledgeBases optional

Bring your own agent framework? Use only the root package + secrets and translate AgentConfig into your framework's structures. The dependency footprint of those two is client-go and nothing else.

Quickstart

package main

import (
	"context"
	"log"

	agentplane "github.com/hkmdxlftjf/agent-plane-sdk-go"
	"github.com/hkmdxlftjf/agent-plane-sdk-go/agentloop"
	"github.com/hkmdxlftjf/agent-plane-sdk-go/secrets"
)

func main() {
	ctx := context.Background()

	// 1. Pull resolved config from the Registry.
	client := agentplane.NewClient("http://agentplane-registry:9090")
	cfg, err := client.FetchConfig(ctx, "default", "my-agent")
	if err != nil {
		log.Fatal(err)
	}
	if cfg.Phase != agentplane.PhaseReady {
		log.Fatalf("agent not ready: phase=%s", cfg.Phase)
	}

	// 2. Read the model API key via the pod's own RBAC.
	sec, err := secrets.NewReader(cfg.Namespace)
	if err != nil {
		log.Fatal(err)
	}
	apiKey, err := sec.Read(ctx, cfg.Model.SecretName, cfg.Model.SecretKey)
	if err != nil {
		log.Fatal(err)
	}

	// 3. Compose the system prompt: PromptTemplate + Skill packs.
	system := "You are a helpful assistant."
	if cfg.Prompt != nil && cfg.Prompt.System != "" {
		system = cfg.Prompt.System
	}
	for _, sk := range cfg.Skills {
		system += "\n\n# Skill: " + sk.Name + "\n" + sk.Content
	}

	// 4. Run the reference loop (or feed cfg into your own framework here).
	answer, err := agentloop.Run(ctx, agentloop.Config{
		Endpoint: cfg.Model.Endpoint,
		APIKey:   apiKey,
		Model:    cfg.Model.ModelName,
		System:   system,
		Tools:    cfg.Tools,
	}, "What is the status of order A-42?")
	if err != nil {
		log.Fatal(err)
	}
	log.Println(answer)
}
Hot reload (long-running runtimes)

Watch streams full config snapshots over SSE, reconnects on disconnect, and dedups on ConfigHash — your callback fires only when the effective config actually changed:

err := client.Watch(ctx, "default", "my-agent", func(cfg *agentplane.AgentConfig) {
	// Atomically swap your model client / tool table here.
})
Multi-turn sessions with memory
session := agentloop.NewSession(base)

store, _ := memory.Open(m.Backend, dsn, m.Namespace) // dsn read via secrets.Reader
turns, _ := store.Load(ctx, sessionID)
for _, t := range turns {
	session.AppendHistory(t.Role, t.Content)
}

answer, _ := session.Send(ctx, userText)
_ = store.Append(ctx, sessionID,
	memory.Turn{Role: "user", Content: userText},
	memory.Turn{Role: "assistant", Content: answer})

Registry wire protocol

  • GET /v1/agents/{namespace}/{name}/config — one-shot resolved snapshot (JSON AgentConfig).
  • GET /v1/agents/{namespace}/{name}/watch — SSE stream; each data: event is a full AgentConfig snapshot (never a delta), keyed by configHash. Keepalive comments (: keepalive) flow every 25s.

See runtime-protocol.md in the main repository for the full protocol description.

Versioning

The SDK follows the Registry's wire contract. Until v1, minor versions may add fields (always backward-compatible JSON) but never remove or rename them.

License

Apache-2.0

Documentation

Overview

Package agentplane is the Go SDK for building Agent Plane runtimes.

An Agent Plane runtime never talks to the Kubernetes API server for its configuration: it pulls the fully resolved config from the Registry (Client.FetchConfig / Client.Watch) and reads only Secret values — model API keys, memory connection strings — through its own RBAC (package secrets). This package defines the Registry wire contract; the same types are used by the Registry server, so the contract cannot drift silently.

Subpackages provide optional reference building blocks a runtime can adopt piecemeal: agentloop (an OpenAI-compatible tool-calling loop), memory (conversation persistence for the Memory CRD), and retriever (RAG retrieval for http-source KnowledgeBases).

Index

Constants

View Source
const PhaseReady = "Ready"

PhaseReady is the Agent phase in which the resolved config is complete and a runtime may serve traffic.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentConfig

type AgentConfig struct {
	Namespace string `json:"namespace"`
	Name      string `json:"name"`
	// ConfigHash is the Operator-computed hash of the resolved configuration.
	// Runtimes compare it to detect drift; Client.Watch dedups on it.
	ConfigHash string `json:"configHash"`
	// Phase is the Agent's lifecycle phase ("Ready", "Pending", …). A runtime
	// should only serve traffic when the phase is PhaseReady.
	Phase string `json:"phase"`
	// Spec is the effective Agent spec (AgentClass defaults applied), as raw
	// JSON. Most runtimes never need it — everything actionable is resolved
	// into the typed views below — but it is available for introspection.
	Spec json.RawMessage `json:"spec,omitempty"`
	// Prompt is the resolved system prompt from the Agent's PromptTemplate,
	// if one is referenced.
	Prompt    *Prompt         `json:"prompt,omitempty"`
	Model     *Model          `json:"model,omitempty"`
	Tools     []Tool          `json:"tools,omitempty"`
	Skills    []Skill         `json:"skills,omitempty"`
	Memories  []Memory        `json:"memories,omitempty"`
	Knowledge []KnowledgeBase `json:"knowledgeBases,omitempty"`
}

AgentConfig is the fully resolved runtime configuration the Registry serves for one Agent. Every field a runtime needs to operate is resolved server-side (tool endpoints, skill content, secret coordinates); the runtime never reads the Agent Plane CRDs itself.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to the Agent Plane Registry.

func NewClient

func NewClient(baseURL string, opts ...Option) *Client

NewClient returns a Registry client for the given base URL, e.g. "http://agentplane-registry.agentplane-system:9090".

func (*Client) FetchConfig

func (c *Client) FetchConfig(ctx context.Context, namespace, name string) (*AgentConfig, error)

FetchConfig returns a one-shot snapshot of the resolved config for an Agent (GET /v1/agents/{ns}/{name}/config).

func (*Client) Watch

func (c *Client) Watch(ctx context.Context, namespace, name string, onChange func(*AgentConfig)) error

Watch subscribes to the Registry's SSE stream for an Agent (GET /v1/agents/{ns}/{name}/watch) and invokes onChange for every config whose ConfigHash differs from the previously delivered one. Each event is a full snapshot, never a delta, so a dropped intermediate update always converges on the next event.

Watch blocks until ctx is cancelled, reconnecting with a fixed delay when the stream ends. onChange is called from Watch's goroutine; a slow onChange backpressures the stream, it is never called concurrently.

type KnowledgeBase

type KnowledgeBase struct {
	Name           string `json:"name"`
	Source         string `json:"source"`
	URI            string `json:"uri,omitempty"`
	EmbeddingModel string `json:"embeddingModel,omitempty"`
	SecretName     string `json:"secretName,omitempty"`
	SecretKey      string `json:"secretKey,omitempty"`
}

KnowledgeBase tells the runtime where a retrieval corpus lives (RAG). EmbeddingModel is resolved to its model name; Secret coordinates for accessing the source are served, never the value.

type Memory

type Memory struct {
	Name    string `json:"name"`
	Backend string `json:"backend"`
	// Namespace is a key prefix that scopes entries within the backend.
	Namespace  string `json:"namespace,omitempty"`
	SecretName string `json:"secretName,omitempty"`
	SecretKey  string `json:"secretKey,omitempty"`
}

Memory tells the runtime which conversation-memory backend to use and where its connection string lives. As with Model, only Secret coordinates are served — the runtime reads the DSN value itself.

type Model

type Model struct {
	Provider   string `json:"provider"`
	ModelName  string `json:"modelName"`
	Endpoint   string `json:"endpoint,omitempty"`
	SecretName string `json:"secretName,omitempty"`
	SecretKey  string `json:"secretKey,omitempty"`
}

Model tells the runtime which chat model to call and where to find the API key. SecretName/SecretKey are Secret *coordinates*: the Registry never serves the secret value itself — the runtime reads the Secret through its own Kubernetes RBAC (see package secrets).

type Option

type Option func(*Client)

Option configures a Client.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient replaces the underlying *http.Client. The client is used for both snapshot fetches and long-lived Watch streams, so it must not set a global Timeout (use WithFetchTimeout-style per-call contexts instead).

func WithLogf

func WithLogf(logf func(format string, args ...any)) Option

WithLogf directs the client's human-readable progress lines (reconnects, decode skips) to a printf-style logger. Silent by default.

func WithReconnectDelay

func WithReconnectDelay(d time.Duration) Option

WithReconnectDelay sets the pause between Watch reconnect attempts (default 2s).

type Prompt

type Prompt struct {
	// Name of the PromptTemplate the content was resolved from.
	Name string `json:"name"`
	// System is the system prompt text.
	System string `json:"system,omitempty"`
}

Prompt is the resolved system prompt of the Agent's PromptTemplate.

type Skill

type Skill struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Content     string `json:"content,omitempty"`
}

Skill is a resolved Skill: a markdown instruction pack whose content the runtime folds into the system prompt.

type Tool

type Tool struct {
	Name string `json:"name"`
	// Type is "http" (POST JSON to Endpoint) or "mcp" (JSON-RPC tools/call).
	Type        string `json:"type"`
	Description string `json:"description,omitempty"`
	Endpoint    string `json:"endpoint,omitempty"`
	// MCPToolName is the tool's name on the MCP server when it differs from
	// Name (mcp tools only).
	MCPToolName string `json:"mcpToolName,omitempty"`
	// InputSchema is the tool's JSON-Schema parameters object.
	InputSchema json.RawMessage `json:"inputSchema,omitempty"`
}

Tool is a fully resolved tool definition a runtime can invoke without reading the Tool/MCPServer CRs itself.

Directories

Path Synopsis
Package agentloop is a minimal, reusable agent execution loop.
Package agentloop is a minimal, reusable agent execution loop.
Package memory is a minimal, dependency-free persistence layer for agent conversation history, backing the Memory CRD.
Package memory is a minimal, dependency-free persistence layer for agent conversation history, backing the Memory CRD.
Package retriever augments user queries with context retrieved from the KnowledgeBases the Registry serves (RAG).
Package retriever augments user queries with context retrieved from the KnowledgeBases the Registry serves (RAG).
Package secrets reads Secret values through the runtime's own Kubernetes RBAC.
Package secrets reads Secret values through the runtime's own Kubernetes RBAC.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL