Documentation
¶
Overview ¶
Package agent provides the Agent orchestration layer for OpenBotStack runtime.
The Agent is responsible for:
- Receiving user messages
- Delegating to a Planner for LLM-based skill selection
- Forwarding structured ExecutionPlans to the Executor
The Agent does NOT:
- Directly select skills (that's the Planner's job)
- Execute skills (that's the Executor's job)
- Handle HTTP concerns (that's the Router's job)
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNilPlan is returned when an execution plan is nil. ErrNilPlan = errors.New("agent: execution plan is nil") // ErrEmptySkillID is returned when plan has no skill ID. ErrEmptySkillID = errors.New("agent: execution plan has empty skill ID") // ErrPlanningFailed is returned when the planner fails to produce a plan. ErrPlanningFailed = errors.New("agent: planning failed") // ErrNoSkillsAvailable is returned when no skills are registered. ErrNoSkillsAvailable = errors.New("agent: no skills available for planning") )
Common errors for the agent package.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
type Agent interface {
// HandleMessage processes a user message and returns a response.
HandleMessage(ctx context.Context, req MessageRequest) (*MessageResponse, error)
}
Agent orchestrates the planning and execution of skills.
The Agent lifecycle:
- Receives MessageRequest from Router
- Gathers available skills from registry
- Delegates to Planner for skill selection (LLM call)
- Receives ExecutionPlan from Planner
- Forwards plan to Executor
- Returns MessageResponse to Router
type DefaultAgent ¶
type DefaultAgent struct {
// contains filtered or unexported fields
}
DefaultAgent is the standard Agent implementation.
func NewDefaultAgent ¶
func NewDefaultAgent(planner Planner, executor PlanExecutor, registry SkillRegistry, runtime *assistant.AssistantRuntime) *DefaultAgent
NewDefaultAgent creates a new Agent with the given dependencies.
func (*DefaultAgent) HandleMessage ¶
func (a *DefaultAgent) HandleMessage(ctx context.Context, req MessageRequest) (*MessageResponse, error)
HandleMessage implements Agent.
type ExecutionMeta ¶
type ExecutionMeta struct {
TenantID string
UserID string
SessionID string
RequestID string
AssistantID string
}
ExecutionMeta contains metadata for execution tracking.
type ExecutionPlan ¶
type ExecutionPlan struct {
// SkillID is the identifier of the skill to execute.
// Format: "namespace/name" (e.g., "core/summarize")
SkillID string `json:"skill_id"`
// Arguments are the structured inputs for the skills.
// Must conform to the skill's InputSchema.
Arguments map[string]any `json:"arguments"`
// Reasoning explains why this skill was selected (for audit/debug).
Reasoning string `json:"reasoning,omitempty"`
}
ExecutionPlan is the structured output from LLM-based planning. It specifies which skill to invoke and with what arguments.
func (*ExecutionPlan) ArgumentsJSON ¶
func (p *ExecutionPlan) ArgumentsJSON() ([]byte, error)
ArgumentsJSON returns the arguments serialized as JSON bytes.
func (*ExecutionPlan) Validate ¶
func (p *ExecutionPlan) Validate() error
Validate checks if the execution plan is valid.
type LLMPlanner ¶
type LLMPlanner struct {
// contains filtered or unexported fields
}
LLMPlanner implements Planner using the Model Router for skill selection.
func NewLLMPlanner ¶
func NewLLMPlanner(router providers.ModelRouter) *LLMPlanner
NewLLMPlanner creates a new LLM-based planner.
func (*LLMPlanner) Plan ¶
func (p *LLMPlanner) Plan(ctx context.Context, runtime *assistant.AssistantRuntime, req PlanRequest) (*ExecutionPlan, error)
Plan implements Planner.
type MessageRequest ¶
type MessageRequest struct {
TenantID string `json:"tenant_id"`
UserID string `json:"user_id"`
SessionID string `json:"session_id"`
Message string `json:"message"`
}
MessageRequest represents input to the Agent.
type MessageResponse ¶
type MessageResponse struct {
SessionID string `json:"session_id"`
Message string `json:"message"`
SkillUsed string `json:"skill_used,omitempty"`
Plan *ExecutionPlan `json:"plan,omitempty"`
}
MessageResponse represents output from the Agent.
type MockLLMClient ¶
type MockLLMClient struct {
// Responses maps prompts (or substrings) to responses.
Responses map[string]string
// DefaultResponse is returned when no match is found.
DefaultResponse string
// ForcedError causes Generate to return this error if set.
ForcedError error
}
MockLLMClient is a test implementation of LLMClient.
func NewMockLLMClient ¶
func NewMockLLMClient() *MockLLMClient
NewMockLLMClient creates a mock LLM client.
type MockPlanner ¶
type MockPlanner struct {
// DefaultSkillID is returned when no heuristic matches.
DefaultSkillID string
// ForcedPlan overrides all logic and returns this plan if set.
ForcedPlan *ExecutionPlan
// ForcedError causes Plan to return this error if set.
ForcedError error
}
MockPlanner is a test implementation of Planner. It uses simple heuristics instead of an LLM for deterministic testing.
func NewMockPlanner ¶
func NewMockPlanner(defaultSkillID string) *MockPlanner
NewMockPlanner creates a mock planner with the given default skills.
func (*MockPlanner) Plan ¶
func (p *MockPlanner) Plan(ctx context.Context, runtime *assistant.AssistantRuntime, req PlanRequest) (*ExecutionPlan, error)
Plan implements Planner with simple keyword-based heuristics.
type PlanExecutor ¶
type PlanExecutor interface {
// ExecuteFromPlan runs a skill based on the execution plan.
ExecuteFromPlan(ctx context.Context, plan *ExecutionPlan, meta ExecutionMeta) (*execution.ExecutionResult, error)
}
PlanExecutor executes validated execution plans.
type PlanRequest ¶
type PlanRequest struct {
// UserMessage is the current user input.
UserMessage string
// AvailableSkills describes skills the LLM can choose from.
AvailableSkills []SkillDescriptor
// ConversationHistory provides context from prior messages.
ConversationHistory []Message
}
PlanRequest contains context for the Planner.
type Planner ¶
type Planner interface {
// Plan analyzes user intent and produces an execution plan.
// Returns an ExecutionPlan specifying which skill to call and with what arguments.
Plan(ctx context.Context, runtime *assistant.AssistantRuntime, req PlanRequest) (*ExecutionPlan, error)
}
Planner uses an LLM to analyze user intent and select appropriate skills.
The Planner is the ONLY component that decides which skill to invoke. It produces a structured ExecutionPlan that the Executor will run.
type SkillDescriptor ¶
type SkillDescriptor struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
InputSchema *control_skills.JSONSchema `json:"input_schema,omitempty"`
}
SkillDescriptor describes a skill for LLM context building. This is passed to the Planner so the LLM knows which skills are available.
func SkillDescriptorFromSkill ¶
func SkillDescriptorFromSkill(s skills.Skill) SkillDescriptor
SkillDescriptorFromSkill converts a skills.Skill to a SkillDescriptor.