Documentation
¶
Overview ¶
Package sleipnir provides a multi-agent LLM orchestration harness. It is a thin canonical agent loop with first-class parallel sub-agents, a typed event stream, and a provider-agnostic LLM boundary.
Index ¶
- Variables
- func WithCompactStore(ctx context.Context, cs CompactStore) context.Context
- type AgentEndEvent
- type AgentInfo
- type AgentInput
- type AgentNamer
- type AgentSpec
- type AgentStartEvent
- type BaseMiddleware
- type BufferedSink
- type CachedRouter
- type CompactStore
- type Config
- type ContextRewriter
- type ErrorEvent
- type Event
- type HITLHandler
- type Harness
- type LLMObserver
- type LLMRequest
- type LLMResponse
- type MapRouter
- type Middleware
- type ModelConfig
- type ModelRouter
- type QuestionEvent
- type RetryPolicy
- type RunInput
- type RunOutput
- type Sink
- type StopReason
- type ThinkingEvent
- type TodoEvent
- type TodoItem
- type TodoStatus
- type TokenEvent
- type Tool
- type ToolCall
- type ToolCallEvent
- type ToolDefinition
- type ToolObserver
- type ToolResult
- type ToolResultEvent
- type Usage
Constants ¶
This section is empty.
Variables ¶
var ( ErrHarnessFrozen = errors.New("sleipnir: harness is frozen; RegisterAgent called after first Run with AllowLateRegistration disabled") ErrAgentNotRegistered = errors.New("sleipnir: agent not registered") ErrToolNameCollision = errors.New("sleipnir: duplicate tool name detected") )
Harness lifecycle errors.
var ( ErrIterationBudget = errors.New("sleipnir: agent loop exhausted MaxIterations without a final text response") ErrTokenBudget = errors.New("sleipnir: cumulative token usage exceeded RunInput.MaxTotalTokens") )
Run budget errors.
var ( ErrHITLTimeout = errors.New("sleipnir: HITL handler did not return within SLEIPNIR_HITL_TIMEOUT") ErrHITLCancelled = errors.New("sleipnir: HITL handler returned because context was cancelled") )
Human-in-the-loop errors.
var (
ErrCompactionFailed = errors.New("sleipnir: compactor middleware failed; run proceeds uncompacted")
)
Middleware errors.
Functions ¶
func WithCompactStore ¶
func WithCompactStore(ctx context.Context, cs CompactStore) context.Context
WithCompactStore stores cs in ctx. Called by the harness at the start of every runLoop invocation; also usable in tests for unit-testing middleware that reads the store.
Types ¶
type AgentEndEvent ¶
type AgentEndEvent struct {
AgentName string
Usage Usage
Stopped StopReason
}
func (AgentEndEvent) EventAgent ¶
func (e AgentEndEvent) EventAgent() string
type AgentInput ¶
type AgentInput struct {
Prompt string
Input json.RawMessage
History []anyllm.Message
}
type AgentNamer ¶
type AgentNamer interface {
EventAgent() string
}
Exported so sleipnirtest can use it:
type AgentSpec ¶
type AgentSpec struct {
Name string
Description string
InputSchema map[string]any
SystemPrompt func(AgentInput) string
Tools []Tool
Middlewares []Middleware
MaxIterations int
MaxParallelTools int
}
type AgentStartEvent ¶
type AgentStartEvent struct{ AgentName, ParentName string }
func (AgentStartEvent) EventAgent ¶
func (e AgentStartEvent) EventAgent() string
type BaseMiddleware ¶
type BaseMiddleware struct{}
BaseMiddleware can be embedded in any struct to satisfy the Middleware marker interface. External packages (e.g. sleipnirtest, application code) must embed this to produce valid Middleware values.
type BufferedSink ¶
type BufferedSink struct {
// contains filtered or unexported fields
}
func NewBufferedSink ¶
func NewBufferedSink(ctx context.Context, size int) *BufferedSink
func (*BufferedSink) DroppedCount ¶
func (s *BufferedSink) DroppedCount() int64
func (*BufferedSink) Events ¶
func (s *BufferedSink) Events() <-chan Event
func (*BufferedSink) Send ¶
func (s *BufferedSink) Send(e Event)
type CachedRouter ¶
type CachedRouter struct {
// contains filtered or unexported fields
}
CachedRouter wraps a ModelRouter and caches resolved ModelConfig values keyed by agent name. The cache persists for the lifetime of the CachedRouter instance. Construct a new CachedRouter per Run to get per-Run scoping.
func NewCachedRouter ¶
func NewCachedRouter(inner ModelRouter) *CachedRouter
func (*CachedRouter) Resolve ¶
func (r *CachedRouter) Resolve(ctx context.Context, agentName string) (ModelConfig, error)
type CompactStore ¶
type CompactStore interface {
GetWatermark(agentName string) int // returns 0 if not set
SetWatermark(agentName string, n int)
}
CompactStore tracks stable compaction watermarks per agent, scoped to one run. Stored in ctx by the harness; consumed by the Compactor middleware.
func CompactStoreFrom ¶
func CompactStoreFrom(ctx context.Context) (CompactStore, bool)
CompactStoreFrom returns the CompactStore added by the harness, or (nil, false). Used by middleware/compact — not needed by most callers.
type Config ¶
type Config struct {
DefaultMaxIterations int
DefaultMaxParallelTools int
CompactThreshold float64 // 0.75 = 75% of model context; validated (0.0, 1.0]
CompactModel string
MaxLLMRetries int
HITLTimeout time.Duration
// LogLevel controls the minimum log level for the harness logger.
//
// NOTE: this field is only honoured when set via [LoadConfigFromEnv] or
// the SLEIPNIR_LOG_LEVEL environment variable. Direct struct construction
// cannot set the internal logLevelSet flag, so [resolveDefaults] will
// silently override any value set here to [slog.LevelInfo].
LogLevel slog.Level
LogFormat string // "json" | "text"
Middlewares []Middleware
AllowLateRegistration bool
// contains filtered or unexported fields
}
Config holds harness-wide settings. All fields are optional; zero values are replaced with documented defaults by [resolveDefaults].
Note on [Config.Middlewares]: nil and empty slice are both valid; the harness treats them identically.
func LoadConfigFromEnv ¶
LoadConfigFromEnv reads SLEIPNIR_* environment variables and returns a fully resolved Config. Missing variables fall back to documented defaults. No files are read; no globals are mutated.
type ContextRewriter ¶
type ContextRewriter interface {
Middleware
RewriteBeforeLLMCall(ctx context.Context, req *LLMRequest) error
}
ContextRewriter can mutate an LLMRequest immediately before it is sent to the provider. Mutations are visible to the provider but not persisted to the conversation history. Returning a non-nil error emits an ErrorEvent; the request is sent as-is.
type ErrorEvent ¶
func (ErrorEvent) EventAgent ¶
func (e ErrorEvent) EventAgent() string
type HITLHandler ¶
type Harness ¶
type Harness struct {
// contains filtered or unexported fields
}
func NewHarness ¶
func (*Harness) AgentAsTool ¶
AgentAsTool returns a Tool that, when dispatched by the harness, recursively runs the named sub-agent. The tool's Definition is derived from the registered AgentSpec (Name, Description, InputSchema).
Returns ErrAgentNotRegistered if no agent with that name has been registered.
func (*Harness) RegisterAgent ¶
Register agent with harness. Returns ErrHarnessFrozen if `h.frozen.Load() && !h.cfg.AllowLateRegistration`
type LLMObserver ¶
type LLMObserver interface {
Middleware
OnLLMCall(ctx context.Context, req *LLMRequest, resp *LLMResponse, err error)
}
LLMObserver is called after every provider call, whether it succeeds or fails. It must not mutate req or resp.
type LLMRequest ¶
type LLMRequest struct {
Agent AgentInfo
Messages []anyllm.Message
Tools []anyllm.Tool // converted from []ToolDefinition via toolsToAnyllm()
Model ModelConfig
}
LLMRequest is the request passed to the LLM. Middleware may mutate fields. The Agent field must not be mutated by middleware.
type LLMResponse ¶
type LLMResponse struct {
Agent AgentInfo
Message anyllm.Message // the assistant turn (Role == RoleAssistant)
Usage Usage // converted from anyllm.Usage, TotalTokens computed
}
LLMResponse wraps the provider response and carries AgentInfo for observers.
type MapRouter ¶
type MapRouter struct {
Default ModelConfig
Overrides map[string]ModelConfig
}
type Middleware ¶
type Middleware interface {
// contains filtered or unexported methods
}
Middleware is a marker interface for middleware values. A middleware may implement any subset of ContextRewriter, LLMObserver, ToolObserver, and RetryPolicy. The harness discovers capabilities via type assertion.
type ModelConfig ¶
type ModelRouter ¶
type ModelRouter interface {
Resolve(ctx context.Context, agentName string) (ModelConfig, error)
}
type QuestionEvent ¶
type QuestionEvent struct{ AgentName, QuestionID, Question string }
func (QuestionEvent) EventAgent ¶
func (e QuestionEvent) EventAgent() string
type RetryPolicy ¶
type RetryPolicy interface {
Middleware
ShouldRetry(ctx context.Context, attempt int, err error) (retry bool, backoff time.Duration)
}
RetryPolicy decides whether a failed provider call should be retried and how long to wait before the next attempt. The first RetryPolicy in the chain wins; subsequent policies are not consulted. attempt is 0-based: 0 on the first failure, 1 on the second, and so on.
type RunOutput ¶
type RunOutput struct {
Text string
Messages []anyllm.Message
Usage Usage
Stopped StopReason
}
type StopReason ¶
type StopReason string
const ( StopDone StopReason = "done" StopIterationBudget StopReason = "iteration_budget" StopTokenBudget StopReason = "token_budget" StopHITLTimeout StopReason = "hitl_timeout" StopHITLCancelled StopReason = "hitl_cancelled" StopContextCancelled StopReason = "context_cancelled" StopContextTimeout StopReason = "context_timeout" )
type ThinkingEvent ¶
type ThinkingEvent struct{ AgentName, Text string }
func (ThinkingEvent) EventAgent ¶
func (e ThinkingEvent) EventAgent() string
type TodoEvent ¶
func (TodoEvent) EventAgent ¶
type TodoItem ¶
type TodoItem struct {
ID string `json:"id"`
Text string `json:"text"`
Status TodoStatus `json:"status"`
}
type TodoStatus ¶
type TodoStatus string
const ( TodoPending TodoStatus = "pending" TodoInProgress TodoStatus = "in_progress" TodoDone TodoStatus = "done" )
type TokenEvent ¶
type TokenEvent struct{ AgentName, Text string }
func (TokenEvent) EventAgent ¶
func (e TokenEvent) EventAgent() string
type Tool ¶
type Tool interface {
Definition() ToolDefinition
Invoke(ctx context.Context, args json.RawMessage) (ToolResult, error)
}
Tool defines the behaviour of an agent tool
There are two distinct failure modes:
- Infrastructure failure the LLM cannot meaningfully interpret -> Wrap error as ToolResult{IsError: true, Content: "tool execution failed: "+err.Error()} -> Emit ErrorEvent, continue run
- Structured failure the LLM can read and react to -> passed to LLM as tool_result: (ToolResult{IsError: true}, nil)
func AskUserTool ¶
func AskUserTool(handler HITLHandler) Tool
AskUserTool returns a Tool that, when invoked, emits a QuestionEvent and then delegates to the provided HITLHandler. Pass via RunInput.ExtraTools. If handler is nil, Invoke returns ToolResult{IsError: true} immediately.
func NewFuncTool ¶
func NewFuncTool(name, desc string, schema map[string]any, fn func(context.Context, json.RawMessage) (ToolResult, error)) Tool
func NewTypedTool ¶
func TodoReadTool ¶
func TodoReadTool() Tool
TodoReadTool returns a Tool that reads the current todo list for the invoking agent. Returns "[]" if no list has been written yet. Pass via RunInput.ExtraTools.
func TodoWriteTool ¶
func TodoWriteTool() Tool
TodoWriteTool returns a Tool that replaces the current todo list for the invoking agent and emits a TodoEvent. The list is keyed by agent name: state persists across turns, but two concurrent calls from the same agent are not isolated from each other. Pass via RunInput.ExtraTools.
type ToolCall ¶
type ToolCall struct {
Agent AgentInfo
ToolCallID string
ToolName string
Args json.RawMessage
}
ToolCall carries the agent identity and call parameters for ToolObserver. Middleware must not mutate Agent fields. ToolCall is distinct from anyllm.ToolCall; it carries harness-level agent identity.
type ToolCallEvent ¶
type ToolCallEvent struct {
AgentName, ToolCallID, ToolName string
Args json.RawMessage
}
func (ToolCallEvent) EventAgent ¶
func (e ToolCallEvent) EventAgent() string
type ToolDefinition ¶
type ToolObserver ¶
type ToolObserver interface {
Middleware
OnToolCall(ctx context.Context, call *ToolCall, result *ToolResult, err error)
}
ToolObserver is called after every tool invocation, including sub-agent calls. It must not mutate tc or result.
type ToolResult ¶
type ToolResultEvent ¶
func (ToolResultEvent) EventAgent ¶
func (e ToolResultEvent) EventAgent() string
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
hello
command
hello demonstrates the minimal Sleipnir setup: one agent, one typed tool, and a custom event sink.
|
hello demonstrates the minimal Sleipnir setup: one agent, one typed tool, and a custom event sink. |
|
orchestrator
command
orchestrator demonstrates a parent agent dispatching two sub-agents via AgentAsTool, with per-agent model routing, ExtraTools isolation, and event collection for replay.
|
orchestrator demonstrates a parent agent dispatching two sub-agents via AgentAsTool, with per-agent model routing, ExtraTools isolation, and event collection for replay. |
|
internal
|
|
|
Package mcpadapter bridges the MCP SDK with Sleipnir tools.
|
Package mcpadapter bridges the MCP SDK with Sleipnir tools. |
|
middleware
|
|