Skip to main content

Overview

This runbook covers operational procedures for managing SO1 engineering agents, including Hono API development, Next.js frontend component creation, and TypeScript shared library maintenance. These procedures ensure consistent code quality and development velocity across the platform. Purpose: Provide step-by-step instructions for using engineering agents in development workflows Scope: API endpoint development, frontend components, shared TypeScript packages, code generation Target Audience: Software engineers, frontend developers, backend developers

Prerequisites

  • GitHub repository access (so1-io/control-plane, so1-io/console, so1-io/shared)
  • Control Plane API access (CONTROL_PLANE_API_KEY)
  • Railway project access (API deployments)
  • Vercel project access (Console deployments)
  • npm registry access (for shared packages)
  • Node.js 20+ and npm/pnpm
  • TypeScript 5.0+
  • OpenCode with engineering agents installed
  • Git CLI
  • Docker (for local testing)
  • TypeScript/JavaScript fundamentals
  • Understanding of Hono framework (API backend)
  • Familiarity with Next.js 14+ (App Router)
  • REST API design principles
  • Component-driven architecture

Procedure 1: Create Hono API Endpoint

Step 1: Design API Specification

Define the endpoint requirements:
// API Specification
interface EndpointSpec {
  path: '/api/v1/workflows/:id';
  method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
  authentication: 'bearer_token';
  rateLimit: '100/minute';
  requestSchema: {
    /* Zod schema */
  };
  responseSchema: {
    /* Zod schema */
  };
}

Step 2: Invoke Hono Backend Agent

curl -X POST https://control-plane.so1.io/api/v1/agents/hono-backend/generate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint": {
      "path": "/api/v1/workflows/:id",
      "method": "GET",
      "description": "Retrieve workflow details by ID",
      "authentication": "bearer",
      "parameters": {
        "id": {
          "type": "string",
          "description": "Workflow UUID",
          "validation": "uuid"
        }
      },
      "response": {
        "200": {
          "workflow_id": "string",
          "name": "string",
          "status": "enum[active,inactive,failed]",
          "created_at": "datetime"
        },
        "404": {
          "error": "string",
          "message": "Workflow not found"
        }
      }
    },
    "database": "postgresql",
    "orm": "drizzle",
    "include_tests": true
  }' | jq '.'
Expected Response:
{
  "generation_id": "gen_5Xy9mPqRs",
  "files": [
    {
      "path": "src/routes/workflows.ts",
      "content": "// Generated Hono route handler..."
    },
    {
      "path": "src/schemas/workflow.ts",
      "content": "// Zod validation schemas..."
    },
    {
      "path": "src/tests/workflows.test.ts",
      "content": "// Vitest test suite..."
    }
  ],
  "dependencies": ["zod", "@hono/zod-validator", "drizzle-orm"],
  "migration": {
    "path": "drizzle/migrations/0001_add_workflows.sql",
    "content": "-- Database migration..."
  }
}

Step 3: Review and Integrate Generated Code

# Save generated files
curl -s https://control-plane.so1.io/api/v1/agents/hono-backend/generations/gen_5Xy9mPqRs/files \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  | jq -r '.files[] | @json' | while read -r file; do
    path=$(echo "$file" | jq -r '.path')
    content=$(echo "$file" | jq -r '.content')
    mkdir -p "$(dirname "$path")"
    echo "$content" > "$path"
done

# Install new dependencies
npm install zod @hono/zod-validator

# Run database migration
npm run db:migrate

Step 4: Test Generated Endpoint

# Run tests
npm test src/tests/workflows.test.ts

# Start dev server
npm run dev

# Test endpoint locally
curl -s http://localhost:3000/api/v1/workflows/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" | jq '.'

Step 5: Deploy to Railway

See Deployment Runbook for full deployment procedures.
# Quick deployment
railway up --service control-plane-api

# Verify deployment
curl -s https://control-plane.so1.io/api/v1/workflows/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" | jq '.status'

Procedure 2: Create Next.js Frontend Component

Step 1: Define Component Requirements

// Component Specification
interface ComponentSpec {
  name: 'WorkflowCard';
  type: 'server' | 'client';
  props: {
    workflow: {
      id: string;
      name: string;
      status: 'active' | 'inactive' | 'failed';
    };
    onEdit?: () => void;
  };
  styling: 'tailwind';
  accessibility: 'wcag-aa';
}

Step 2: Invoke Next.js Frontend Agent

curl -X POST https://control-plane.so1.io/api/v1/agents/nextjs-frontend/generate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "component": {
      "name": "WorkflowCard",
      "type": "client",
      "description": "Display workflow summary with status badge and edit button",
      "props": {
        "workflow": {
          "type": "object",
          "properties": {
            "id": "string",
            "name": "string",
            "status": "enum"
          }
        },
        "onEdit": {
          "type": "function",
          "optional": true
        }
      },
      "features": [
        "status_badge_with_color_coding",
        "edit_button_with_icon",
        "responsive_layout",
        "loading_skeleton",
        "error_boundary"
      ],
      "styling": "tailwind",
      "accessibility": "wcag-aa"
    },
    "framework_version": "next@14",
    "include_tests": true,
    "include_storybook": true
  }' | jq '.'
Expected Response:
{
  "generation_id": "gen_7TnVw9Kj2m",
  "files": [
    {
      "path": "src/components/WorkflowCard/WorkflowCard.tsx",
      "content": "// React component..."
    },
    {
      "path": "src/components/WorkflowCard/WorkflowCard.test.tsx",
      "content": "// Jest/Testing Library tests..."
    },
    {
      "path": "src/components/WorkflowCard/WorkflowCard.stories.tsx",
      "content": "// Storybook stories..."
    },
    {
      "path": "src/components/WorkflowCard/index.ts",
      "content": "export { WorkflowCard } from './WorkflowCard';"
    }
  ],
  "dependencies": ["lucide-react", "clsx"]
}

Step 3: Review Generated Component

// Generated by nextjs-frontend agent
'use client';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Edit } from 'lucide-react';
import { clsx } from 'clsx';

interface WorkflowCardProps {
  workflow: {
    id: string;
    name: string;
    status: 'active' | 'inactive' | 'failed';
  };
  onEdit?: () => void;
}

export function WorkflowCard({ workflow, onEdit }: WorkflowCardProps) {
  const statusColors = {
    active: 'bg-green-100 text-green-800',
    inactive: 'bg-gray-100 text-gray-800',
    failed: 'bg-red-100 text-red-800',
  };

  return (
    <Card className="w-full hover:shadow-md transition-shadow">
      <CardHeader className="flex flex-row items-center justify-between">
        <CardTitle className="text-lg font-semibold">{workflow.name}</CardTitle>
        {onEdit && (
          <Button
            variant="ghost"
            size="icon"
            onClick={onEdit}
            aria-label={`Edit ${workflow.name}`}
          >
            <Edit className="h-4 w-4" />
          </Button>
        )}
      </CardHeader>
      <CardContent>
        <Badge className={clsx(statusColors[workflow.status])}>
          {workflow.status}
        </Badge>
      </CardContent>
    </Card>
  );
}

Step 4: Test Component

# Run component tests
npm test -- WorkflowCard.test.tsx

# Run Storybook for visual testing
npm run storybook

# Open: http://localhost:6006/?path=/story/components-workflowcard--default

Step 5: Integrate into Application

// app/workflows/page.tsx
import { WorkflowCard } from '@/components/WorkflowCard';

export default async function WorkflowsPage() {
  const workflows = await fetchWorkflows();

  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
      {workflows.map((workflow) => (
        <WorkflowCard
          key={workflow.id}
          workflow={workflow}
          onEdit={() => router.push(`/workflows/${workflow.id}/edit`)}
        />
      ))}
    </div>
  );
}

Procedure 3: Manage TypeScript Shared Library

Step 1: Create Shared Type Definitions

curl -X POST https://control-plane.so1.io/api/v1/agents/typescript-shared/generate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "package_name": "@so1/types",
    "types": [
      {
        "name": "Workflow",
        "description": "Core workflow type used across Control Plane and Console",
        "properties": {
          "id": "string (uuid)",
          "name": "string",
          "status": "WorkflowStatus enum",
          "agents": "Agent[]",
          "created_at": "Date",
          "updated_at": "Date"
        },
        "export": "named"
      },
      {
        "name": "WorkflowStatus",
        "type": "enum",
        "values": ["active", "inactive", "failed", "pending"]
      }
    ],
    "output_format": "typescript",
    "include_zod_schemas": true,
    "include_json_schema": true
  }' | jq '.'
Expected Response:
{
  "generation_id": "gen_2mP7nQzXy",
  "files": [
    {
      "path": "packages/types/src/workflow.ts",
      "content": "// TypeScript types..."
    },
    {
      "path": "packages/types/src/workflow.schema.ts",
      "content": "// Zod schemas..."
    },
    {
      "path": "packages/types/src/workflow.json",
      "content": "// JSON Schema..."
    },
    {
      "path": "packages/types/src/index.ts",
      "content": "export * from './workflow';"
    }
  ]
}

Step 2: Review Generated Types

// Generated by typescript-shared agent
// packages/types/src/workflow.ts

/**
 * Core workflow type used across Control Plane and Console
 */
export interface Workflow {
  /** Unique identifier (UUID v4) */
  id: string;
  
  /** Human-readable workflow name */
  name: string;
  
  /** Current workflow execution status */
  status: WorkflowStatus;
  
  /** List of agents involved in this workflow */
  agents: Agent[];
  
  /** Workflow creation timestamp */
  created_at: Date;
  
  /** Last update timestamp */
  updated_at: Date;
}

/**
 * Possible workflow execution states
 */
export enum WorkflowStatus {
  Active = 'active',
  Inactive = 'inactive',
  Failed = 'failed',
  Pending = 'pending',
}

// Zod schema for runtime validation
import { z } from 'zod';

export const WorkflowSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1).max(255),
  status: z.nativeEnum(WorkflowStatus),
  agents: z.array(AgentSchema),
  created_at: z.date(),
  updated_at: z.date(),
});

Step 3: Publish Shared Package

# Navigate to shared types package
cd packages/types

# Build package
npm run build

# Update version
npm version patch -m "Add Workflow types"

# Publish to npm registry (or GitHub Packages)
npm publish --access public

# Tag release
git tag -a "@so1/types@1.2.3" -m "Add Workflow types"
git push origin "@so1/types@1.2.3"

Step 4: Update Consuming Projects

# In Control Plane API
cd ../../control-plane-api
npm install @so1/types@latest
npm run type-check

# In Console
cd ../console
npm install @so1/types@latest
npm run type-check

Step 5: Verify Type Consistency

# Run type compatibility tests
curl -X POST https://control-plane.so1.io/api/v1/agents/typescript-shared/validate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "package": "@so1/types@1.2.3",
    "consumers": [
      "control-plane-api",
      "console",
      "n8n-workflows"
    ],
    "check_breaking_changes": true
  }' | jq '.'

Procedure 4: Code Review and Quality Checks

Step 1: Run Automated Quality Checks

# Type checking
npm run type-check

# Linting
npm run lint

# Unit tests
npm test

# Integration tests
npm run test:integration

# Code coverage
npm run test:coverage

Step 2: Review Agent-Generated Code

Quality Checklist:

Step 3: Run Security Scan

# Dependency vulnerability scan
npm audit

# Fix vulnerabilities
npm audit fix

# Check for secrets in code
npx secretlint "**/*"

# Static analysis
npx eslint . --ext .ts,.tsx

Step 4: Performance Testing

# API endpoint load testing
npx autocannon -c 100 -d 30 http://localhost:3000/api/v1/workflows

# Frontend bundle size analysis
npm run build
npx next-bundle-analyzer

# Lighthouse audit (for Console)
npx lighthouse https://console.so1.io --output html --output-path ./lighthouse-report.html

Verification Checklist

After completing engineering operations, verify:

Troubleshooting

Issue: Generated Code Has Type Errors

Symptoms: TypeScript compiler errors in agent-generated code Possible Causes:
  • Outdated agent generation templates
  • Incompatible TypeScript version
  • Missing type definitions
Resolution:
# Update TypeScript and type definitions
npm install -D typescript@latest @types/node@latest

# Regenerate code with updated agent
curl -X POST https://control-plane.so1.io/api/v1/agents/hono-backend/regenerate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -d '{
    "generation_id": "gen_5Xy9mPqRs",
    "typescript_version": "5.3.0",
    "strict_mode": true
  }'

# Run type checking with verbose output
npx tsc --noEmit --pretty

Issue: Frontend Component Not Rendering

Symptoms: Component shows blank or throws runtime error Possible Causes:
  • Missing CSS imports
  • Client/Server component mismatch
  • Hydration errors
Resolution:
# Check browser console for errors
# Common fixes:

# 1. Add 'use client' directive for client components
echo "'use client';" | cat - src/components/WorkflowCard/WorkflowCard.tsx > temp && mv temp src/components/WorkflowCard/WorkflowCard.tsx

# 2. Ensure Tailwind config includes component paths
# tailwind.config.js
content: [
  './src/components/**/*.{js,ts,jsx,tsx}',
]

# 3. Check Next.js error overlay
npm run dev
# Navigate to http://localhost:3000

Issue: Shared Types Version Mismatch

Symptoms: Type errors when consuming shared package in multiple projects Possible Causes:
  • Different versions of @so1/types installed
  • Breaking changes not communicated
Resolution:
# Check installed versions across projects
for project in control-plane-api console n8n-workflows; do
  echo "=== $project ==="
  cd ../$project
  npm list @so1/types
done

# Update all projects to same version
VERSION="1.2.3"
for project in control-plane-api console n8n-workflows; do
  cd ../$project
  npm install @so1/types@$VERSION
done

# Verify compatibility
curl -X POST https://control-plane.so1.io/api/v1/agents/typescript-shared/validate \
  -H "Authorization: Bearer ${CONTROL_PLANE_API_KEY}" \
  -d '{"check_breaking_changes": true}'


Best Practices

API Development

  1. Always use Zod schemas for request/response validation
  2. Implement rate limiting on all public endpoints (use @hono/rate-limiter)
  3. Return consistent error formats:
    {
      "error": "validation_error",
      "message": "Invalid workflow ID",
      "details": { "field": "id", "issue": "must be UUID" }
    }
    
  4. Use proper HTTP status codes: 200 (success), 201 (created), 400 (validation), 401 (auth), 404 (not found), 500 (server error)
  5. Document endpoints with OpenAPI/Swagger annotations

Frontend Development

  1. Prefer Server Components unless interactivity is required
  2. Use TypeScript strict mode (strict: true in tsconfig.json)
  3. Implement loading states for all async operations
  4. Add error boundaries around component trees
  5. Follow accessibility guidelines: ARIA labels, keyboard navigation, focus management
  6. Optimize images: Use Next.js <Image> component with proper sizing

Shared Library Management

  1. Use semantic versioning: Major (breaking), Minor (features), Patch (fixes)
  2. Document breaking changes in CHANGELOG.md
  3. Keep dependencies minimal in shared packages
  4. Export both TypeScript types and Zod schemas for runtime validation
  5. Write migration guides when introducing breaking changes