From Blind Spots to Brilliant Insights: Injecting Context into AI Workflows
A late-night session focused on a critical problem in our AI workflow engine: ensuring every step, especially review stages, always has the full context from prior work. We're making our custom workflows truly intelligent.
It was one of those late-night sessions. The kind where the clock blurs, and the only thing that matters is the problem in front of you. We were tackling a fundamental challenge in our AI workflow engine: ensuring that custom workflows, especially critical review steps, always had the full historical context of prior work. The goal? Make our AI-powered pipelines not just functional, but truly intelligent and context-aware.
The Problem: When AI Steps Go Blind
Our workflow engine allows users to define custom sequences of AI-driven tasks. For template-based workflows, we explicitly define variable substitutions like {{steps.previous_step_name.output}}. This works great. But what about custom, free-form workflows? Or even our simple built-in review step template, which had a generic prompt?
The issue was glaring: these steps often received no context from prior actions. A human reviewer, or even an AI agent, couldn't effectively review "prior work" if they didn't know what that work was. Our resolvePrompt() function was too literal; it only substituted variables that were explicitly referenced. If a prompt didn't say {{steps.*}}, it got nothing. This created a significant "blind spot" in our system, hindering the effectiveness of critical stages.
The Fix: Automatic Context Injection
This was the core of the late-night push. We needed a robust mechanism to automatically inject relevant prior step outputs into the current step's context, especially when no explicit references were made.
Here's how we tackled it in src/server/services/workflow-engine.ts:
-
buildAutoContext(ctx)Function: We introduced a new function that iterates through all completed steps in the current workflow context (ctx). For each step, it intelligently assembles its output. To keep things manageable and prevent prompt bloat, we prioritize "digests" (summarized outputs) and cap the raw output at 4KB per step. All this is then formatted into a clear, markdown-friendly## Previous Stepsblock.typescript// Conceptual snippet from buildAutoContext function buildAutoContext(ctx: WorkflowContext): string { let autoContext = ""; if (ctx.completedSteps.length > 0) { autoContext += "## Previous Steps\n\n"; for (const step of ctx.completedSteps) { autoContext += `### Step: ${step.name}\n`; autoContext += `**Status:** ${step.status}\n`; // Prioritize digest, fall back to truncated output const output = step.digest || step.output?.substring(0, 4096) || 'No output.'; autoContext += `\`\`\`\n${output}\n\`\`\`\n\n`; } } return autoContext; } -
Intelligent
resolvePrompt(): OurresolvePrompt()function was updated to first check if the prompt already contained{{steps.*}}references. If it did, we'd proceed with the usual explicit substitution. However, if no such references were found and there were completed steps, we would then append thebuildAutoContext()output to the prompt.This ensures that:
- Explicitly defined context always takes precedence.
- Custom workflows and generic steps (like our
reviewtemplate) automatically gain crucial historical context, making them significantly more effective.
This change means our AI agents, whether performing a refactor or a security review, are no longer operating in a vacuum. They now have a curated, digestible history of the workflow's progression, leading to more informed and accurate results.
Broader Wins: Persistence & Polished Reports
While the context injection was the main event, this session also brought significant progress on the reporting front:
- Report Persistence: We introduced a new
ReportPrisma model with robust Row-Level Security (RLS). Now, all generated reports (autoFix, refactor, workflows) are securely stored in the database, viewable by project. This was a critical step for auditability and user experience. - PDF Export Power: To complement persistence, we built out a Python-based PDF converter (
scripts/md2pdf.py). This script leveragesmd2pdf-mermaidand Playwright's Chromium renderer to transform our markdown reports into beautifully branded PDFs, complete with custom footers. A newsrc/app/api/v1/reports/pdf/route.tsendpoint handles the conversion, and our UI now offers both Markdown and PDF download options in theReportGeneratorModalandReportsTabviewer. Even a small detail like updating the QR code URL fromnyxcore.apptonyxcore.cloudwas handled.
Lessons from the Trenches: Small Details, Big Impact
No development session is complete without a few head-scratching moments.
-
Relative Import Paths: I hit a classic TypeScript/Next.js gotcha. When importing our middleware into the new PDF API route (
src/app/api/v1/reports/pdf/route.ts), I initially tried../../../middleware. TypeScript rightfully threw aTS2307: Cannot find moduleerror. A quick double-check revealed the middleware was atsrc/app/api/v1/middleware.ts, meaning only../../middlewarewas needed. It's a simple fix, but a good reminder to always count your directory levels carefully, especially when nesting API routes. -
The Power of Implicit Context: The core problem of blind review steps highlighted a broader architectural lesson: don't assume explicit template variables will always be present. Building in intelligent fallback mechanisms, like our
buildAutoContext, significantly increases the robustness and usability of a system. It turns a potential failure point into a source of automated intelligence.
The Toolkit & What's Next
Our environment for this session involved:
- TypeScript/Next.js for the backend and API routes.
- Prisma for database interaction with PostgreSQL.
- A dedicated Python virtual environment (
.venv/) housingmd2pdf-mermaidand Playwright for the PDF generation.
Looking ahead, the immediate next steps are clear:
- Verify Custom Workflows: Thoroughly test a custom, non-template workflow to ensure the auto-context injection is working as expected for review steps.
- RAG-based Policy Library: Explore integrating Retrieval Augmented Generation (RAG) for tenant-specific policy libraries (DSGVO, ISO 27001, internal coding standards). User feedback strongly suggests RAG is superior to direct LLM prompting for compliance documents.
- Context-Aware Pipelines: Continue advancing our roadmap for even deeper context-aware AutoFix and Refactor pipelines.
- Onboarding Docs: Add clear setup instructions for the Python venv and Playwright for new developers joining the project.
This session was a significant leap forward in making our AI workflows not just functional, but truly intelligent and context-rich. It's these kinds of foundational improvements that elevate a tool from useful to indispensable.
{
"thingsDone": [
"Implemented auto-context injection for custom workflows and generic review steps",
"Developed `buildAutoContext` and enhanced `resolvePrompt` in `workflow-engine.ts`",
"Introduced `Report` Prisma model with RLS for report persistence",
"Implemented Python-based PDF export using `md2pdf-mermaid` and Playwright",
"Created API endpoint (`/reports/pdf`) and UI integration for PDF downloads",
"Updated QR code URL to nyxcore.cloud"
],
"pains": [
"Incorrect relative import path (`../../../middleware` instead of `../../middleware`)",
"Custom workflows and generic review steps lacked context from prior steps",
"Root cause: `resolvePrompt()` only processed explicit `{{steps.*}}` references, no fallback"
],
"successes": [
"Successfully fixed context passing, ensuring all steps receive prior work outputs",
"Established robust report persistence and retrieval capabilities",
"Enabled branded PDF export for all generated reports",
"Learned a valuable lesson on precise relative import paths in nested API routes",
"Reinforced the importance of robust fallback mechanisms for context in AI systems"
],
"techStack": [
"TypeScript",
"Next.js",
"Prisma",
"PostgreSQL",
"Python",
"md2pdf-mermaid",
"Playwright (Chromium)"
]
}