Skill: working with the render pipeline (render arrays, cacheability metadata, lazy builders)
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3583217. -->
Reported by: [alex ua](https://www.drupal.org/user/110386)
Related to !16
>>>
<h3>Problem/Motivation</h3>
<p>The Drupal render pipeline is where AI agents confabulate most frequently. Agents routinely:</p>
<ul>
<li>Return raw HTML strings or HTML <code>Response</code> objects from page controllers instead of render arrays</li>
<li>Ignore cacheability metadata entirely, producing pages that cache incorrectly or not at all</li>
<li>Misunderstand cache tag propagation — metadata must <strong>bubble up</strong> through the render tree; attaching tags at the wrong level means they're silently lost</li>
<li>Fail to use lazy builders for personalized or uncacheable content, defeating the Dynamic Page Cache</li>
<li>Confuse <code>#markup</code> (filtered HTML), <code>#plain_text</code> (escaped), and <code>#theme</code>/<code>#type</code> (structured rendering)</li>
<li>Assume cache tag invalidation means eager deletion (it's actually two-phase: checksum update is immediate, item eviction is lazy on read)</li>
</ul>
<p>These errors are especially dangerous because they often produce <em>working</em> code — the page renders correctly in development. The bugs only surface under caching in production, where they cause stale content, personalization leaks, or performance degradation.</p>
<h3>Proposed Resolution</h3>
<p>Create a <code>working-with-the-render-pipeline/SKILL.md</code> skill covering:</p>
<h4>Core concepts (ordered by what agents get wrong most)</h4>
<ol>
<li><strong>For HTML page controllers, return render arrays rather than concatenated HTML strings.</strong> Controllers should return structured data so the render system can turn it into HTML and preserve metadata.</li>
<li><strong>Cacheability metadata is mandatory.</strong> Every render array that varies by user, permission, route, or query string must declare its cache contexts. Every render array that depends on an entity or config must declare its cache tags. Missing metadata = caching bugs in production.</li>
<li><strong>Metadata bubbles up automatically — but only if you use render arrays.</strong> When you bypass the render system (raw HTML, Response objects), metadata is silently lost.</li>
<li><strong>Lazy builders for uncacheable content.</strong> The Dynamic Page Cache caches the page with placeholders; lazy builders fill them per-request. Without lazy builders, the entire page becomes uncacheable.</li>
<li><strong>Cache tag invalidation is two-phase.</strong> Checksum update is synchronous; item eviction is lazy on next read. Agents frequently assume eager deletion.</li>
</ol>
<h4>"What not to do" section</h4>
<ul>
<li>Do not return <code>new Response($html)</code> from an HTML page controller unless you are intentionally bypassing Drupal's render/cache system and handling cacheability yourself</li>
<li>Do not use <code>#markup</code> for user-generated content without understanding that it runs through <code>Xss::filterAdmin()</code></li>
<li>Do not attach cache tags to a render array that is not part of the render tree — they won't bubble</li>
<li>Do not put personalized content (username, cart count) directly in a render array — use a lazy builder</li>
</ul>
<h3>Why this skill is high priority</h3>
<p>The render pipeline touches every controller, block, field formatter, and page in Drupal. It is the subsystem where incorrect agent output is most likely to ship to production, because the errors are invisible in development. Among the subsystems not yet covered by ai_best_practices, this one has the highest blast radius.</p>
<h3>Remaining Tasks</h3>
<ol>
<li>Draft the skill file with worked examples</li>
<li>Write eval cases: agent generates a controller (must use render arrays, must include cache metadata), agent generates a block (must propagate tags correctly), agent handles personalized content (must use lazy builder)</li>
<li>Add entry to AGENTS.md</li>
<li>Review with core maintainers for accuracy</li>
</ol>
issue