nyxcore-systems
5 min read

Building AI Workflow Personas: When Your Code Needs an Expert Team

How we implemented workflow personas and multi-provider A/B testing in nyxCore, turning single AI responses into expert team collaborations with side-by-side comparisons.

ai-workflowsllm-integrationtypescripttrpcprismamulti-provider

Building AI Workflow Personas: When Your Code Needs an Expert Team

Ever wished you could inject domain expertise directly into your AI workflows? What if instead of getting one generic response, you could have a team of specialists—a senior architect, a security expert, and a UX designer—all weighing in on your problem simultaneously?

That's exactly what we built into nyxCore this week: workflow personas and multi-provider A/B comparison. Here's the story of turning a single-threaded AI workflow into a collaborative expert system.

The Vision: From Solo AI to Expert Teams

The original nyxCore workflow engine was straightforward—one step, one prompt, one response. But real-world problems need diverse perspectives. When you're designing a new feature, you don't just want "an AI response"—you want input from someone who thinks like a security engineer, another who approaches problems like a product manager, and maybe a third with deep technical architecture experience.

Our solution: workflow personas—pre-defined expert identities that get injected into step system prompts, combined with multi-provider comparison that runs the same prompt across different LLM providers side-by-side.

The Architecture: Database to UI

Database Schema Changes

We started with the data layer, adding two key fields to our Prisma schema:

prisma
model Workflow {
  // ... existing fields
  personaIds    String[] @db.Uuid  // Links to expert personas
}

model WorkflowStep {
  // ... existing fields
  compareProviders String[] @default([])  // ["anthropic", "openai", "google"]
}

The beauty of Prisma's String[] type meant we could store multiple personas per workflow and multiple providers per step without complex junction tables.

Backend: The Expert Injection System

The real magic happens in the workflow engine. We built a loadPersonaSystemPrompts() function that fetches persona data and formats it for injection:

typescript
// Before: Single system prompt
systemPrompt = step.systemPrompt

// After: Expert team + step prompt
const personaPrompts = await loadPersonaSystemPrompts(workflow.personaIds);
systemPrompt = `${personaPrompts}\n\n${step.systemPrompt}`;

Each persona gets formatted as:

## Expert: Senior Security Engineer
You are a security-focused engineer with 10+ years experience...

## Expert: UX Design Lead  
You approach problems from a user-centered design perspective...

Multi-Provider Execution

When a step has compareProviders configured, instead of generating one response, we fork execution:

typescript
if (step.compareProviders.length > 1) {
  // Generate one alternative per provider
  for (const provider of step.compareProviders) {
    alternatives.push(
      await executeStep(context, step, { providerOverride: provider })
    );
  }
} else {
  // Traditional single/multi-generation
  // ...
}

This gives you side-by-side comparisons: the same expert-enhanced prompt run through GPT-4, Claude, and Gemini simultaneously.

Frontend: Intuitive Configuration

The UI needed to make this powerful feature approachable. We added:

Persona Selection: A multi-select checklist that appears after you choose your consolidation strategy:

typescript
{selectedPersonas.map(persona => (
  <div key={persona.id} className="flex items-center space-x-2">
    <Users className="h-4 w-4" />
    <Badge variant="secondary">{persona.name}</Badge>
  </div>
))}

Provider Comparison Toggle: Each step card now has provider selection that auto-syncs with generation count:

typescript
// When you enable multi-provider, generateCount updates automatically
const handleProviderToggle = (providers: string[]) => {
  updateStep(step.id, { 
    compareProviders: providers,
    generateCount: Math.max(1, providers.length)
  });
};

Visual Feedback: Alternative cards now show which provider and model generated each response, plus step headers display "N providers" badges when comparison is active.

Lessons Learned: The TypeScript Tango

Building this feature taught us some valuable lessons about TypeScript and complex state management:

The Zod Enum Challenge

Our first attempt used simple string[] types for provider arrays, but TypeScript wasn't having it:

typescript
// ❌ This failed
compareProviders: string[]  // Not assignable to ("anthropic"|"openai"|"google")[]

// ✅ This worked  
compareProviders: ("anthropic" | "openai" | "google" | "ollama")[]

Lesson: When working with Zod schemas and strict enums, match your TypeScript types exactly to the schema constraints. The extra verbosity prevents runtime errors.

Default Configuration Gotchas

Adding new required fields to existing schemas created ripple effects:

typescript
// ❌ TS2741: Property 'compareProviders' is missing
const defaultStepConfig = {
  systemPrompt: "",
  generateCount: 1
  // compareProviders missing!
};

// ✅ Always provide defaults for new fields
const defaultStepConfig = {
  systemPrompt: "",
  generateCount: 1,
  compareProviders: []
};

Lesson: When extending existing types, audit all the places that create default instances. TypeScript will catch most of them, but it's better to be proactive.

Development Server Conflicts

Running multiple development servers while testing led to mysterious style conflicts and cached responses.

Lesson: When making significant changes, kill all processes on your dev port (lsof -ti:3000 | xargs kill), clear your .next cache, and start fresh. The few extra seconds save hours of debugging phantom issues.

The Results: Workflows That Think Like Teams

The final implementation supports powerful new workflow patterns:

  1. Expert Team Workflows: Select multiple personas (Security Expert, Product Manager, Technical Architect) and every step gets their combined perspective
  2. Provider A/B Testing: Enable comparison mode and see how GPT-4, Claude, and Gemini each interpret the same expert-enhanced prompt
  3. Cost-Aware Planning: The system automatically calculates costs across all providers and personas before execution
  4. Seamless Selection: Pick the best alternative from any provider and the workflow continues with that choice

What's Next?

This foundation opens up exciting possibilities:

  • Dynamic persona creation from natural language descriptions
  • Persona marketplace where teams can share expert configurations
  • Automated provider selection based on step type and performance history
  • Consensus mechanisms that automatically merge insights from multiple expert perspectives

The code is live, tested, and ready for teams who want their AI workflows to think more like diverse, expert human teams. Because sometimes the best AI response isn't from one model—it's from the right combination of expertise and intelligence working together.


Want to see this in action? The complete implementation is available in nyxCore commit aa37799 with full TypeScript types, tRPC procedures, and React components.