OSSA Agents Remote Execution Architecture
OSSA Agents Remote Execution Architecture
šÆ Goal: Run 20 OSSA Agents on NAS + Vast.ai via GitLab Duo
GitLab Duo Chat/Workflows
ā Invokes agent
GitLab CI/CD Pipeline
ā Custom executor selects runtime
āāā NAS Docker (lightweight agents)
ā āā mr-reviewer, code-quality-reviewer, ossa-validator
āāā Vast.ai GPU (heavy AI agents)
āā vulnerability-scanner, issue-lifecycle-manager, drupal-standards-checker
Architecture
Layer 1: GitLab Duo ā Agent Invocation
User interacts with GitLab Duo:
// In GitLab Duo Chat /duo review MR !123 // GitLab Duo creates workflow POST /api/v4/ai/duo_workflows/workflows { "goal": "Review MR !123", "agent_config": { "name": "mr-reviewer", "capabilities": ["code_analysis"] } }
Layer 2: GitLab CI/CD Pipeline
GitLab creates CI job for agent:
# Auto-generated by GitLab Duo .gitlab-ci.yml: agent-execution: stage: execute tags: - ossa-agent-runner variables: AGENT_NAME: mr-reviewer AGENT_GOAL: "Review MR !123" EXECUTION_MODE: docker # or vast-ai script: - tsx /builds/agent-executor.ts
Layer 3: Custom Executor (On NAS)
Runner decides where to execute:
// infrastructure/gitlab-runner/drivers/prepare.ts import { z } from 'zod'; const JobConfigSchema = z.object({ agent_name: z.string(), agent_goal: z.string(), execution_mode: z.enum(['docker', 'vast-ai']), }); async function prepare() { const config = JobConfigSchema.parse(process.env); // Load agent manifest const agent = await loadAgentManifest(config.agent_name); // Decide execution environment if (needsGPU(agent) || config.execution_mode === 'vast-ai') { return prepareVastAI(agent); } else { return prepareDocker(agent); } } function needsGPU(agent: AgentManifest): boolean { // Check if agent needs GPU const gpuAgents = [ 'vulnerability-scanner', 'issue-lifecycle-manager', 'drupal-standards-checker', 'module-generator', ]; return gpuAgents.includes(agent.metadata.name); }
Layer 4a: Docker Execution (NAS)
Lightweight agents run in NAS Docker:
// infrastructure/gitlab-runner/drivers/run.ts import { Gitlab } from '@gitbeaker/rest'; async function runDocker() { const agentName = process.env.AGENT_NAME; const agentGoal = process.env.AGENT_GOAL; // Load service account credentials const mapping = await loadServiceAccountMapping(); const agent = mapping.agents.find(a => a.agent_id === agentName); const token = process.env[agent.token_var]; // Initialize GitLab client const gitlab = new Gitlab({ token }); // Execute agent in Docker const result = await execDocker([ 'docker', 'run', '--rm', '-e', `GITLAB_TOKEN=${token}`, '-e', `AGENT_GOAL=${agentGoal}`, '-v', '/volume1/agent-builds:/builds', `registry.gitlab.com/blueflyio/agent-platform/agent-registry/${agentName}:latest`, ]); return result; }
Layer 4b: Vast.ai Execution (GPU)
Heavy AI agents run on Vast.ai GPU:
// infrastructure/gitlab-runner/drivers/run-vast.ts import { z } from 'zod'; const VastConfigSchema = z.object({ api_key: z.string(), image: z.string(), gpu_count: z.number().default(1), disk_space: z.number().default(20), }); async function runVastAI() { const agentName = process.env.AGENT_NAME; const agentGoal = process.env.AGENT_GOAL; // Get service account token const mapping = await loadServiceAccountMapping(); const agent = mapping.agents.find(a => a.agent_id === agentName); const token = process.env[agent.token_var]; // Create Vast.ai instance const instance = await createVastInstance({ api_key: process.env.VAST_API_KEY, image: `registry.gitlab.com/blueflyio/agent-platform/agent-registry/${agentName}:gpu`, gpu_count: 1, disk_space: 20, env: { GITLAB_TOKEN: token, AGENT_GOAL: agentGoal, OPENAI_API_KEY: process.env.OPENAI_API_KEY, }, }); // Wait for execution const result = await waitForCompletion(instance.id); // Cleanup await destroyVastInstance(instance.id); return result; } async function createVastInstance(config: VastConfig) { const response = await fetch('https://console.vast.ai/api/v0/asks/', { method: 'POST', headers: { 'Authorization': `Bearer ${config.api_key}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ client_id: 'gitlab-runner', image: config.image, gpu_name: 'RTX_4090', num_gpus: config.gpu_count, disk_space: config.disk_space, env: config.env, }), }); return response.json(); }
Agent Container Images
Docker Images (One per agent)
Build script:
// infrastructure/gitlab-runner/build-agent-images.ts import { readFile } from 'fs/promises'; async function buildAgentImages() { const mapping = await loadServiceAccountMapping(); for (const agent of mapping.agents) { if (agent.status !== 'mapped') continue; // Build Docker image await exec([ 'docker', 'build', '-t', `registry.gitlab.com/blueflyio/agent-platform/agent-registry/${agent.agent_id}:latest`, '-f', `packages/@ossa/${agent.package}/Dockerfile`, '.', ]); // Build GPU variant if needed if (needsGPU(agent.agent_id)) { await exec([ 'docker', 'build', '-t', `registry.gitlab.com/blueflyio/agent-platform/agent-registry/${agent.agent_id}:gpu`, '-f', `packages/@ossa/${agent.package}/Dockerfile.gpu`, '.', ]); } // Push to GitLab Container Registry await exec(['docker', 'push', `registry.gitlab.com/blueflyio/agent-platform/agent-registry/${agent.agent_id}:latest`]); } }
Agent Dockerfile Template
# packages/@ossa/mr-reviewer/Dockerfile FROM node:20-alpine WORKDIR /agent # Copy package files COPY package.json package-lock.json ./ RUN npm ci --production # Copy agent code COPY packages/@ossa/mr-reviewer ./agent COPY src/observability ./src/observability COPY service-account-mapping.json ./ # Install dependencies RUN npm install @gitbeaker/rest @anthropic-ai/sdk zod # Set entrypoint CMD ["node", "agent/src/index.js"]
GPU Dockerfile Template
# packages/@ossa/vulnerability-scanner/Dockerfile.gpu FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04 # Install Node.js RUN apt-get update && apt-get install -y nodejs npm WORKDIR /agent # Copy agent code COPY packages/@ossa/vulnerability-scanner ./agent COPY src/observability ./src/observability COPY service-account-mapping.json ./ # Install GPU-accelerated dependencies RUN pip install transformers torch accelerate # Set entrypoint CMD ["node", "agent/src/index.js"]
Agent Execution Flow
1. User Invokes Agent (GitLab Duo Chat)
User: /duo review !123
GitLab Duo: Creates workflow for mr-reviewer agent
2. GitLab Duo ā CI Pipeline
# Auto-generated .gitlab-ci.yml agent-mr-reviewer: stage: execute tags: - ossa-agent-runner # Custom runner on NAS variables: AGENT_NAME: mr-reviewer AGENT_GOAL: "Review MR !123" script: - echo "Executing agent..."
3. Custom Runner (NAS) Receives Job
GitLab Runner on NAS:
1. Receives job
2. Runs prepare.ts ā Selects Docker (lightweight)
3. Runs run.ts ā Executes in Docker
4. Returns result to GitLab
4. Agent Executes with Service Account
// Inside container const gitlab = new Gitlab({ token: process.env.SA_TOKEN_MR_REVIEWER, }); const mr = await gitlab.MergeRequests.show(projectId, 123); const review = await analyzeMR(mr); await gitlab.MergeRequestNotes.create(projectId, 123, { body: formatReview(review), });
5. Results ā GitLab Duo ā User
GitLab Duo Chat:
ā
MR Review Complete!
- 3 suggestions for improvement
- 1 security concern (SQL injection risk)
- Code quality: 8/10
Deployment
Step 1: Deploy GitLab Runner on NAS
cd infrastructure/gitlab-runner # Set environment variables export GITLAB_RUNNER_TOKEN="your-runner-token" export VAST_API_KEY="your-vast-api-key" # Deploy via Docker Compose docker-compose up -d # Register runner docker exec gitlab-runner-custom gitlab-runner register \ --url https://gitlab.com/ \ --registration-token $GITLAB_RUNNER_TOKEN \ --name "NAS Custom Executor" \ --tag-list "ossa-agent-runner" \ --executor custom
Step 2: Build Agent Images
# Build all 20 agent images npm run build:agent-images # Push to GitLab Container Registry npm run push:agent-images
Step 3: Configure GitLab Project
# .gitlab-ci.yml in your project include: - component: $CI_SERVER_FQDN/blueflyio/gitlab-agent-platform/ossa-runner@v1.0.0 variables: OSSA_RUNNER_TAG: ossa-agent-runner
Step 4: Test Agent Execution
# Trigger agent via GitLab Duo # In GitLab Duo Chat: /duo review !123 # OR via API curl -X POST "https://gitlab.com/api/v4/ai/duo_workflows/workflows" \ -H "PRIVATE-TOKEN: $GITLAB_PAT" \ -d '{ "project_id": 12345, "goal": "Review MR !123", "agent_config": { "name": "mr-reviewer", "capabilities": ["code_analysis"] } }'
Monitoring
Agent Executions in GitLab
GitLab ā Monitor ā Observability:
- See all agent executions as traces
- View span details
- Track performance
- Cost per execution
A2A Communication
A2A Collector tracks inter-agent communication:
mr-reviewer ā code-quality-reviewer ā ossa-validator
All logged to:
/volume1/a2a/logs/YYYY/MM/DD/- Exported to GitLab Ultimate
Cost Optimization
Docker (NAS) - $0/execution
- Free (runs on your hardware)
- Fast startup (<2s)
- Good for lightweight agents
Vast.ai (GPU) - $0.10-$0.50/execution
- Pay per minute ($0.20/hr average)
- Powerful GPUs (RTX 4090)
- Good for heavy AI workloads
Auto-selection Logic
function selectExecutor(agent: AgentManifest): 'docker' | 'vast-ai' { // High token usage ā GPU if (agent.spec.llm.max_tokens > 8000) { return 'vast-ai'; } // Complex reasoning ā GPU if (agent.spec.llm.reasoning_enabled) { return 'vast-ai'; } // Default ā Docker (NAS) return 'docker'; }
Summary
ā 20 OSSA agents execute on NAS + Vast.ai ā GitLab Duo invokes agents via workflows ā Custom runner routes to Docker or GPU ā Service accounts authenticate with GitLab ā A2A collector tracks inter-agent communication ā GitLab Ultimate monitors all executions ā Cost optimized - NAS for light, GPU for heavy
YOU CAN NOW ASK GITLAB DUO TO RUN YOUR AGENTS!