agentic

package
v1.0.0-alpha.39 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2026 License: MIT Imports: 8 Imported by: 0

README

agentic

Shared types for the SemStreams agentic processing system.

Overview

The agentic package defines foundational types used by the agentic component family:

  • agentic-loop: Orchestrates agent lifecycle and state machine
  • agentic-model: Integrates with LLM endpoints
  • agentic-tools: Executes tool calls

These components communicate over NATS JetStream using the types defined here.

Architecture

┌─────────────────┐
│  agentic-loop   │  Orchestrates the agent lifecycle
│  (state machine)│  Manages state, routes messages, captures trajectory
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
    ▼         ▼
┌────────┐  ┌────────────┐
│agentic-│  │agentic-    │
│model   │  │tools       │
│(LLM)   │  │(execution) │
└────────┘  └────────────┘

Type Categories

Request/Response Types
Type Description
AgentRequest Request to LLM endpoint with messages and tools
AgentResponse LLM response with content, tool calls, or error
ChatMessage Message in conversation (system/user/assistant/tool)
TokenUsage Token consumption tracking
ModelConfig LLM parameters (temperature, max_tokens)
State Machine Types
Type Description
LoopState Loop lifecycle state (exploring, planning, executing, etc.)
LoopEntity Complete loop instance with state, iterations, timeouts
Tool System Types
Type Description
ToolDefinition Tool schema (name, description, parameters)
ToolCall Request to execute a tool
ToolResult Tool execution outcome (content, error, or metadata)
Trajectory Types
Type Description
Trajectory Complete execution path of a loop
TrajectoryStep Single step (model_call or tool_call)
User Interaction Types
Type Description
UserMessage Normalized input from any channel
UserSignal Control signal (cancel, pause, resume, approve)
UserResponse Response sent back to user
TaskMessage Task to execute by agentic loop
Attachment File or media attached to a message
ResponseBlock Block of content in a rich response (text, code, diff)
ResponseAction Interactive action in a response (button, reaction)

Usage

Creating an Agent Request
request := agentic.AgentRequest{
    RequestID: "req_001",
    LoopID:    "loop_123",
    Role:      "general",
    Model:     "gpt-4",
    Messages: []agentic.ChatMessage{
        {Role: "system", Content: "You are a helpful assistant."},
        {Role: "user", Content: "Analyze this code for bugs."},
    },
    Tools: []agentic.ToolDefinition{
        {Name: "read_file", Description: "Read file contents", Parameters: schema},
    },
}

if err := request.Validate(); err != nil {
    // Handle validation error
}
Managing Loop State
// Create with default max iterations (20)
entity := agentic.NewLoopEntity("loop_123", "task_456", "general", "gpt-4")

// Or with custom max iterations
entity := agentic.NewLoopEntity("loop_123", "task_456", "general", "gpt-4", 50)

// State transitions
entity.TransitionTo(agentic.LoopStatePlanning)
entity.TransitionTo(agentic.LoopStateExecuting)

// Iteration tracking
if err := entity.IncrementIteration(); err != nil {
    // Max iterations reached
}

// Check terminal state
if entity.State.IsTerminal() {
    // Loop has finished
}
Recording Trajectory
trajectory := agentic.NewTrajectory("loop_123")

// Record a model call
trajectory.AddStep(agentic.TrajectoryStep{
    Timestamp: time.Now(),
    StepType:  "model_call",
    RequestID: "req_001",
    Prompt:    "Analyze this code...",
    Response:  "I found 3 issues...",
    TokensIn:  150,
    TokensOut: 200,
    Duration:  1250,
})

// Record a tool call
trajectory.AddStep(agentic.TrajectoryStep{
    Timestamp:     time.Now(),
    StepType:      "tool_call",
    ToolName:      "read_file",
    ToolArguments: map[string]any{"path": "main.go"},
    ToolResult:    "package main...",
    Duration:      50,
})

// Complete
trajectory.Complete("complete")
Validating Tool Calls Against Allowlist
allowed := []string{"read_file", "write_file", "list_dir"}
calls := []agentic.ToolCall{{ID: "1", Name: "delete_file"}}

if err := agentic.ValidateToolsAllowed(calls, allowed); err != nil {
    // Error: "disallowed tools: delete_file"
}

Loop States

The state machine supports these states:

State Description
exploring Initial discovery phase
planning Planning approach
architecting High-level design
executing Active execution
reviewing Reviewing results
complete Successfully finished (terminal)
failed Failed execution (terminal)
cancelled Cancelled by user (terminal)
paused Paused by user signal
awaiting_approval Waiting for user approval

States are fluid checkpoints. The loop can move backward except from terminal states.

NATS Subject Patterns

Components communicate via these subjects:

Subject Direction Description
agent.task.* external → loop Task requests
agent.request.* loop → model Model requests
agent.response.* model → loop Model responses
tool.execute.* loop → tools Tool execution
tool.result.* tools → loop Tool results
agent.complete.* loop → external Completions

User Signals

Control signals for user interaction:

Signal Description
cancel Stop execution immediately
pause Pause at next checkpoint
resume Continue paused loop
approve Approve pending result
reject Reject with optional reason
feedback Add feedback without decision
retry Retry failed loop

Thread Safety

Types in this package are not inherently thread-safe. The agentic-loop component provides thread-safe managers (LoopManager, TrajectoryManager) that wrap these types.

Limitations

  • No streaming support (responses are complete documents)
  • Tool parameters use map[string]any (no strong typing)
  • Trajectory steps are append-only (no editing)
  • Maximum trajectory size limited by NATS KV (1MB default)

Documentation

Overview

Package agentic provides shared types for the SemStreams agentic processing system.

Overview

The agentic package defines the foundational types used by the agentic component family: agentic-loop (orchestration), agentic-model (LLM integration), and agentic-tools (tool execution). These components work together to enable autonomous, tool-using AI agents that can execute complex multi-step tasks.

This package provides:

  • Request/Response types for agent communication (AgentRequest, AgentResponse)
  • State machine types for loop lifecycle (LoopState, LoopEntity)
  • Tool system types (ToolDefinition, ToolCall, ToolResult)
  • Trajectory tracking for observability (Trajectory, TrajectoryStep)

Architecture Context

The agentic system uses a three-component architecture communicating over NATS JetStream:

┌─────────────────┐
│  agentic-loop   │  Orchestrates the agent lifecycle
│  (state machine)│  Manages state, routes messages, captures trajectory
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
    ▼         ▼
┌────────┐  ┌────────────┐
│agentic-│  │agentic-    │
│model   │  │tools       │
│(LLM)   │  │(execution) │
└────────┘  └────────────┘

All three components share the types defined in this package, ensuring consistent serialization and validation across the system.

Request/Response Types

AgentRequest encapsulates a request to an LLM endpoint:

request := agentic.AgentRequest{
    RequestID: "req_001",
    LoopID:    "loop_123",
    Role:      "general",  // or "architect", "editor"
    Model:     "gpt-4",
    Messages: []agentic.ChatMessage{
        {Role: "system", Content: "You are a helpful assistant."},
        {Role: "user", Content: "Analyze this code for bugs."},
    },
    Tools: []agentic.ToolDefinition{
        {Name: "read_file", Description: "Read file contents", Parameters: schema},
    },
}

AgentResponse captures the LLM's response:

response := agentic.AgentResponse{
    RequestID: "req_001",
    Status:    "complete",  // or "tool_call", "error"
    Message: agentic.ChatMessage{
        Role:    "assistant",
        Content: "I found 3 potential issues...",
    },
    TokenUsage: agentic.TokenUsage{
        PromptTokens:     150,
        CompletionTokens: 200,
    },
}

ChatMessage Roles

The ChatMessage type supports four roles following the OpenAI convention:

  • "system": System instructions that shape agent behavior
  • "user": User input or task descriptions
  • "assistant": Agent responses (from the LLM)
  • "tool": Results from tool execution

Messages with tool calls use the ToolCalls field instead of Content:

assistantMessage := agentic.ChatMessage{
    Role: "assistant",
    ToolCalls: []agentic.ToolCall{
        {ID: "call_001", Name: "read_file", Arguments: map[string]any{"path": "main.go"}},
    },
}

Agent Roles

The agentic system supports three agent roles for different task patterns:

  • "general": Standard single-agent execution for most tasks
  • "architect": High-level planning and design (used with editor split)
  • "editor": Implementation based on architect's plan

The architect/editor split enables complex tasks where planning and execution benefit from separation. The loop orchestrator handles spawning editor loops when an architect completes.

State Machine

LoopState represents the lifecycle of an agentic loop with seven states:

exploring → planning → architecting → executing → reviewing → complete
                                                           ↘ failed

States are fluid checkpoints, not gates. The loop can move backward (e.g., from executing back to exploring if the agent needs to rethink). Only the terminal states (complete, failed) prevent further transitions.

Create and manage loop entities:

entity := agentic.NewLoopEntity("loop_123", "task_456", "general", "gpt-4")

// State transitions
entity.TransitionTo(agentic.LoopStatePlanning)
entity.TransitionTo(agentic.LoopStateExecuting)

// Iteration tracking (with guard)
if err := entity.IncrementIteration(); err != nil {
    // Max iterations reached
}

// Check terminal state
if entity.State.IsTerminal() {
    // Loop has finished
}

Tool System

The tool system enables agents to interact with external systems through a well-defined interface.

ToolDefinition describes an available tool:

toolDef := agentic.ToolDefinition{
    Name:        "read_file",
    Description: "Read the contents of a file",
    Parameters: map[string]any{
        "type": "object",
        "properties": map[string]any{
            "path": map[string]any{"type": "string", "description": "File path"},
        },
        "required": []string{"path"},
    },
}

ToolCall represents a request from the LLM to execute a tool:

call := agentic.ToolCall{
    ID:        "call_001",
    Name:      "read_file",
    Arguments: map[string]any{"path": "/etc/hosts"},
}

ToolResult returns the outcome of tool execution:

result := agentic.ToolResult{
    CallID:  "call_001",
    Content: "127.0.0.1 localhost\n...",
    // Or on error:
    // Error: "file not found",
}

Tool Validation

The ValidateToolsAllowed function checks tool calls against an allowlist:

allowed := []string{"read_file", "write_file", "list_dir"}
calls := []agentic.ToolCall{{ID: "1", Name: "delete_file"}}

if err := agentic.ValidateToolsAllowed(calls, allowed); err != nil {
    // Error: "disallowed tools: delete_file"
}

Trajectory Tracking

Trajectories capture the complete execution path of an agentic loop for observability, debugging, and compliance.

Create and populate a trajectory:

trajectory := agentic.NewTrajectory("loop_123")

// Record a model call
trajectory.AddStep(agentic.TrajectoryStep{
    Timestamp: time.Now(),
    StepType:  "model_call",
    RequestID: "req_001",
    Prompt:    "Analyze this code...",
    Response:  "I found 3 issues...",
    TokensIn:  150,
    TokensOut: 200,
    Duration:  1250, // milliseconds
})

// Record a tool call
trajectory.AddStep(agentic.TrajectoryStep{
    Timestamp:     time.Now(),
    StepType:      "tool_call",
    ToolName:      "read_file",
    ToolArguments: map[string]any{"path": "main.go"},
    ToolResult:    "package main...",
    Duration:      50,
})

// Complete the trajectory
trajectory.Complete("complete")

Trajectories automatically track:

  • Total input/output tokens across all model calls
  • Cumulative duration of all steps
  • Start and end times with final outcome

Token Usage

TokenUsage tracks token consumption for cost monitoring and rate limiting:

usage := agentic.TokenUsage{
    PromptTokens:     500,
    CompletionTokens: 250,
}
total := usage.Total() // 750

Model Configuration

ModelConfig provides default values for LLM parameters:

config := agentic.ModelConfig{
    Temperature: 0.7,
    MaxTokens:   2048,
}

// Apply defaults (Temperature: 0.2, MaxTokens: 4096)
config = config.WithDefaults()

Validation

All types include Validate() methods for input validation:

request := agentic.AgentRequest{...}
if err := request.Validate(); err != nil {
    // Handle validation error
}

Validation rules:

  • AgentRequest: requires request_id, at least one message, valid role
  • AgentResponse: requires valid status (complete, tool_call, error)
  • ChatMessage: requires valid role, either content, reasoning_content, or tool_calls
  • ToolDefinition: requires name and parameters
  • ToolCall: requires id and name
  • ToolResult: requires call_id
  • TrajectoryStep: requires valid step_type and timestamp
  • LoopEntity: requires id, valid state, positive max_iterations

Integration with NATS

The agentic components communicate via NATS JetStream using these subject patterns:

agent.task.*       - Task requests (external → loop)
agent.request.*    - Model requests (loop → model)
agent.response.*   - Model responses (model → loop)
tool.execute.*     - Tool execution (loop → tools)
tool.result.*      - Tool results (tools → loop)
agent.complete.*   - Completions (loop → external)

All subjects use the AGENT stream for reliable delivery.

KV Storage

Loop state and trajectories are persisted to NATS KV buckets:

  • AGENT_LOOPS: LoopEntity per loop ID
  • AGENT_TRAJECTORIES: Trajectory per loop ID

This enables recovery after restarts and provides queryable execution history.

Thread Safety

Types in this package are not inherently thread-safe. When used concurrently, external synchronization is required. The agentic-loop component provides thread-safe managers (LoopManager, TrajectoryManager) that wrap these types.

Error Handling

Validation errors are returned as standard Go errors with descriptive messages. Tool execution errors are captured in ToolResult.Error rather than returned as Go errors, allowing the agent to handle them gracefully.

Limitations

Current limitations of the agentic type system:

  • No streaming support (responses are complete documents)
  • Tool parameters use map[string]any (no strong typing)
  • Trajectory steps are append-only (no editing)
  • Maximum trajectory size limited by NATS KV (1MB default)

See Also

Related packages:

  • processor/agentic-loop: Loop orchestration and state management
  • processor/agentic-model: LLM endpoint integration
  • processor/agentic-tools: Tool execution framework

Package agentic provides shared types for the agentic components system. This includes loop state management, tool execution interfaces, and trajectory tracking.

Index

Constants

View Source
const (
	Domain        = "agentic"
	SchemaVersion = "v1"
)

Domain and version constants for message type identification.

View Source
const (
	CategoryTask          = "task"
	CategoryUserMessage   = "user_message"
	CategorySignal        = "signal"
	CategoryUserResponse  = "user_response"
	CategoryRequest       = "request"
	CategoryResponse      = "response"
	CategoryToolCall      = "tool_call"
	CategoryToolResult    = "tool_result"
	CategoryLoopCreated   = "loop_created"
	CategoryLoopCompleted = "loop_completed"
	CategoryLoopFailed    = "loop_failed"
	CategoryLoopCancelled = "loop_cancelled"
	CategoryContextEvent  = "context_event"
	CategorySignalMessage = "signal_message"
)

Category constants for message types.

View Source
const (
	OutcomeSuccess   = "success"
	OutcomeFailed    = "failed"
	OutcomeCancelled = "cancelled"
)

Outcome values for loop completion events.

View Source
const (
	StatusComplete = "complete"
	StatusToolCall = "tool_call"
	StatusError    = "error"
)

Response status values from model responses.

View Source
const (
	ContextEventCompactionStarting = "compaction_starting"
	ContextEventCompactionComplete = "compaction_complete"
	ContextEventGCComplete         = "gc_complete"
)

ContextEvent type values.

View Source
const (
	RoleArchitect = "architect"
	RoleEditor    = "editor"
	RoleGeneral   = "general"
	RoleQualifier = "qualifier"
	RoleDeveloper = "developer"
	RoleReviewer  = "reviewer"
)

Role values for agent loops.

View Source
const (
	SignalCancel   = "cancel"   // Stop execution immediately
	SignalPause    = "pause"    // Pause at next checkpoint
	SignalResume   = "resume"   // Continue paused loop
	SignalApprove  = "approve"  // Approve pending result
	SignalReject   = "reject"   // Reject with optional reason
	SignalFeedback = "feedback" // Add feedback without decision
	SignalRetry    = "retry"    // Retry failed loop
)

Signal type constants for user control signals

View Source
const (
	ResponseTypeText   = "text"   // Plain text response
	ResponseTypeStatus = "status" // Status update
	ResponseTypeResult = "result" // Final result
	ResponseTypeError  = "error"  // Error message
	ResponseTypePrompt = "prompt" // Awaiting user input (approval, etc.)
	ResponseTypeStream = "stream" // Streaming partial content
)

Response type constants

Variables

This section is empty.

Functions

func ValidateToolsAllowed

func ValidateToolsAllowed(calls []ToolCall, allowed []string) error

ValidateToolsAllowed validates that all tool calls are in the allowed list

Types

type AgentRequest

type AgentRequest struct {
	RequestID   string           `json:"request_id"`
	LoopID      string           `json:"loop_id"`
	Role        string           `json:"role"`
	Messages    []ChatMessage    `json:"messages"`
	Model       string           `json:"model"`
	MaxTokens   int              `json:"max_tokens,omitempty"`
	Temperature float64          `json:"temperature,omitempty"`
	Tools       []ToolDefinition `json:"tools,omitempty"`
	ToolChoice  *ToolChoice      `json:"tool_choice,omitempty"`
}

AgentRequest represents a request to an agentic service

func (*AgentRequest) MarshalJSON

func (r *AgentRequest) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*AgentRequest) Schema

func (r *AgentRequest) Schema() message.Type

Schema implements message.Payload

func (*AgentRequest) UnmarshalJSON

func (r *AgentRequest) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (AgentRequest) Validate

func (r AgentRequest) Validate() error

Validate checks if the AgentRequest is valid

type AgentResponse

type AgentResponse struct {
	RequestID  string      `json:"request_id"`
	Status     string      `json:"status"`
	Message    ChatMessage `json:"message,omitempty"`
	Error      string      `json:"error,omitempty"`
	TokenUsage TokenUsage  `json:"token_usage,omitempty"`
}

AgentResponse represents a response from an agentic service

func (*AgentResponse) MarshalJSON

func (r *AgentResponse) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*AgentResponse) Schema

func (r *AgentResponse) Schema() message.Type

Schema implements message.Payload

func (*AgentResponse) UnmarshalJSON

func (r *AgentResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (AgentResponse) Validate

func (r AgentResponse) Validate() error

Validate checks if the AgentResponse is valid

type Attachment

type Attachment struct {
	Type     string `json:"type"`              // file, image, code, url
	Name     string `json:"name"`              // filename or title
	URL      string `json:"url,omitempty"`     // URL to fetch content
	Content  string `json:"content,omitempty"` // inline content if small
	MimeType string `json:"mime_type,omitempty"`
	Size     int64  `json:"size,omitempty"`
}

Attachment represents a file or other media attached to a message

type ChatMessage

type ChatMessage struct {
	Role             string     `json:"role"`
	Content          string     `json:"content,omitempty"`
	Name             string     `json:"name,omitempty"`              // Function name for tool role messages (required by Gemini)
	ReasoningContent string     `json:"reasoning_content,omitempty"` // Thinking model chain-of-thought
	ToolCalls        []ToolCall `json:"tool_calls,omitempty"`
	ToolCallID       string     `json:"tool_call_id,omitempty"` // Required for tool role messages
}

ChatMessage represents a message in a conversation

func (*ChatMessage) UnmarshalJSON

func (m *ChatMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts both "reasoning" (Ollama) and "reasoning_content" (DeepSeek/canonical). If both are present, reasoning_content wins.

func (ChatMessage) Validate

func (m ChatMessage) Validate() error

Validate checks if the ChatMessage is valid

type ConstructedContext

type ConstructedContext = types.ConstructedContext

ConstructedContext is an alias for types.ConstructedContext. The canonical type is defined in pkg/types/context.go.

type ContextEvent

type ContextEvent struct {
	Type        string  `json:"type"` // ContextEventCompactionStarting, ContextEventCompactionComplete, ContextEventGCComplete
	LoopID      string  `json:"loop_id"`
	Iteration   int     `json:"iteration"`
	Utilization float64 `json:"utilization,omitempty"`
	TokensSaved int     `json:"tokens_saved,omitempty"`
	Summary     string  `json:"summary,omitempty"`
}

ContextEvent represents a context management event (compaction, GC).

func (*ContextEvent) MarshalJSON

func (e *ContextEvent) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*ContextEvent) Schema

func (e *ContextEvent) Schema() message.Type

Schema implements message.Payload

func (*ContextEvent) UnmarshalJSON

func (e *ContextEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*ContextEvent) Validate

func (e *ContextEvent) Validate() error

Validate implements message.Payload

type ContextSource

type ContextSource = types.ContextSource

ContextSource is an alias for types.ContextSource. The canonical type is defined in pkg/types/context.go.

type GraphContextSpec

type GraphContextSpec = types.GraphContextSpec

GraphContextSpec is an alias for types.GraphContextSpec. The canonical type is defined in pkg/types/context.go.

type LoopCancelledEvent

type LoopCancelledEvent struct {
	LoopID       string    `json:"loop_id"`
	TaskID       string    `json:"task_id"`
	Outcome      string    `json:"outcome"` // OutcomeCancelled
	CancelledBy  string    `json:"cancelled_by"`
	WorkflowSlug string    `json:"workflow_slug,omitempty"`
	WorkflowStep string    `json:"workflow_step,omitempty"`
	CancelledAt  time.Time `json:"cancelled_at"`
}

LoopCancelledEvent is published when a loop is cancelled by user action.

func (*LoopCancelledEvent) MarshalJSON

func (e *LoopCancelledEvent) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*LoopCancelledEvent) Schema

func (e *LoopCancelledEvent) Schema() message.Type

Schema implements message.Payload

func (*LoopCancelledEvent) UnmarshalJSON

func (e *LoopCancelledEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*LoopCancelledEvent) Validate

func (e *LoopCancelledEvent) Validate() error

Validate implements message.Payload

type LoopCompletedEvent

type LoopCompletedEvent struct {
	LoopID       string    `json:"loop_id"`
	TaskID       string    `json:"task_id"`
	Outcome      string    `json:"outcome"` // OutcomeSuccess
	Role         string    `json:"role"`
	Result       string    `json:"result"`
	Model        string    `json:"model"`
	Iterations   int       `json:"iterations"`
	TokensIn     int       `json:"tokens_in"`
	TokensOut    int       `json:"tokens_out"`
	ParentLoopID string    `json:"parent_loop,omitempty"`
	WorkflowSlug string    `json:"workflow_slug,omitempty"`
	WorkflowStep string    `json:"workflow_step,omitempty"`
	CompletedAt  time.Time `json:"completed_at"`
	// User routing info for response delivery
	ChannelType string `json:"channel_type,omitempty"`
	ChannelID   string `json:"channel_id,omitempty"`
	UserID      string `json:"user_id,omitempty"`
}

LoopCompletedEvent is published when a loop completes successfully.

func (*LoopCompletedEvent) MarshalJSON

func (e *LoopCompletedEvent) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*LoopCompletedEvent) Schema

func (e *LoopCompletedEvent) Schema() message.Type

Schema implements message.Payload

func (*LoopCompletedEvent) UnmarshalJSON

func (e *LoopCompletedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*LoopCompletedEvent) Validate

func (e *LoopCompletedEvent) Validate() error

Validate implements message.Payload

type LoopCreatedEvent

type LoopCreatedEvent struct {
	LoopID           string    `json:"loop_id"`
	TaskID           string    `json:"task_id"`
	Role             string    `json:"role"`
	Model            string    `json:"model"`
	WorkflowSlug     string    `json:"workflow_slug,omitempty"`
	WorkflowStep     string    `json:"workflow_step,omitempty"`
	ContextRequestID string    `json:"context_request_id,omitempty"`
	MaxIterations    int       `json:"max_iterations"`
	CreatedAt        time.Time `json:"created_at"`
}

LoopCreatedEvent is published when a new agentic loop is created.

func (*LoopCreatedEvent) MarshalJSON

func (e *LoopCreatedEvent) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*LoopCreatedEvent) Schema

func (e *LoopCreatedEvent) Schema() message.Type

Schema implements message.Payload

func (*LoopCreatedEvent) UnmarshalJSON

func (e *LoopCreatedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*LoopCreatedEvent) Validate

func (e *LoopCreatedEvent) Validate() error

Validate implements message.Payload

type LoopEntity

type LoopEntity struct {
	ID                 string                `json:"id"`
	TaskID             string                `json:"task_id"`
	State              LoopState             `json:"state"`
	Role               string                `json:"role"`
	Model              string                `json:"model"`
	Iterations         int                   `json:"iterations"`
	MaxIterations      int                   `json:"max_iterations"`
	PendingToolResults map[string]ToolResult `json:"pending_tool_results,omitempty"` // Accumulated tool results by call ID
	StartedAt          time.Time             `json:"started_at,omitempty"`           // When the loop was created
	TimeoutAt          time.Time             `json:"timeout_at,omitempty"`           // When the loop should timeout
	ParentLoopID       string                `json:"parent_loop_id,omitempty"`       // Parent loop ID for architect->editor relationship

	// Multi-agent depth tracking
	Depth    int `json:"depth,omitempty"`     // Current depth in agent tree (0 = root)
	MaxDepth int `json:"max_depth,omitempty"` // Maximum allowed depth for spawned agents

	// Signal support fields
	PauseRequested   bool      `json:"pause_requested,omitempty"`    // Pause requested, will pause at next checkpoint
	PauseRequestedBy string    `json:"pause_requested_by,omitempty"` // User who requested pause
	StateBeforePause LoopState `json:"state_before_pause,omitempty"` // State before pause (for resume)
	CancelledBy      string    `json:"cancelled_by,omitempty"`       // User who cancelled the loop
	CancelledAt      time.Time `json:"cancelled_at,omitempty"`       // When the loop was cancelled

	// User context (for routing responses)
	UserID      string `json:"user_id,omitempty"`      // User who initiated the loop
	ChannelType string `json:"channel_type,omitempty"` // cli, slack, discord, web
	ChannelID   string `json:"channel_id,omitempty"`   // Channel/session ID for routing responses

	// Workflow context (for loops created by workflow commands)
	WorkflowSlug string `json:"workflow_slug,omitempty"` // e.g., "add-user-auth"
	WorkflowStep string `json:"workflow_step,omitempty"` // e.g., "design"

	// Completion data (populated when loop completes)
	// These fields enable SSE delivery of results via KV watch
	Outcome     string    `json:"outcome,omitempty"`      // success, failed, cancelled
	Result      string    `json:"result,omitempty"`       // LLM response content
	Error       string    `json:"error,omitempty"`        // Error message on failure
	CompletedAt time.Time `json:"completed_at,omitempty"` // When the loop completed

	// AGNTCY identity (Phase 2 AGNTCY integration)
	// When set, provides DID-based cryptographic identity for this agent loop.
	Identity *identity.AgentIdentity `json:"identity,omitempty"`
}

LoopEntity represents an agentic loop instance

func NewLoopEntity

func NewLoopEntity(id, taskID, role, model string, maxIterations ...int) LoopEntity

NewLoopEntity creates a new LoopEntity with default values

func (*LoopEntity) IncrementIteration

func (e *LoopEntity) IncrementIteration() error

IncrementIteration increments the iteration counter

func (*LoopEntity) TransitionTo

func (e *LoopEntity) TransitionTo(newState LoopState) error

TransitionTo transitions the entity to a new state

func (*LoopEntity) Validate

func (e *LoopEntity) Validate() error

Validate checks if the LoopEntity is valid

type LoopFailedEvent

type LoopFailedEvent struct {
	LoopID       string    `json:"loop_id"`
	TaskID       string    `json:"task_id"`
	Outcome      string    `json:"outcome"` // OutcomeFailed
	Reason       string    `json:"reason"`
	Error        string    `json:"error"`
	Role         string    `json:"role"`
	Model        string    `json:"model"`
	Iterations   int       `json:"iterations"`
	TokensIn     int       `json:"tokens_in"`
	TokensOut    int       `json:"tokens_out"`
	WorkflowSlug string    `json:"workflow_slug,omitempty"`
	WorkflowStep string    `json:"workflow_step,omitempty"`
	FailedAt     time.Time `json:"failed_at"`
	// User routing info for error notifications
	ChannelType string `json:"channel_type,omitempty"`
	ChannelID   string `json:"channel_id,omitempty"`
	UserID      string `json:"user_id,omitempty"`
}

LoopFailedEvent is published when a loop fails.

func (*LoopFailedEvent) MarshalJSON

func (e *LoopFailedEvent) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*LoopFailedEvent) Schema

func (e *LoopFailedEvent) Schema() message.Type

Schema implements message.Payload

func (*LoopFailedEvent) UnmarshalJSON

func (e *LoopFailedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*LoopFailedEvent) Validate

func (e *LoopFailedEvent) Validate() error

Validate implements message.Payload

type LoopState

type LoopState string

LoopState represents the current state of an agentic loop

const (
	// Standard workflow states
	LoopStateExploring    LoopState = "exploring"
	LoopStatePlanning     LoopState = "planning"
	LoopStateArchitecting LoopState = "architecting"
	LoopStateExecuting    LoopState = "executing"
	LoopStateReviewing    LoopState = "reviewing"

	// Terminal states
	LoopStateComplete  LoopState = "complete"
	LoopStateFailed    LoopState = "failed"
	LoopStateCancelled LoopState = "cancelled" // Cancelled by user signal

	// Signal-related states
	LoopStatePaused           LoopState = "paused"            // Paused by user signal
	LoopStateAwaitingApproval LoopState = "awaiting_approval" // Waiting for user approval
)

Loop states for the agentic state machine. The state machine supports fluid transitions (can move backward) except from terminal states.

func (LoopState) IsTerminal

func (s LoopState) IsTerminal() bool

IsTerminal returns true if the state is a terminal state

func (LoopState) String

func (s LoopState) String() string

String returns the string representation of the state

type ModelConfig

type ModelConfig struct {
	Temperature float64 `json:"temperature,omitempty"`
	MaxTokens   int     `json:"max_tokens,omitempty"`
}

ModelConfig represents configuration for a language model

func (ModelConfig) WithDefaults

func (c ModelConfig) WithDefaults() ModelConfig

WithDefaults returns a copy of the config with default values applied

type ResponseAction

type ResponseAction struct {
	ID     string `json:"id"`
	Type   string `json:"type"` // button, reaction
	Label  string `json:"label"`
	Signal string `json:"signal"` // signal to send if clicked
	Style  string `json:"style"`  // primary, danger, secondary
}

ResponseAction represents an interactive action in a response

type ResponseBlock

type ResponseBlock struct {
	Type    string `json:"type"` // text, code, diff, file, progress
	Content string `json:"content"`
	Lang    string `json:"lang,omitempty"` // for code blocks
}

ResponseBlock represents a block of content in a rich response

type TaskMessage

type TaskMessage struct {
	LoopID string `json:"loop_id,omitempty"` // loop to continue, or empty for new
	TaskID string `json:"task_id"`
	Role   string `json:"role"`
	Model  string `json:"model"`
	Prompt string `json:"prompt"`

	// Workflow context (optional, set by workflow commands)
	WorkflowSlug string `json:"workflow_slug,omitempty"` // e.g., "add-user-auth"
	WorkflowStep string `json:"workflow_step,omitempty"` // e.g., "design"

	// User routing info (optional, for error notifications)
	ChannelType string `json:"channel_type,omitempty"` // e.g., "http", "cli", "slack"
	ChannelID   string `json:"channel_id,omitempty"`   // session/channel identifier
	UserID      string `json:"user_id,omitempty"`      // user who initiated the request

	// Multi-agent hierarchy (optional, for parallel/nested agents)
	ParentLoopID string `json:"parent_loop_id,omitempty"` // Parent loop ID for nested agents
	Depth        int    `json:"depth,omitempty"`          // Current depth in agent tree (0 = root)
	MaxDepth     int    `json:"max_depth,omitempty"`      // Maximum allowed depth

	// Pre-constructed context (optional, skips discovery if present)
	// When set, the agent loop uses this context directly instead of hydrating
	Context *types.ConstructedContext `json:"context,omitempty"`

	// Context assembly reference (links to assembled context)
	ContextRequestID string `json:"context_request_id,omitempty"`

	// Per-task tool override (optional, skips global discovery if present)
	Tools []ToolDefinition `json:"tools,omitempty"`

	// ToolChoice controls how the model selects tools for this task.
	// Nil means "auto" (model decides). Cached for all iterations in the loop.
	ToolChoice *ToolChoice `json:"tool_choice,omitempty"`

	// Domain context propagated to all tool calls in this loop
	Metadata map[string]any `json:"metadata,omitempty"`
}

TaskMessage represents a task to be executed by an agentic loop

func (*TaskMessage) MarshalJSON

func (t *TaskMessage) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*TaskMessage) Schema

func (t *TaskMessage) Schema() message.Type

Schema implements message.Payload

func (*TaskMessage) UnmarshalJSON

func (t *TaskMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (TaskMessage) Validate

func (t TaskMessage) Validate() error

Validate checks if the TaskMessage is valid

type TokenUsage

type TokenUsage struct {
	PromptTokens     int `json:"prompt_tokens"`
	CompletionTokens int `json:"completion_tokens"`
}

TokenUsage tracks token consumption for a request

func (TokenUsage) Total

func (u TokenUsage) Total() int

Total returns the total number of tokens used

type ToolCall

type ToolCall struct {
	ID        string         `json:"id"`
	Name      string         `json:"name"`
	Arguments map[string]any `json:"arguments,omitempty"`
	Metadata  map[string]any `json:"metadata,omitempty"` // Domain context, propagated from task
	LoopID    string         `json:"loop_id,omitempty"`
	TraceID   string         `json:"trace_id,omitempty"`
}

ToolCall represents a request to call a tool

func (*ToolCall) MarshalJSON

func (t *ToolCall) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*ToolCall) Schema

func (t *ToolCall) Schema() message.Type

Schema implements message.Payload

func (*ToolCall) UnmarshalJSON

func (t *ToolCall) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (ToolCall) Validate

func (t ToolCall) Validate() error

Validate checks if the ToolCall is valid

type ToolCallFilter

type ToolCallFilter interface {
	FilterToolCalls(loopID string, calls []ToolCall) (ToolCallFilterResult, error)
}

ToolCallFilter intercepts tool calls before execution. Implementations can approve, reject, or modify calls for authorization, rate limiting, or domain-scoped access control.

type ToolCallFilterResult

type ToolCallFilterResult struct {
	Approved []ToolCall
	Rejected []ToolCallRejection
}

ToolCallFilterResult contains the outcome of filtering tool calls.

type ToolCallRejection

type ToolCallRejection struct {
	Call   ToolCall
	Reason string
}

ToolCallRejection pairs a rejected tool call with the reason it was denied.

type ToolChoice

type ToolChoice struct {
	Mode         string `json:"mode"`                    // "auto", "required", "none", "function"
	FunctionName string `json:"function_name,omitempty"` // required when Mode is "function"
}

ToolChoice controls how the model selects tools. Mode is one of: "auto" (default), "required", "none", or "function". When Mode is "function", FunctionName specifies which function to call.

func (ToolChoice) Validate

func (tc ToolChoice) Validate() error

Validate checks if the ToolChoice has a valid mode and required fields.

type ToolDefinition

type ToolDefinition struct {
	Name        string         `json:"name"`
	Description string         `json:"description"`
	Parameters  map[string]any `json:"parameters"`
}

ToolDefinition represents the definition of a tool that can be called

func (ToolDefinition) Validate

func (t ToolDefinition) Validate() error

Validate checks if the ToolDefinition is valid

type ToolResult

type ToolResult struct {
	CallID   string         `json:"call_id"`
	Name     string         `json:"name,omitempty"` // Tool function name (required by Gemini on tool result messages)
	Content  string         `json:"content,omitempty"`
	Error    string         `json:"error,omitempty"`
	Metadata map[string]any `json:"metadata,omitempty"`
	LoopID   string         `json:"loop_id,omitempty"`
	TraceID  string         `json:"trace_id,omitempty"`
	StopLoop bool           `json:"stop_loop,omitempty"` // Signal loop termination; Content becomes the completion result
}

ToolResult represents the result of a tool call

func (*ToolResult) MarshalJSON

func (t *ToolResult) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*ToolResult) Schema

func (t *ToolResult) Schema() message.Type

Schema implements message.Payload

func (*ToolResult) UnmarshalJSON

func (t *ToolResult) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (ToolResult) Validate

func (t ToolResult) Validate() error

Validate checks if the ToolResult is valid

type Trajectory

type Trajectory struct {
	LoopID         string           `json:"loop_id"`
	StartTime      time.Time        `json:"start_time"`
	EndTime        *time.Time       `json:"end_time,omitempty"`
	Steps          []TrajectoryStep `json:"steps"`
	Outcome        string           `json:"outcome,omitempty"`
	TotalTokensIn  int              `json:"total_tokens_in"`
	TotalTokensOut int              `json:"total_tokens_out"`
	Duration       int64            `json:"duration"` // milliseconds
}

Trajectory represents the complete execution path of an agentic loop

func NewTrajectory

func NewTrajectory(loopID string) Trajectory

NewTrajectory creates a new Trajectory with initialized values

func (*Trajectory) AddStep

func (t *Trajectory) AddStep(step TrajectoryStep)

AddStep adds a step to the trajectory and updates totals

func (*Trajectory) Complete

func (t *Trajectory) Complete(outcome string)

Complete marks the trajectory as complete and calculates final duration

type TrajectoryStep

type TrajectoryStep struct {
	Timestamp     time.Time      `json:"timestamp"`
	StepType      string         `json:"step_type"`
	RequestID     string         `json:"request_id,omitempty"`
	Prompt        string         `json:"prompt,omitempty"`
	Response      string         `json:"response,omitempty"`
	TokensIn      int            `json:"tokens_in,omitempty"`
	TokensOut     int            `json:"tokens_out,omitempty"`
	ToolName      string         `json:"tool_name,omitempty"`
	ToolArguments map[string]any `json:"tool_arguments,omitempty"`
	ToolResult    string         `json:"tool_result,omitempty"`
	Duration      int64          `json:"duration"`             // milliseconds
	Messages      []ChatMessage  `json:"messages,omitempty"`   // Full request messages (detail=full)
	ToolCalls     []ToolCall     `json:"tool_calls,omitempty"` // Assistant tool calls (detail=full)
	Model         string         `json:"model,omitempty"`      // Model used
}

TrajectoryStep represents a single step in an agentic trajectory

func (TrajectoryStep) Validate

func (s TrajectoryStep) Validate() error

Validate checks if the TrajectoryStep is valid

type UserMessage

type UserMessage struct {
	// Identity
	MessageID   string `json:"message_id"`
	ChannelType string `json:"channel_type"` // cli, slack, discord, web
	ChannelID   string `json:"channel_id"`   // specific conversation/channel
	UserID      string `json:"user_id"`

	// Content
	Content     string       `json:"content"`
	Attachments []Attachment `json:"attachments,omitempty"`

	// Context
	ReplyTo          string            `json:"reply_to,omitempty"`           // loop_id if continuing
	ThreadID         string            `json:"thread_id,omitempty"`          // for threaded channels
	Metadata         map[string]string `json:"metadata,omitempty"`           // channel-specific
	ContextRequestID string            `json:"context_request_id,omitempty"` // links to assembled context

	// Timing
	Timestamp time.Time `json:"timestamp"`
}

UserMessage represents normalized input from any channel (CLI, Slack, Discord, web)

func (*UserMessage) MarshalJSON

func (m *UserMessage) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*UserMessage) Schema

func (m *UserMessage) Schema() message.Type

Schema implements message.Payload

func (*UserMessage) UnmarshalJSON

func (m *UserMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (UserMessage) Validate

func (m UserMessage) Validate() error

Validate checks if the UserMessage is valid

type UserResponse

type UserResponse struct {
	ResponseID  string `json:"response_id"`
	ChannelType string `json:"channel_type"`
	ChannelID   string `json:"channel_id"`
	UserID      string `json:"user_id"` // who to respond to

	// What we're responding to
	InReplyTo string `json:"in_reply_to,omitempty"` // message_id or loop_id
	ThreadID  string `json:"thread_id,omitempty"`

	// Content
	Type    string `json:"type"` // text, status, result, error, prompt, stream
	Content string `json:"content"`

	// Rich content (optional)
	Blocks  []ResponseBlock  `json:"blocks,omitempty"`
	Actions []ResponseAction `json:"actions,omitempty"`

	Timestamp time.Time `json:"timestamp"`
}

UserResponse is sent back to users via their channel

func (*UserResponse) MarshalJSON

func (r *UserResponse) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*UserResponse) Schema

func (r *UserResponse) Schema() message.Type

Schema implements message.Payload

func (*UserResponse) UnmarshalJSON

func (r *UserResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (UserResponse) Validate

func (r UserResponse) Validate() error

Validate checks if the UserResponse is valid

type UserSignal

type UserSignal struct {
	SignalID    string    `json:"signal_id"`
	Type        string    `json:"type"` // cancel, pause, resume, approve, reject, feedback, retry
	LoopID      string    `json:"loop_id"`
	UserID      string    `json:"user_id"`
	ChannelType string    `json:"channel_type"`
	ChannelID   string    `json:"channel_id"`
	Payload     any       `json:"payload,omitempty"` // signal-specific data (e.g., rejection reason)
	Timestamp   time.Time `json:"timestamp"`
}

UserSignal represents a control signal from user to affect loop execution

func (*UserSignal) MarshalJSON

func (s *UserSignal) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*UserSignal) Schema

func (s *UserSignal) Schema() message.Type

Schema implements message.Payload

func (*UserSignal) UnmarshalJSON

func (s *UserSignal) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (UserSignal) Validate

func (s UserSignal) Validate() error

Validate checks if the UserSignal is valid

Directories

Path Synopsis
Package identity provides DID-based cryptographic identity for AGNTCY integration.
Package identity provides DID-based cryptographic identity for AGNTCY integration.

Jump to

Keyboard shortcuts

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