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
- Variables
- type AgentInfo
- type AgentSession
- type Client
- type Executor
- func (e *Executor) CleanupRuntime(rt *runtime.Runtime) error
- func (e *Executor) CreateRuntime(agentPath, agentName string, envFiles []string, gateway string) (*runtime.Runtime, *session.Session, error)
- func (e *Executor) ExecuteStream(rt *runtime.Runtime, sess *session.Session, agentSpec, message string) (*Response, error)
- type Manager
- func (m *Manager) CloseSession(clientID, sessionID string) error
- func (m *Manager) CreateAgentSession(clientID, agentSpec string) (*AgentSession, error)
- func (m *Manager) CreateClient(clientID string) error
- func (m *Manager) GetSessionHistory(clientID, sessionID string, limit int) ([]SessionMessage, error)
- func (m *Manager) GetSessionInfo(clientID, sessionID string) (*SessionInfo, error)
- func (m *Manager) ListAgents(source string) ([]AgentInfo, error)
- func (m *Manager) ListSessions(clientID string) ([]*AgentSession, error)
- func (m *Manager) PullAgent(registryRef string) error
- func (m *Manager) RemoveClient(clientID string) error
- func (m *Manager) ResolveAgent(agentSpec string) (string, error)
- func (m *Manager) SendMessage(clientID, sessionID, message string) (*Response, error)
- type Resolver
- type Response
- type SQLiteStore
- func (s *SQLiteStore) Close() error
- func (s *SQLiteStore) CreateClient(ctx context.Context, clientID string) error
- func (s *SQLiteStore) CreateSession(ctx context.Context, clientID string, agentSession *AgentSession) error
- func (s *SQLiteStore) DeleteClient(ctx context.Context, clientID string) error
- func (s *SQLiteStore) DeleteSession(ctx context.Context, clientID, sessionID string) error
- func (s *SQLiteStore) GetSession(ctx context.Context, clientID, sessionID string) (*AgentSession, error)
- func (s *SQLiteStore) ListSessions(ctx context.Context, clientID string) ([]*AgentSession, error)
- func (s *SQLiteStore) UpdateSession(ctx context.Context, clientID string, agentSession *AgentSession) error
- type ServiceManager
- type SessionInfo
- type SessionMessage
- type Store
Constants ¶
const DEFAULT_CLIENT_ID = "__global"
DEFAULT_CLIENT_ID is used for HTTP API compatibility and existing sessions
Variables ¶
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 (*Executor) CleanupRuntime ¶
CleanupRuntime cleans up runtime resources
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager implements ServiceManager with multi-tenant client and session management
func (*Manager) CloseSession ¶
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 ¶
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 ¶
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) RemoveClient ¶
RemoveClient removes a client and cleans up all associated sessions
func (*Manager) ResolveAgent ¶
ResolveAgent resolves an agent specification to a file path
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver handles agent specification resolution (file path, image reference, or store reference)
func NewResolver ¶
NewResolver creates a new agent resolver with security root directory
func NewResolverWithStore ¶
NewResolverWithStore creates a new agent resolver with a custom store (for testing)
func (*Resolver) ListFileAgents ¶
ListFileAgents lists agents available as files
func (*Resolver) ListStoreAgents ¶
ListStoreAgents lists agents available in the content store
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 ¶
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 ¶
NewSQLiteStore creates a new SQLite store with multi-tenant support