servicecore

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2025 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

executor.go handles runtime creation and stream execution for agent sessions in cagent's servicecore architecture.

This component bridges the gap between the servicecore's session management and cagent's existing runtime system, providing:

1. Runtime Lifecycle Management:

  • Creates new runtime instances from resolved agent configurations
  • Initializes agent toolsets and validates configurations
  • Manages runtime cleanup to prevent resource leaks
  • Integrates with existing cagent loader and runtime components

2. Stream Execution Coordination:

  • Processes user messages through the agent runtime
  • Collects streaming events from runtime.RunStream() into structured responses
  • Tracks execution metadata (duration, tool calls, event counts)
  • Handles runtime errors and provides structured error reporting

3. Event Processing and Response Formatting:

  • Aggregates streaming events (tool calls, responses, agent messages)
  • Builds structured Response objects with content, events, and metadata
  • Provides timing and performance metrics for monitoring
  • Maintains session state consistency across message exchanges

Integration Points: - Uses pkg/teamloader for agent configuration parsing - Leverages pkg/runtime for actual agent execution - Integrates with pkg/session for conversation state management - Provides clean abstractions for both MCP and HTTP transports

The Executor ensures that runtime complexity is hidden from transport layers while providing rich structured data for client consumption and system monitoring.

manager.go implements the ServiceManager interface as the central orchestrator for multi-tenant agent operations in cagent's MCP mode.

This file serves as the primary coordination layer that: 1. Manages client lifecycle with proper isolation between MCP clients 2. Orchestrates agent resolution, runtime creation, and session management 3. Enforces security boundaries and resource limits per client 4. Provides thread-safe operations for concurrent client access

Key Components: - Client management: Creates, tracks, and cleans up client sessions - Agent operations: Delegates to Resolver for secure agent specification handling - Session lifecycle: Coordinates Executor for runtime creation and message processing - Resource limits: Enforces maximum sessions per client and proper cleanup

Security Considerations: - All operations are client-scoped to prevent cross-client access - Agent resolution is restricted to configured root directories - Proper resource cleanup prevents memory leaks and zombie processes

The Manager acts as the single entry point for both MCP and future HTTP transports, ensuring consistent behavior and security across all access methods.

resolver.go implements secure agent specification resolution for cagent's multi-tenant architecture. This component handles the critical security boundary between external agent specifications and the cagent runtime system.

Core Responsibilities: 1. Agent specification resolution with multiple source priority:

  • File paths (absolute or relative to agents directory) - HIGHEST PRIORITY
  • Content store lookups (Docker images) - FALLBACK
  • Error reporting for missing agents - FINAL

2. Path security validation:

  • Restricts all file access to within a configured root directory
  • Prevents directory traversal attacks (../../../etc/passwd)
  • Blocks access to system files outside the allowed scope
  • Uses absolute path conversion with secure prefix matching

3. Agent discovery and metadata:

  • Lists available file-based agents with recursive directory scanning
  • Provides agent metadata for client consumption
  • Integrates with Docker registry pulling for remote agents

Security Architecture: The resolver implements defense-in-depth by: - Converting all paths to absolute form to eliminate relative path ambiguity - Using trailing separator prefix matching to prevent bypass attacks - Logging security violations for monitoring and audit - Failing secure by default (reject unsafe paths, don't expand home directories)

This component is essential for preventing MCP clients from accessing arbitrary files on the host system while maintaining usability for legitimate agent specifications.

store.go implements multi-tenant session storage for cagent's servicecore architecture. This component provides persistent storage with client isolation for MCP and HTTP clients.

Core Responsibilities: 1. Multi-Tenant Session Management:

  • Client-scoped session storage with mandatory client_id isolation
  • Backward-compatible database migration from single-tenant to multi-tenant
  • Session lifecycle tracking (creation, retrieval, updates, deletion)
  • Automatic cleanup when clients disconnect

2. Database Schema Evolution:

  • Non-breaking migration adding client_id column with '__global' default
  • Preserves existing sessions by assigning them to DEFAULT_CLIENT_ID
  • Performance optimization through proper indexing on client_id
  • PRAGMA-based schema introspection for safe migrations

3. Security and Isolation:

  • All operations require explicit client_id to prevent cross-client access
  • Input validation prevents empty client/session IDs
  • Structured error handling with specific error types
  • Defensive programming with proper resource cleanup

4. Integration with Existing Systems:

  • Maintains compatibility with pkg/session data structures
  • JSON serialization for message storage
  • RFC3339 timestamp formatting for consistent time handling
  • Bridge between servicecore types and legacy session storage

Client ID Strategy: - MCP clients: Use real client ID from MCP session context - HTTP clients: Use '__global' constant until authentication is added - Legacy sessions: Automatically inherit '__global' client ID

This component is essential for enabling true multi-tenant operation while maintaining backward compatibility with existing single-tenant deployments.

Package servicecore provides the core business logic layer for cagent's multi-tenant agent services. This package abstracts the complexity of agent resolution, runtime management, and session handling to provide a clean interface for both MCP and HTTP transport layers.

Key Design Principles: - Multi-tenant architecture: All operations are client-scoped to ensure isolation - Transport-agnostic: Core business logic is independent of MCP or HTTP specifics - Security-first: Agent resolution is restricted to configured root directories - Resource management: Proper cleanup and lifecycle management for runtimes and sessions

The types in this file define the core interfaces and data structures that enable: 1. Client isolation through explicit client IDs in all operations 2. Agent metadata representation across different sources (files, Docker images) 3. Structured response formatting with events and metadata 4. Session lifecycle management with proper resource tracking

Index

Constants

View Source
const DEFAULT_CLIENT_ID = "__global"

DEFAULT_CLIENT_ID is used for HTTP API compatibility and existing sessions

Variables

View Source
var (
	ErrClientNotFound  = errors.New("client not found")
	ErrSessionNotFound = errors.New("session not found")
	ErrEmptyClientID   = errors.New("client ID cannot be empty")
	ErrEmptySessionID  = errors.New("session ID cannot be empty")
)

Functions

This section is empty.

Types

type AgentInfo

type AgentInfo struct {
	Name         string `json:"name"`
	Description  string `json:"description"`
	Source       string `json:"source"`                  // "file", "store"
	Path         string `json:"path,omitempty"`          // Absolute path (for internal use)
	RelativePath string `json:"relative_path,omitempty"` // Relative path from agents dir (for user reference)
	Reference    string `json:"reference,omitempty"`     // Full image reference (for store agents)
}

AgentInfo represents metadata about an available agent

type AgentSession

type AgentSession struct {
	ID        string
	ClientID  string
	AgentSpec string
	Runtime   *runtime.Runtime
	Session   *session.Session
	Created   time.Time
	LastUsed  time.Time
}

AgentSession represents a conversational session with a specific agent

type Client

type Client struct {
	ID            string
	AgentSessions map[string]*AgentSession
	Created       time.Time
	LastUsed      time.Time
}

Client represents an MCP or HTTP client session

type Executor

type Executor struct {
}

Executor handles runtime creation and stream execution

func NewExecutor

func NewExecutor() *Executor

NewExecutor creates a new runtime executor

func (*Executor) CleanupRuntime

func (e *Executor) CleanupRuntime(rt *runtime.Runtime) error

CleanupRuntime cleans up runtime resources

func (*Executor) CreateRuntime

func (e *Executor) CreateRuntime(agentPath, agentName string, envFiles []string, gateway string) (*runtime.Runtime, *session.Session, error)

CreateRuntime creates a new runtime instance for an agent

func (*Executor) ExecuteStream

func (e *Executor) ExecuteStream(rt *runtime.Runtime, sess *session.Session, agentSpec, message string) (*Response, error)

ExecuteStream executes a message and collects streaming events into a response

type Manager

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

Manager implements ServiceManager with multi-tenant client and session management

func (*Manager) CloseSession

func (m *Manager) CloseSession(clientID, sessionID string) error

CloseSession closes an agent session

func (*Manager) CreateAgentSession

func (m *Manager) CreateAgentSession(clientID, agentSpec string) (*AgentSession, error)

CreateAgentSession creates a new agent session for a client

func (*Manager) CreateClient

func (m *Manager) CreateClient(clientID string) error

CreateClient creates a new client session

func (*Manager) GetSessionHistory

func (m *Manager) GetSessionHistory(clientID, sessionID string, limit int) ([]SessionMessage, error)

GetSessionHistory retrieves conversation history for an agent session with optional pagination

func (*Manager) GetSessionInfo

func (m *Manager) GetSessionInfo(clientID, sessionID string) (*SessionInfo, error)

GetSessionInfo retrieves detailed information about an agent session

func (*Manager) ListAgents

func (m *Manager) ListAgents(source string) ([]AgentInfo, error)

ListAgents lists available agents from files and store

func (*Manager) ListSessions

func (m *Manager) ListSessions(clientID string) ([]*AgentSession, error)

ListSessions lists all agent sessions for a client

func (*Manager) PullAgent

func (m *Manager) PullAgent(registryRef string) error

PullAgent pulls an agent image from registry to local store

func (*Manager) RemoveClient

func (m *Manager) RemoveClient(clientID string) error

RemoveClient removes a client and cleans up all associated sessions

func (*Manager) ResolveAgent

func (m *Manager) ResolveAgent(agentSpec string) (string, error)

ResolveAgent resolves an agent specification to a file path

func (*Manager) SendMessage

func (m *Manager) SendMessage(clientID, sessionID, message string) (*Response, error)

SendMessage sends a message to an agent session

type Resolver

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

Resolver handles agent specification resolution (file path, image reference, or store reference)

func NewResolver

func NewResolver(agentsDir string) (*Resolver, error)

NewResolver creates a new agent resolver with security root directory

func NewResolverWithStore

func NewResolverWithStore(agentsDir string, store *content.Store) (*Resolver, error)

NewResolverWithStore creates a new agent resolver with a custom store (for testing)

func (*Resolver) ListFileAgents

func (r *Resolver) ListFileAgents() ([]AgentInfo, error)

ListFileAgents lists agents available as files

func (*Resolver) ListStoreAgents

func (r *Resolver) ListStoreAgents() ([]AgentInfo, error)

ListStoreAgents lists agents available in the content store

func (*Resolver) PullAgent

func (r *Resolver) PullAgent(registryRef string) error

PullAgent pulls an agent image from registry to local store

func (*Resolver) ResolveAgent

func (r *Resolver) ResolveAgent(agentSpec string) (string, error)

ResolveAgent resolves an agent specification to a file path with security restrictions Priority: File path (within root) → Content store → Error

type Response

type Response struct {
	Content  string                 `json:"content"`
	Events   []runtime.Event        `json:"events"`
	Metadata map[string]interface{} `json:"metadata"`
}

Response represents a structured response from agent execution

type SQLiteStore

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

SQLiteStore implements Store using SQLite with multi-tenant support

func (*SQLiteStore) Close

func (s *SQLiteStore) Close() error

Close closes the database connection

func (*SQLiteStore) CreateClient

func (s *SQLiteStore) CreateClient(ctx context.Context, clientID string) error

CreateClient creates a client record (no-op for SQLite, clients are implicit)

func (*SQLiteStore) CreateSession

func (s *SQLiteStore) CreateSession(ctx context.Context, clientID string, agentSession *AgentSession) error

CreateSession creates a new agent session

func (*SQLiteStore) DeleteClient

func (s *SQLiteStore) DeleteClient(ctx context.Context, clientID string) error

DeleteClient removes all sessions for a client

func (*SQLiteStore) DeleteSession

func (s *SQLiteStore) DeleteSession(ctx context.Context, clientID, sessionID string) error

DeleteSession deletes a session

func (*SQLiteStore) GetSession

func (s *SQLiteStore) GetSession(ctx context.Context, clientID, sessionID string) (*AgentSession, error)

GetSession retrieves a session by client and session ID

func (*SQLiteStore) ListSessions

func (s *SQLiteStore) ListSessions(ctx context.Context, clientID string) ([]*AgentSession, error)

ListSessions lists all sessions for a client

func (*SQLiteStore) UpdateSession

func (s *SQLiteStore) UpdateSession(ctx context.Context, clientID string, agentSession *AgentSession) error

UpdateSession updates an existing session

type ServiceManager

type ServiceManager interface {
	// Client lifecycle
	CreateClient(clientID string) error
	RemoveClient(clientID string) error

	// Agent operations
	ResolveAgent(agentSpec string) (string, error)
	ListAgents(source string) ([]AgentInfo, error)
	PullAgent(registryRef string) error

	// Session operations (client-scoped)
	CreateAgentSession(clientID, agentSpec string) (*AgentSession, error)
	SendMessage(clientID, sessionID, message string) (*Response, error)
	ListSessions(clientID string) ([]*AgentSession, error)
	CloseSession(clientID, sessionID string) error

	// Advanced session operations
	GetSessionHistory(clientID, sessionID string, limit int) ([]SessionMessage, error)
	GetSessionInfo(clientID, sessionID string) (*SessionInfo, error)
}

ServiceManager defines the core interface for multi-tenant agent service operations

func NewManager

func NewManager(agentsDir string, timeout time.Duration, maxSessions int) (ServiceManager, error)

NewManager creates a new ServiceManager instance

func NewManagerWithResolver

func NewManagerWithResolver(resolver *Resolver, timeout time.Duration, maxSessions int) (ServiceManager, error)

NewManagerWithResolver creates a new ServiceManager instance with a custom resolver (for testing)

type SessionInfo

type SessionInfo struct {
	ID           string                 `json:"id"`
	ClientID     string                 `json:"client_id"`
	AgentSpec    string                 `json:"agent_spec"`
	Created      time.Time              `json:"created"`
	LastUsed     time.Time              `json:"last_used"`
	MessageCount int                    `json:"message_count"`
	Metadata     map[string]interface{} `json:"metadata"`
}

SessionInfo represents detailed information about a session

type SessionMessage

type SessionMessage struct {
	AgentName string    `json:"agent_name"`
	Role      string    `json:"role"`
	Content   string    `json:"content"`
	Timestamp time.Time `json:"timestamp,omitempty"`
}

SessionMessage represents a message in the conversation history

type Store

type Store interface {
	// Client operations
	CreateClient(ctx context.Context, clientID string) error
	DeleteClient(ctx context.Context, clientID string) error

	// Session operations (client-scoped)
	CreateSession(ctx context.Context, clientID string, session *AgentSession) error
	GetSession(ctx context.Context, clientID, sessionID string) (*AgentSession, error)
	ListSessions(ctx context.Context, clientID string) ([]*AgentSession, error)
	UpdateSession(ctx context.Context, clientID string, session *AgentSession) error
	DeleteSession(ctx context.Context, clientID, sessionID string) error
}

Store defines the interface for multi-tenant session storage

func NewSQLiteStore

func NewSQLiteStore(path string) (Store, error)

NewSQLiteStore creates a new SQLite store with multi-tenant support

Jump to

Keyboard shortcuts

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