nyxcore-systems
7 min read

Unfolding Insights: Bringing Expert Teams and Clarity to Our AI Workflow UI

This week, we tackled two core areas of our AI workflow engine: enhancing the user experience with full Markdown rendering and empowering our AI with dynamic expert team assembly. Join us as we unpack the journey, the solutions, and the valuable lessons learned along the way.

ai-workflowsfrontend-developmentbackend-developmentux-designdeveloper-experiencetypescriptnextjstrpcssezodprompt-engineering

As developers, we're constantly striving for that sweet spot where powerful backend logic meets an intuitive, informative frontend. This past development session was a prime example, focusing on a dual mission: making our AI workflow outputs more digestible for users, and simultaneously making our AI smarter by introducing dynamic "expert teams."

The goal was clear: ditch the clunky, collapsed prompt sections in our workflow execution UI, provide immediate value through full Markdown rendering, and bake in a robust "expert team" concept directly into our core prompt templates. I'm happy to report, all three are now live, compiled clean, and thoroughly verified.

From Collapsed Cards to Crystal Clear Markdown

Our previous workflow execution UI had a bit of a usability bottleneck. While functional, the output of each completed step was presented in a series of collapsed cards. You'd get a truncated snippet, and if you wanted the full context, you'd have to expand each one individually. This was fine for short outputs, but for detailed implementation prompts or lengthy analysis, it quickly became a chore.

The Fix: We ripped out the PromptSectionCard component and its associated parsePromptSections() function. In their place, we now render the full output of each completed step directly inline using a MarkdownRenderer. This immediately transforms a wall of expandable sections into a coherent, scrollable document, just like you'd expect from a well-formatted technical report.

But we didn't stop there. We also overhauled the actionability around each step's output. Instead of buried Edit and Retry buttons at the bottom, each completed step now sports a sleek action toolbar above it, offering:

  • .md Download: A new downloadMarkdown(content, filename) helper function creates a Blob and triggers a browser download, using the step's label as a sanitized filename. Super handy for archiving or sharing.
  • Copy: Instantly copy the full markdown content to your clipboard.
  • Edit: Jump back in and tweak the prompt for that specific step.
  • Retry: Rerun the step with the current (or edited) prompt.

This small UI/UX change dramatically improves the experience of reviewing, iterating, and extracting information from our AI-driven workflows.

Assembling the Dream Team: Dynamic Expert Assignment

Beyond UI enhancements, we significantly upgraded the intelligence layer of our AI workflows. The core idea? For complex tasks, a single AI isn't always enough. What if we could dynamically "assemble" a team of virtual domain experts tailored to the specific context of the task at hand?

That's exactly what we implemented. We updated three of our most critical prompt templates (extensionPrompt, deepPrompt, and secPrompts) to include a new "Step 0: Assemble the Expert Team" section.

Here's how it works:

  1. Contextual Analysis: Based on the input and the project's tech stack, domain, or even identified vulnerability classes, the system now first generates a list of 3-5 specialized "domain experts."
  2. Role Assignment: Each subsequent prompt within the workflow is then dynamically assigned to one or more of these generated experts.

For example, an extensionPrompt for a new feature might generate:

  • Sarah Chen, Full-Stack Engineer
  • Marcus Rodriguez, Database Architect
  • AI Integration Specialist
  • Alex Kim, Frontend Developer
  • Jordan Taylor, DevOps Engineer

And then, individual steps like "Design Features" or "Implementation Prompts" would include an "Assigns Expert(s): [Expert Name(s)]" field in their prompt, guiding the AI to think from that expert's perspective.

We verified this with a new test workflow, "Expert Team Test." It ran through "Analyze Idea" → "Design Features" → "Implementation Prompts," and successfully produced a diverse team of 5 experts, each assigned to relevant prompts, demonstrating the power of this new, more nuanced approach to AI-driven task execution.

Lessons from the Trenches: Navigating the Dev Landscape

No dev session is complete without its share of head-scratchers. These "pain points" are often the most valuable learning opportunities.

1. The Curious Case of the Missing Playwright Module

The Challenge: I tried running a Playwright screenshot script from a /tmp/ directory, expecting it to pick up node_modules from the project root. The Reality: Cannot find module 'playwright'. Node.js module resolution is deeply tied to the current working directory (CWD) and node_modules hierarchy. Running a script from outside the project root often means it can't find its dependencies. The Lesson: Always be mindful of your execution context (CWD) when running scripts that rely on local node_modules. If you need to run something from a temporary location, ensure it has access to its dependencies, perhaps by explicitly setting NODE_PATH or copying necessary node_modules alongside it (though the latter is usually overkill). For quick tests, copying the script into the project root and running it from there is often the simplest workaround.

2. Environment Variable Mix-Up: NEXTAUTH_SECRET vs. AUTH_SECRET

The Challenge: Attempting to forge a JWT using process.env.NEXTAUTH_SECRET. The Reality: The project's authentication secret was actually configured as AUTH_SECRET. The Lesson: Project environments, especially those that evolve or use custom configurations, can have subtle differences in environment variable naming conventions. Always double-check your .env files, next.config.js or auth.js configurations to confirm the exact variable names. A quick console.log(process.env) can save a lot of debugging time.

3. Workflow Execution: Beyond the start Mutation

The Challenge: After calling a tRPC start mutation to kick off a workflow, it remained "running" with all steps "pending." The Reality: The start mutation only updates the workflow's status in the database. The actual execution (driving the AsyncGenerator that processes steps) relies on consuming a Server-Sent Events (SSE) endpoint. Without a client actively listening to /api/v1/events/workflows/[id], the workflow process won't advance. The Lesson: For asynchronous, real-time processes, understand the full execution model. A database status update is often just a flag; the actual work might be driven by event streams, message queues, or other background workers. If your UI needs to reflect real-time progress, you likely need to connect to an event source.

4. Zod's Strict Input Validation: Object vs. String

The Challenge: Passing a simple string as input to a workflow creation mutation. The Reality: Zod validation failed, expecting z.record(z.string()) (an object), not a string. Our {{input}} template resolver is designed to handle objects and stringify them. The Lesson: Always respect your Zod schemas! They are your contract for data integrity. If a field expects an object, even if it's a simple {"text": "my string"}, provide an object. This ensures consistency and prevents unexpected runtime errors. We'll consider if the {{input}} resolver should be more forgiving for simple string inputs in the future, but for now, explicit objects are key.

What's Next?

Our immediate roadmap includes:

  • Cleaning up stale workflows that got stuck in the "running" state due to the SSE consumer issue.
  • Refining the {{input}} template resolver to potentially handle direct string inputs, improving developer ergonomics.
  • Updating our cost estimation logic to accurately reflect generateCount multipliers for alternatives.
  • Thorough end-to-end testing of the alternatives selection flow (generating multiple options, selecting one, and continuing).
  • Verifying prompt editing on pending workflows.
  • Considering a "Section View" toggle for extremely long outputs, perhaps with a table of contents, as full markdown rendering can still be overwhelming for 10k+ token responses.

This session was a fantastic step forward, making our AI workflows both more powerful under the hood and significantly more user-friendly. It's exciting to see these improvements come to life, and we're already looking forward to the next set of challenges!

json
{"thingsDone":["Replaced collapsed prompt cards with full Markdown rendering in workflow UI","Added action toolbar (download, copy, edit, retry) to each completed step","Implemented dynamic 'Expert Team' assembly in core prompt templates","Updated `extensionPrompt`, `deepPrompt`, `secPrompts` templates for expert teams","Created and verified 'Expert Team Test' workflow"],"pains":["Playwright module resolution outside project root","Incorrect environment variable name for Auth Secret (`NEXTAUTH_SECRET` vs `AUTH_SECRET`)","Misunderstanding workflow execution flow (tRPC mutation vs. SSE consumption)","Zod validation error for `input` field (expected object, received string)"],"successes":["Enhanced user experience for workflow outputs","Increased AI workflow intelligence with dynamic expert assignment","Streamlined developer experience with improved actionability","Robust end-to-end testing of new features"],"techStack":["Next.js","React","TypeScript","tRPC","PostgreSQL","Zod","Playwright","Server-Sent Events (SSE)","MarkdownRenderer"]}