Architecture Deep Dive
This document provides detailed architecture diagrams showing how Station’s services, APIs, and components interact.High-Level System Architecture
Copy
┌─────────────────────────────────────────────────────────────────────────┐
│ STATION PLATFORM │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ CLI Layer │ │ API Server │ │ MCP Server │ │
│ │ (cmd/main) │ │ (:8585) │ │ (stdio) │ │
│ │ │ │ │ │ │ │
│ │ • agent │ │ • /api/v1/agents │ │ • Tool handlers │ │
│ │ • bundle │ │ • /api/v1/envs │ │ • Agent handlers │ │
│ │ • env │ │ • /api/v1/runs │ │ • Resources │ │
│ │ • sync │ │ • /api/v1/mcp │ │ • Tool Discovery │ │
│ │ • runs │ │ • /api/v1/tools │ │ • Prompts │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │ │
│ └───────────────────────┼────────────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Service Layer │ │
│ │ (internal/services)│ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Environment System │ │
│ │ ~/.config/station/environments/<env>/ │ │
│ │ ├── template.json (MCP Server definitions) │ │
│ │ ├── variables.yml (Template variables) │ │
│ │ └── agents/ (Agent .prompt files) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ External Integration Layer │ │
│ │ • GenKit AI Models (OpenAI, Gemini, Ollama) │ │
│ │ • MCP Server Processes (filesystem, custom tools) │ │
│ │ • Lighthouse (CloudShip data ingestion & telemetry) │ │
│ │ • OpenTelemetry (Tracing & metrics) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Agent Execution Flow
All entry points converge at the AgentExecutionEngine:Copy
┌──────────────────────────────────────────────────────────────────────┐
│ AGENT EXECUTION PATHS │
└──────────────────────────────────────────────────────────────────────┘
CLI PATH: stn agent run <name> <task>
═══════════════════════════════════════════════════════════════════════
cmd/main/handlers/agent/execution.go
└─ RunAgentLocal()
│
├─ Load config
├─ Open database connection
└─ Call: agentExecutionEngine.ExecuteWithOptions()
API PATH: POST /api/v1/agents/:id/execute
═══════════════════════════════════════════════════════════════════════
internal/api/v1/agents.go
└─ executeAgent() handler
│
├─ Validate authentication
├─ Parse task from request body
└─ Call: agentService.ExecuteAgent()
MCP SERVER PATH: call_agent tool
═══════════════════════════════════════════════════════════════════════
internal/mcp/execution_handlers.go
└─ handleMCPAgentRun()
│
├─ Parse MCP tool call arguments
├─ Create AgentRun database entry
└─ Call: agentService.ExecuteAgentWithRunID()
SCHEDULER PATH: Cron-triggered execution
═══════════════════════════════════════════════════════════════════════
internal/services/scheduler.go
└─ SchedulerService.Start()
│
├─ Load scheduled agents from database
└─ At cron trigger:
└─ Call: agentService.ExecuteAgent()
AgentExecutionEngine Internals
The core execution engine orchestrates the full agent lifecycle:Copy
┌─ AgentExecutionEngine Key Responsibilities ─────────────────────────┐
│ │
│ File: /internal/services/agent_execution_engine.go │
│ │
│ 1. Agent Validation & Loading │
│ • Fetch agent from database │
│ • Validate agent exists and is configured │
│ • Get environment and tool assignments │
│ │
│ 2. Environment Setup │
│ • Load environment configuration │
│ • Load variables.yml for template processing │
│ • Validate environment exists │
│ │
│ 3. AI Model Configuration │
│ • Initialize GenKit with configured provider │
│ • Set up model-specific parameters │
│ • Handle model fallbacks if needed │
│ │
│ 4. MCP Server Connection │
│ • Create MCPConnectionManager instance │
│ • Connect to each MCP server in environment │
│ • Discover available tools per server │
│ • Cache tools for performance │
│ │
│ 5. Tool Preparation │
│ • Build complete tool list from all servers │
│ • Apply agent-specific tool assignments │
│ • Filter tools based on permissions │
│ │
│ 6. Execution │
│ • Render dotprompt template with variables │
│ • Pass task + tools to GenKit │
│ • Process iterative tool calls │
│ • Enforce max steps limit │
│ │
│ 7. Metadata Capture │
│ • Record all tool calls with parameters │
│ • Capture execution steps │
│ • Track token usage (input/output) │
│ • Measure execution duration │
│ │
│ 8. Lighthouse Integration (Optional) │
│ • Send run data to Lighthouse │
│ • Include app/app_type classification │
│ • Enable CloudShip data ingestion │
│ │
│ 9. Cleanup │
│ • Close all MCP connections │
│ • Release resources │
│ • Stop any running processes │
│ │
└──────────────────────────────────────────────────────────────────────┘
Service Layer Architecture
Station’s service layer contains 43+ focused modules:Copy
┌─────────────────────────────────────────────────────────────────────┐
│ CORE SERVICES LAYER │
│ /internal/services/ - 43 focused modules │
└─────────────────────────────────────────────────────────────────────┘
AGENT EXECUTION SERVICES
═════════════════════════════════════════════════════════════════════
AgentService (agent_service_impl.go)
├─ Creates/manages AgentExecutionEngine
├─ Wraps execution with telemetry
├─ Interface: AgentServiceInterface
└─ Methods:
├─ ExecuteAgent(agentID, task, variables) → Message
├─ ExecuteAgentWithRunID(agentID, task, runID, variables)
├─ CreateAgent(config) → Agent
├─ UpdateAgent(agentID, config) → Agent
└─ DeleteAgent(agentID)
AgentExecutionEngine (agent_execution_engine.go)
├─ Main execution orchestrator
├─ Manages GenKit + MCP lifecycle
└─ Methods:
├─ Execute(agent, task, runID, userVars)
└─ ExecuteWithOptions(agent, task, runID, userVars, opts)
GenKitProvider (genkit_provider.go)
├─ AI model provider initialization
├─ Supports: OpenAI, Gemini, Ollama
└─ Methods:
└─ InitializeGenKit() → *genkit.Genkit
MCP MANAGEMENT SERVICES
═════════════════════════════════════════════════════════════════════
MCPConnectionManager (mcp_connection_manager.go)
├─ Lifecycle management for MCP connections
├─ Tool discovery and caching
└─ Methods:
├─ DiscoverTools(envID, genkitApp)
├─ GetCachedTools(envID)
└─ CleanupConnections(clients)
MCPToolDiscovery (mcp_tool_discovery.go)
├─ Discovers tools from MCP servers
├─ Maps tools to servers
└─ Methods:
├─ DiscoverToolsPerServer(fileConfig)
└─ SaveToolsForServer(envID, serverName, tools)
ToolDiscoveryService (tool_discovery_service.go)
├─ High-level tool discovery orchestration
└─ Methods:
├─ DiscoverTools(envID) → []Tool
└─ RefreshTools(envID)
ENVIRONMENT & CONFIGURATION SERVICES
═════════════════════════════════════════════════════════════════════
EnvironmentManagementService (environment_management_service.go)
├─ Environment CRUD operations
├─ File-based configuration management
└─ Methods:
├─ CreateEnvironment(name, description)
├─ DeleteEnvironment(name)
└─ GetEnvironmentFileConfig(name)
DeclarativeSync (declarative_sync.go)
├─ Synchronizes file-based configs to database
├─ Bidirectional sync (files ↔ database)
├─ Template variable processing
└─ Methods:
├─ SyncEnvironment(ctx, envName, options)
├─ SyncAgents(ctx, envID)
└─ SyncMCPServers(ctx, envID)
SCHEDULING & AUTOMATION
═════════════════════════════════════════════════════════════════════
SchedulerService (scheduler.go)
├─ Cron-based agent scheduling (6-field cron)
├─ Persistent schedule storage
└─ Methods:
├─ Start() - loads and activates schedules
├─ Stop() - graceful shutdown
└─ ScheduleAgent(agentID, cronExpression)
TELEMETRY & MONITORING
═════════════════════════════════════════════════════════════════════
TelemetryService (telemetry_service.go)
├─ OpenTelemetry integration
├─ Span creation and tracking
└─ Methods:
├─ Initialize(ctx)
└─ CreateSpan(ctx, name, attributes)
MCP Server Architecture
Copy
┌──────────────────────────────────────────────────────────────────────┐
│ MCP SERVER SUBSYSTEM │
│ /internal/mcp/ - Model Context Protocol │
└──────────────────────────────────────────────────────────────────────┘
CORE MCP SERVER
═══════════════════════════════════════════════════════════════════════
MCP Server (mcp/server.go)
└─ Main MCP server instance
│
├─ Capabilities:
│ ├─ Tools (tool discovery & execution)
│ ├─ Resources (read-only data access)
│ ├─ Prompts (system prompts)
│ └─ Tool suggestions
│
└─ Core Components:
├─ mcpServer: *server.MCPServer (mark3labs/mcp-go)
├─ httpServer: *server.StreamableHTTPServer
├─ toolDiscoverySvc: *ToolDiscoveryService
├─ agentService: AgentServiceInterface
├─ authService: *auth.AuthService
└─ repos: *repositories.Repositories
HANDLER ORGANIZATION
═══════════════════════════════════════════════════════════════════════
/internal/mcp/
│
├─ server.go # Main server setup
│
├─ agent_handlers.go # Agent CRUD tools
│ ├─ call_agent # Execute an agent
│ ├─ list_agents # List all agents
│ ├─ get_agent_details # Get agent info
│ └─ create_agent # Create new agent
│
├─ environment_handlers.go # Environment tools
│ ├─ list_environments # List environments
│ ├─ create_environment # Create environment
│ └─ sync_environment # Sync from files
│
├─ mcp_handlers.go # MCP server management
│ ├─ add_mcp_server # Add MCP server
│ └─ list_mcp_servers # List servers
│
├─ tool_handlers.go # Tool management
│ ├─ list_tools # List all tools
│ ├─ discover_tools # Trigger discovery
│ └─ add_tool # Add tool to agent
│
└─ workflow_handlers.go # Workflow tools
├─ create_workflow # Create workflow
├─ start_workflow_run # Start execution
└─ get_workflow_run # Get run status
Database Layer
Copy
┌──────────────────────────────────────────────────────────────────────┐
│ DATABASE LAYER │
│ /internal/db/ - SQLite with Repositories │
└──────────────────────────────────────────────────────────────────────┘
REPOSITORY PATTERN
═══════════════════════════════════════════════════════════════════════
/internal/db/repositories/
│
├─ agent_repository.go # Agent CRUD
│ ├─ Create(agent) → id
│ ├─ GetByID(id) → Agent
│ ├─ GetByName(name) → Agent
│ ├─ Update(agent)
│ └─ Delete(id)
│
├─ agent_run_repository.go # Execution history
│ ├─ Create(run) → id
│ ├─ GetByID(id) → AgentRun
│ ├─ ListByAgent(agentID) → []AgentRun
│ └─ UpdateStatus(id, status)
│
├─ environment_repository.go # Environment CRUD
│ ├─ Create(env) → id
│ ├─ GetByName(name) → Environment
│ └─ List() → []Environment
│
├─ mcp_server_repository.go # MCP server configs
│ ├─ Create(server) → id
│ ├─ GetByEnvironment(envID) → []MCPServer
│ └─ Delete(id)
│
└─ tool_repository.go # Tool definitions
├─ Create(tool) → id
├─ GetByServer(serverID) → []Tool
└─ GetByAgent(agentID) → []Tool
SCHEMA (simplified)
═══════════════════════════════════════════════════════════════════════
environments
├─ id (INTEGER PRIMARY KEY)
├─ name (TEXT UNIQUE)
├─ description (TEXT)
└─ created_at (DATETIME)
agents
├─ id (INTEGER PRIMARY KEY)
├─ environment_id (FOREIGN KEY)
├─ name (TEXT)
├─ prompt (TEXT)
├─ max_steps (INTEGER)
└─ created_at (DATETIME)
agent_runs
├─ id (TEXT PRIMARY KEY) -- UUID
├─ agent_id (FOREIGN KEY)
├─ task (TEXT)
├─ status (TEXT)
├─ response (TEXT)
├─ tool_calls (JSON)
├─ tokens_used (INTEGER)
├─ duration_ms (INTEGER)
└─ created_at (DATETIME)
mcp_servers
├─ id (INTEGER PRIMARY KEY)
├─ environment_id (FOREIGN KEY)
├─ name (TEXT)
├─ command (TEXT)
├─ args (JSON)
└─ env_vars (JSON)
tools
├─ id (INTEGER PRIMARY KEY)
├─ mcp_server_id (FOREIGN KEY)
├─ name (TEXT)
├─ description (TEXT)
└─ input_schema (JSON)
Request Flow Example
Complete flow forstn agent run analyzer "Check logs":
Copy
┌─────────────────────────────────────────────────────────────────────┐
│ REQUEST FLOW EXAMPLE │
│ stn agent run analyzer "Check logs" │
└─────────────────────────────────────────────────────────────────────┘
1. CLI ENTRY
cmd/main/main.go
└─ Parse command: "agent run analyzer 'Check logs'"
2. HANDLER
cmd/main/handlers/agent/execution.go
└─ RunAgentLocal()
├─ Load config.yaml
├─ Open database
└─ agentService.ExecuteAgent("analyzer", "Check logs")
3. SERVICE LAYER
internal/services/agent_service_impl.go
└─ ExecuteAgent()
├─ Get agent from database
├─ Create AgentRun record (status: "running")
└─ engine.ExecuteWithOptions(agent, task)
4. EXECUTION ENGINE
internal/services/agent_execution_engine.go
└─ ExecuteWithOptions()
│
├─ Load environment config
├─ Initialize GenKit (OpenAI/Gemini)
│
├─ MCPConnectionManager.DiscoverTools()
│ ├─ Connect to MCP servers
│ ├─ Call listTools on each
│ └─ Cache tools
│
├─ Build tool list for agent
│
└─ GenKit.Generate(prompt + task + tools)
│
├─ AI model processes request
├─ Returns tool call: {"name": "grep", "args": {...}}
│
└─ Execute tool via MCP
├─ Route to correct MCP server
├─ Execute grep tool
└─ Return results to AI
└─ AI generates final response
5. RESULT CAPTURE
└─ Update AgentRun
├─ status: "completed"
├─ response: "Found 3 errors in logs..."
├─ tool_calls: [{name: "grep", ...}]
├─ tokens_used: 1234
└─ duration_ms: 5678
6. LIGHTHOUSE (if configured)
└─ Send run data to CloudShip
├─ Include structured output
└─ Enable platform features
7. OUTPUT
└─ Print response to terminal
Key Design Decisions
| Decision | Rationale |
|---|---|
| Single execution engine | All entry points use the same logic |
| File-based config + DB | GitOps-friendly, yet queryable |
| MCP for tools | Standard protocol, extensible |
| GenKit abstraction | Swap AI providers easily |
| 6-field cron | Second-level precision for scheduling |
| SQLite default | Zero-config, portable, cloud-upgradable |

