No More Lost Context: Supercharging Workflow Intelligence and Reporting
We tackled a critical challenge: ensuring AI workflows always remember prior steps. Discover how we built intelligent context injection and revamped report generation with persistent storage and beautiful PDF exports.
Every developer knows the frustration of a system that forgets. Imagine an AI workflow, diligently performing task after task, only to "forget" the output of previous steps when it comes time for a critical review or a subsequent operation. This was the silent saboteur lurking in our custom workflows, and it was time for an intervention.
This past session, we embarked on a mission to inject intelligence and memory into our workflow engine, ensuring that context flows seamlessly from one step to the next. But we didn't stop there. We also gave our reporting capabilities a significant facelift, moving from ephemeral outputs to persistent, beautiful PDF reports.
The Case of the Missing Context: A Workflow Dilemma
Our custom workflows, designed for flexibility and power, had a glaring oversight. While our templated workflows expertly guided the AI by explicitly referencing prior step outputs (e.g., {{steps.step1.output}}), custom, free-form workflows often lacked this explicit instruction. The result? When a review step, or any subsequent action, came along, it was often presented with a blank slate, forcing the AI to re-evaluate or even guess, leading to suboptimal results. Even our simple, built-in review step template suffered from this, as its generic prompt didn't explicitly ask for prior context.
The root cause was clear: our resolvePrompt() function was a stickler for explicit instructions. It would happily substitute variables if they were called out, but it had no fallback mechanism for when context should be there but wasn't explicitly requested.
The Solution: Intelligent Context Injection
To combat this "AI amnesia," we introduced a robust, automated context injection system.
At the heart of this solution lies a new function: buildAutoContext(ctx). This function is a clever assembler, gathering all completed step outputs from the current workflow. To keep things manageable and relevant, it prioritizes concise "digests" of outputs and caps the size of each step's contribution to 4KB. It then elegantly formats this collected wisdom into a ## Previous Steps markdown block.
The magic happens in resolvePrompt(). Before, it was a simple variable replacer. Now, it's smarter. If it detects that a prompt doesn't explicitly reference any {{steps.*}} variables, and there are completed steps in the workflow, it automatically appends the ## Previous Steps markdown block generated by buildAutoContext().
Impact: This seemingly small change has a profound effect:
- Custom Workflows: Now, every custom workflow, even without explicit context references, will automatically feed previous step outputs to subsequent steps. This means more informed decisions, better reviews, and a truly sequential thought process for the AI.
- Review Steps: Our built-in
reviewstep is now context-aware by default, leading to more targeted and valuable feedback.
This ensures that the AI always "remembers" what it has done, making our workflows far more intelligent and reliable.
Beyond Workflows: Reports Get a Major Upgrade
While fixing workflow context was critical, we also dedicated significant effort to enhancing our reporting capabilities. We wanted reports to be not just generated, but also persistent, easily accessible, and professionally presentable.
Persistent Reports: A Historical Record
Ephemeral data is often lost data. To ensure our valuable AI-generated reports (from autoFix, refactor, and custom workflows) are always available, we implemented:
ReportPrisma Model: A new database model was introduced, complete with Row-Level Security (RLS) to ensure data privacy and access control.reports.tstRPC Router: A dedicated API router now handles listing, retrieving, and deleting reports, all filtered by project.- Automatic Persistence: Every time a report is generated by any of our core mutations, it's now automatically saved to the database.
This means users can now revisit past analyses and generated content, providing an invaluable historical record of their interactions with the system.
Professional PDF Export: From Markdown to Masterpiece
Seeing a report in the browser is one thing; having a polished, branded PDF is another. We've introduced a robust PDF export feature:
md2pdf.py: A new Python script, leveragingmd2pdf-mermaidand Playwright's Chromium engine, takes our markdown reports and transforms them into high-fidelity PDFs. It even bakes in a branded footer for a professional touch.src/app/api/v1/reports/pdf/route.ts: A dedicated API endpoint now serves as the bridge, calling the Python subprocess to generate the PDF on demand.- UI Integration: Our
ReportGeneratorModalandReportsTabnow sport dual download buttons, allowing users to choose between raw Markdown or the newly available PDF format. We also implemented smart filename generation for easy organization.
Oh, and a small but important detail: the QR code URL embedded in our reports was updated from nyxcore.app to nyxcore.cloud to reflect our latest branding.
Lessons Learned: The Perils of Relative Paths
Even seasoned developers can stumble on the basics. During the implementation of the PDF export API, I hit a snag with an import path:
// Initial attempt in src/app/api/v1/reports/pdf/route.ts
import { authMiddleware } from '../../../middleware'; // TS2307: Cannot find module
The error TS2307: Cannot find module was a classic. A quick mental map of the directory structure (v1/reports/pdf/route.ts vs v1/middleware.ts) quickly revealed the issue: I was attempting to go up three levels when only two were needed. The fix was simple:
// Corrected path
import { authMiddleware } from '../../middleware';
This served as a good reminder: even in complex systems, sometimes the most fundamental concepts like relative file paths can trip you up. A moment of careful path tracing can save a