states

package
v0.182.1 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnyToolFailed added in v0.178.0

func AnyToolFailed(results []convdomain.ConversationEntry) bool

AnyToolFailed reports whether any entry in a completed tool batch failed (executed with a non-success result). It backs the post_tool `on_failure` reminder trigger; callers set AgentContext.LastToolFailed from it when a batch completes.

func AnyToolRejected added in v0.178.0

func AnyToolRejected(results []convdomain.ConversationEntry) bool

AnyToolRejected reports whether any entry in a completed tool batch was rejected by the user. A rejection ends the agent turn instead of feeding the results back for another LLM response.

Types

type AgentContext added in v0.178.0

type AgentContext struct {
	RequestID        string
	Conversation     *[]sdk.Message
	MessageQueue     convdomain.MessageQueue
	ConversationRepo convdomain.ConversationRepository
	ToolCalls        []*sdk.ChatCompletionMessageToolCall
	Turns            int
	MaxTurns         int
	HasToolResults   bool
	LastToolFailed   bool
	ApprovalPolicy   agentdomain.ApprovalPolicy
	Ctx              context.Context
	IsChatMode       bool
	// MaxTurnsExceeded is set by the state machine when the run is forced into
	// Completing because the turn limit was hit before the task could complete.
	MaxTurnsExceeded bool
}

AgentContext represents the execution context for the agent state machine

type AgentEvent added in v0.178.0

type AgentEvent interface {
	EventType() string
}

AgentEvent represents an event in the event-driven agent system

type AgentExecutionState added in v0.178.0

type AgentExecutionState int

AgentExecutionState represents the state of the agent execution loop This is a more granular state than ChatStatus and is used for the state machine

const (
	// StateIdle indicates no active work
	StateIdle AgentExecutionState = iota
	// StateCheckingQueue indicates examining message queue
	StateCheckingQueue
	// StateStreamingLLM indicates waiting for LLM response
	StateStreamingLLM
	// StatePostStream indicates after stream, before tool evaluation
	StatePostStream
	// StateEvaluatingTools indicates categorizing tool calls
	StateEvaluatingTools
	// StateApprovingTools indicates waiting for user approvals (sequential)
	StateApprovingTools
	// StateBlockingTools indicates approval is required but no approver is
	// reachable (approval_behaviour resolves to block), so the gated tool calls
	// are rejected with a reason instead of being prompted or executed.
	StateBlockingTools
	// StateExecutingTools indicates running tools (parallel)
	StateExecutingTools
	// StatePostToolExecution indicates after all tools complete
	StatePostToolExecution
	// StateCompleting indicates finalizing loop
	StateCompleting
	// StateStopped indicates loop terminated
	StateStopped
	// StateCancelled indicates user cancelled
	StateCancelled
	// StateError indicates error occurred
	StateError
)

func (AgentExecutionState) String added in v0.178.0

func (s AgentExecutionState) String() string

type AgentStateMachine added in v0.178.0

type AgentStateMachine interface {
	// Transition attempts to transition to the target state
	Transition(ctx *AgentContext, targetState AgentExecutionState) error

	// GetCurrentState returns the current state (thread-safe)
	GetCurrentState() AgentExecutionState

	// GetPreviousState returns the previous state (thread-safe)
	GetPreviousState() AgentExecutionState

	// CanTransition checks if a transition is valid without executing it
	CanTransition(ctx *AgentContext, targetState AgentExecutionState) bool

	// GetValidTransitions returns all valid transitions from current state
	GetValidTransitions(ctx *AgentContext) []AgentExecutionState

	// Reset resets the state machine to idle
	Reset()
}

AgentStateMachine manages agent execution state transitions

type AllToolsProcessedEvent added in v0.178.0

type AllToolsProcessedEvent struct{}

AllToolsProcessedEvent is triggered when all tools have been processed

func (AllToolsProcessedEvent) EventType added in v0.178.0

func (e AllToolsProcessedEvent) EventType() string

type ApprovalFailedEvent added in v0.178.0

type ApprovalFailedEvent struct {
	Error error
}

ApprovalFailedEvent is triggered when approval fails

func (ApprovalFailedEvent) EventType added in v0.178.0

func (e ApprovalFailedEvent) EventType() string

type ApprovingToolsState

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

ApprovingToolsState handles events in the ApprovingTools state.

This state manages sequential tool approval with overlapping execution:

  1. MessageReceivedEvent → initializes the tool round, starts sequential approval
  2. AllToolsProcessedEvent → transitions to PostToolExecution
  3. ApprovalFailedEvent → handles approval failures

func (*ApprovingToolsState) Handle

func (s *ApprovingToolsState) Handle(event AgentEvent) error

Handle processes events in ApprovingTools state

func (*ApprovingToolsState) Name

Name returns the state this handler manages

type BlockingToolsState added in v0.121.0

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

BlockingToolsState handles events in the BlockingTools state.

This state is entered (from EvaluatingTools) when at least one tool call requires approval but that approval cannot be delivered in the current session (approval_behaviour resolves to block - e.g. approval_behaviour=block, or =ipc with no broker attached). There is no approver to prompt, so each gated tool is rejected with an actionable reason instead of being executed. Tool calls in the same batch that do NOT require approval (e.g. read-only tools, allow-listed Bash) still run, preserving tool-call order.

  1. MessageReceivedEvent → processes the batch, then emits AllToolsProcessedEvent
  2. AllToolsProcessedEvent → transitions to PostToolExecution

func (*BlockingToolsState) Handle added in v0.121.0

func (s *BlockingToolsState) Handle(event AgentEvent) error

Handle processes events in BlockingTools state

func (*BlockingToolsState) Name added in v0.121.0

Name returns the state this handler manages

type CancelledState

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

CancelledState handles events in the Cancelled state.

The Cancelled state is a terminal state reached when the agent is cancelled by the user. The event loop will exit when this state is reached.

func (*CancelledState) Handle

func (s *CancelledState) Handle(event AgentEvent) error

Handle processes events in Cancelled state This is a terminal state, so no events are expected

func (*CancelledState) Name

Name returns the state this handler manages

type CheckingQueueState

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

CheckingQueueState handles events in the CheckingQueue state.

This state evaluates conditions to determine the next action:

  1. Tool results pending → must respond to tools first (StreamingLLM)
  2. Messages queued → drain queue into conversation
  3. Can complete → transition to Completing
  4. Otherwise → continue agent loop (StreamingLLM)

In chat mode the turn does NOT wait in-state for background work (the UI ticker starts fresh turns that drain completion notes here). Headless runs wait at the completion boundary via WaitForBackgroundTasks so a run never exits with orphaned background tasks.

func (*CheckingQueueState) Handle

func (s *CheckingQueueState) Handle(event AgentEvent) error

Handle processes events in CheckingQueue state

func (*CheckingQueueState) Name

Name returns the state this handler manages

type CompletingState

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

CompletingState handles events in the Completing state.

This state finalizes the agent execution:

  1. Performs a final 20ms queue check
  2. If messages queued → restart agent (CheckingQueue)
  3. Otherwise → publish completion event and transition to Idle

func (*CompletingState) Handle

func (s *CompletingState) Handle(event AgentEvent) error

Handle processes events in Completing state. Completion is driven solely by CompletionRequestedEvent (emitted right after the transition into Completing); any other event is ignored so a stray wake-up cannot finalize the agent.

func (*CompletingState) Name

Name returns the state this handler manages

type CompletionRequestedEvent added in v0.178.0

type CompletionRequestedEvent struct{}

CompletionRequestedEvent is triggered when the agent should complete

func (CompletionRequestedEvent) EventType added in v0.178.0

func (e CompletionRequestedEvent) EventType() string

type ErrorState

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

ErrorState handles events in the Error state.

The Error state is a terminal state reached when unrecoverable errors occur. The event loop will exit when this state is reached.

func (*ErrorState) Handle

func (s *ErrorState) Handle(event AgentEvent) error

Handle processes events in Error state This is a terminal state, so no events are expected

func (*ErrorState) Name

func (s *ErrorState) Name() AgentExecutionState

Name returns the state this handler manages

type EvaluatingToolsState

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

EvaluatingToolsState handles events in the EvaluatingTools state.

This state:

  1. Publishes chat complete event with tool calls
  2. Checks if any tool requires approval
  3. If approval needed → ApprovingTools
  4. Otherwise → ExecutingTools (starts background execution)

func (*EvaluatingToolsState) Handle

func (s *EvaluatingToolsState) Handle(event AgentEvent) error

Handle processes events in EvaluatingTools state

func (*EvaluatingToolsState) Name

Name returns the state this handler manages

type ExecutingToolsState

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

ExecutingToolsState handles events in the ExecutingTools state.

This state processes tool execution completion:

  1. ToolsCompletedEvent (Stop=false) → transitions to PostToolExecution
  2. ToolsCompletedEvent (Stop=true) → transitions to the Stopped terminal (a rejected tool or a successful RequestPlanApproval ended the loop)

func (*ExecutingToolsState) Handle

func (s *ExecutingToolsState) Handle(event AgentEvent) error

Handle processes events in ExecutingTools state

func (*ExecutingToolsState) Name

Name returns the state this handler manages

type IdleState

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

IdleState handles events in the Idle state.

The Idle state is the initial and final resting state of the agent. When a MessageReceivedEvent arrives, it transitions to CheckingQueue to begin processing.

func (*IdleState) Handle

func (s *IdleState) Handle(event AgentEvent) error

Handle processes events in Idle state

func (*IdleState) Name

func (s *IdleState) Name() AgentExecutionState

Name returns the state this handler manages

type MessageReceivedEvent added in v0.178.0

type MessageReceivedEvent struct {
	Message sdk.Message
}

MessageReceivedEvent is triggered when a new message arrives

func (MessageReceivedEvent) EventType added in v0.178.0

func (e MessageReceivedEvent) EventType() string

type PostStreamState

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

PostStreamState handles events in the PostStream state.

This state:

  1. Stores assistant message to conversation
  2. Checks if messages were queued during stream → CheckingQueue
  3. If tool calls exist → EvaluatingTools
  4. If no tools and can complete → Completing
  5. Otherwise → CheckingQueue

func (*PostStreamState) Handle

func (s *PostStreamState) Handle(event AgentEvent) error

Handle processes events in PostStream state

func (*PostStreamState) Name

Name returns the state this handler manages

type PostToolExecutionState

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

PostToolExecutionState handles events in the PostToolExecution state.

This state:

  1. Checks if messages were queued during tool execution → drains and goes to CheckingQueue
  2. Checks if can complete → Completing
  3. Otherwise → CheckingQueue for next turn

func (*PostToolExecutionState) Handle

func (s *PostToolExecutionState) Handle(event AgentEvent) error

Handle processes events in PostToolExecution state

func (*PostToolExecutionState) Name

Name returns the state this handler manages

type StartStreamingEvent added in v0.178.0

type StartStreamingEvent struct{}

StartStreamingEvent is triggered when the agent should start streaming

func (StartStreamingEvent) EventType added in v0.178.0

func (e StartStreamingEvent) EventType() string

type StateAction added in v0.178.0

type StateAction func(ctx *AgentContext) error

StateAction is a function executed on state transitions

type StateContext added in v0.178.0

type StateContext struct {
	// Core dependencies
	StateMachine AgentStateMachine
	AgentCtx     *AgentContext

	// Event communication
	Events chan AgentEvent

	// Concurrency control
	WaitGroup *sync.WaitGroup
	Mutex     *sync.Mutex

	// Shared state data
	CurrentMessage   *sdk.Message
	CurrentToolCalls *[]*sdk.ChatCompletionMessageToolCall
	CurrentReasoning *string

	// Tool processing state
	ToolsNeedingApproval *[]sdk.ChatCompletionMessageToolCall
	CurrentToolIndex     *int
	ToolResults          *[]convdomain.ConversationEntry

	// Request context
	Request                *agentdomain.AgentRequest
	BackgroundTaskRegistry scheddomain.BackgroundTaskRegistry
	Provider               string
	Model                  string

	// MaxConcurrentTools bounds how many approved tools may execute concurrently
	// while later tools are still being approved.
	MaxConcurrentTools int

	// Function callbacks
	ToolExecutor   *func()
	StartStreaming func()

	// Helper methods - these will be implemented as methods that delegate to internal service
	GetMetrics            func(requestID string) *agentdomain.ChatMetrics
	ShouldRequireApproval func(toolCall *sdk.ChatCompletionMessageToolCall, isChatMode bool) bool
	ApprovalDelivery      func(toolCall *sdk.ChatCompletionMessageToolCall) string
	AddMessage            func(entry convdomain.ConversationEntry) error
	BatchDrainQueue       func() int
	RequestToolApproval   func(toolCall sdk.ChatCompletionMessageToolCall) (bool, error)
	ExecuteToolInternal   func(toolCall sdk.ChatCompletionMessageToolCall, isApproved bool) convdomain.ConversationEntry
	GetAgentMode          func() agentdomain.AgentMode
	PublishChatEvent      func(event agentdomain.ChatEvent)
	PublishChatComplete   func(reasoning string, toolCalls []sdk.ChatCompletionMessageToolCall, metrics *agentdomain.ChatMetrics)
	PublishChatCancelled  func(metrics *agentdomain.ChatMetrics)
	PublishToolResults    func(results []convdomain.ConversationEntry)

	// DispatchHooks runs the actions attached to a hook point. State executors call it
	// at their loop point; the streaming path calls the service directly.
	DispatchHooks func(hook agentdomain.HookPoint)

	// WaitForBackgroundTasks blocks until in-flight background work quiesces or
	// posts a result to the message queue. Only non-chat runs invoke it, at the
	// completion boundary in CheckingQueue.
	WaitForBackgroundTasks func()
}

StateContext provides access to agent dependencies for state handlers

type StateGuard added in v0.178.0

type StateGuard func(ctx *AgentContext) bool

StateGuard is a function that determines if a state transition should occur

type StateHandler added in v0.178.0

type StateHandler interface {
	Handle(event AgentEvent) error
	Name() AgentExecutionState
}

StateHandler defines the interface for handling events in a specific state

func NewApprovingToolsState

func NewApprovingToolsState(ctx *StateContext) StateHandler

NewApprovingToolsState creates a new ApprovingTools state handler

func NewBlockingToolsState added in v0.121.0

func NewBlockingToolsState(ctx *StateContext) StateHandler

NewBlockingToolsState creates a new BlockingTools state handler

func NewCancelledState

func NewCancelledState(ctx *StateContext) StateHandler

NewCancelledState creates a new Cancelled state handler

func NewCheckingQueueState

func NewCheckingQueueState(ctx *StateContext) StateHandler

NewCheckingQueueState creates a new CheckingQueue state handler

func NewCompletingState

func NewCompletingState(ctx *StateContext) StateHandler

NewCompletingState creates a new Completing state handler

func NewErrorState

func NewErrorState(ctx *StateContext) StateHandler

NewErrorState creates a new Error state handler

func NewEvaluatingToolsState

func NewEvaluatingToolsState(ctx *StateContext) StateHandler

NewEvaluatingToolsState creates a new EvaluatingTools state handler

func NewExecutingToolsState

func NewExecutingToolsState(ctx *StateContext) StateHandler

NewExecutingToolsState creates a new ExecutingTools state handler

func NewIdleState

func NewIdleState(ctx *StateContext) StateHandler

NewIdleState creates a new Idle state handler

func NewPostStreamState

func NewPostStreamState(ctx *StateContext) StateHandler

NewPostStreamState creates a new PostStream state handler

func NewPostToolExecutionState

func NewPostToolExecutionState(ctx *StateContext) StateHandler

NewPostToolExecutionState creates a new PostToolExecution state handler

func NewStoppedState

func NewStoppedState(ctx *StateContext) StateHandler

NewStoppedState creates a new Stopped state handler

func NewStreamingLLMState

func NewStreamingLLMState(ctx *StateContext) StateHandler

NewStreamingLLMState creates a new StreamingLLM state handler

type StoppedState

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

StoppedState handles events in the Stopped state.

The Stopped state is a terminal state reached when the agent stops execution (e.g., due to tool rejection or other stop conditions). The event loop will exit when this state is reached.

func (*StoppedState) Handle

func (s *StoppedState) Handle(event AgentEvent) error

Handle processes events in Stopped state This is a terminal state, so no events are expected

func (*StoppedState) Name

Name returns the state this handler manages

type StreamCompletedEvent added in v0.178.0

type StreamCompletedEvent struct {
	Message            sdk.Message
	ToolCalls          []*sdk.ChatCompletionMessageToolCall
	Reasoning          string
	Usage              *sdk.CompletionUsage
	IterationStartTime time.Time
}

StreamCompletedEvent is triggered when LLM streaming completes

func (StreamCompletedEvent) EventType added in v0.178.0

func (e StreamCompletedEvent) EventType() string

type StreamingLLMState

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

StreamingLLMState handles events in the StreamingLLM state.

This state manages LLM streaming:

  1. StartStreamingEvent → launches background streaming goroutine
  2. StreamCompletedEvent → processes completed stream, stores data, transitions to PostStream

func (*StreamingLLMState) Handle

func (s *StreamingLLMState) Handle(event AgentEvent) error

Handle processes events in StreamingLLM state

func (*StreamingLLMState) Name

Name returns the state this handler manages

type ToolsCompletedEvent added in v0.178.0

type ToolsCompletedEvent struct {
	Results []convdomain.ConversationEntry
	Stop    bool
}

ToolsCompletedEvent is triggered when all tools finish executing. Stop is set when the results signal the loop should terminate (a rejected tool or a successful RequestPlanApproval); the ExecutingTools state then routes to the Stopped terminal instead of continuing to PostToolExecution.

func (ToolsCompletedEvent) EventType added in v0.178.0

func (e ToolsCompletedEvent) EventType() string

Jump to

Keyboard shortcuts

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