diff --git a/src/lib/agent/__tests__/agent-prompt-loader.test.ts b/src/lib/agent/__tests__/agent-prompt-loader.test.ts
index d2ad5b7ae..0cfc92138 100644
--- a/src/lib/agent/__tests__/agent-prompt-loader.test.ts
+++ b/src/lib/agent/__tests__/agent-prompt-loader.test.ts
@@ -296,4 +296,24 @@ describe('assembleTaskPrompt', () => {
       'task instructions',
     );
   });
+
+  it('surfaces the per-framework SDK docs when present', () => {
+    const assembled = assembleTaskPrompt(
+      {
+        ...ctx,
+        docsPaths: ['.posthog-wizard-cache/reference/references/go.md'],
+      },
+      'do the task',
+    );
+    expect(assembled).toContain('SDK reference docs');
+    expect(assembled).toContain(
+      '.posthog-wizard-cache/reference/references/go.md',
+    );
+  });
+
+  it('omits the SDK docs section when there are none', () => {
+    expect(assembleTaskPrompt(ctx, 'do the task')).not.toContain(
+      'SDK reference docs',
+    );
+  });
 });
diff --git a/src/lib/agent/agent-prompt-loader.ts b/src/lib/agent/agent-prompt-loader.ts
index 8b83ff9ac..2854c10be 100644
--- a/src/lib/agent/agent-prompt-loader.ts
+++ b/src/lib/agent/agent-prompt-loader.ts
@@ -32,6 +32,9 @@ export interface OrchestratorPromptContext {
   examplePath?: string;
   /** Path to the framework's rules (COMMANDMENTS.md), if available. */
   commandmentsPath?: string;
+  /** Paths to the framework's SDK reference docs (the per-framework `.md` files
+   *  packaged in the reference skill), if any. */
+  docsPaths?: readonly string[];
 }
 
 function projectContext(ctx: OrchestratorPromptContext): string {
@@ -55,6 +58,14 @@ function commandmentsReference(ctx: OrchestratorPromptContext): string | null {
   return `Framework rules for this integration are at \`${ctx.commandmentsPath}\`. Read them before you edit and follow them.`;
 }
 
+/** The per-framework SDK docs ship with the reference skill. For docs-only
+ *  frameworks (no EXAMPLE.md) they are the primary implementation signal. */
+function docsReference(ctx: OrchestratorPromptContext): string | null {
+  if (!ctx.docsPaths || ctx.docsPaths.length === 0) return null;
+  const list = ctx.docsPaths.map((p) => `\`${p}\``).join(', ');
+  return `The PostHog SDK reference docs for this framework are at ${list}. Read the ones relevant to your task before you edit.`;
+}
+
 const TASK_BASICS = `You are one isolated task in a larger PostHog workflow, run as a fresh agent with no memory of the other tasks beyond the context you are given. Do only your task, then report exactly once by calling complete_task with a structured handoff: what your goal was, what you did, and what the next agent should know. When you are given context from previous steps, trust it — those agents already did their work, so do not re-verify or re-read what their handoffs tell you. Build on it and move fast. Read a file before you edit it, so your own changes do not duplicate what is already there. Work only inside this project's own directory: never read, list, or search (find, ls, grep, glob) outside it — not the OS, not other projects, not global package caches. If your task seems to need something outside this directory, it does not — skip that part and say so in your handoff rather than hunting across the filesystem. If your task does not apply to this project — there is genuinely nothing for it to do — report it with status \`skipped\` and say why, rather than marking it done.`;
 
 const SEED_BASICS = `You are the orchestrator. Plan the work and seed the queue with enqueue_task — each call returns an id you can pass as a dependency to a later task. Give each task a short label for the UI — the action in a few words, not file names, class names, or other specifics. You are not a task yourself: do not call complete_task and do not edit the project.`;
@@ -80,6 +91,7 @@ export function assembleTaskPrompt(
     projectContext(ctx),
     exampleReference(ctx),
     commandmentsReference(ctx),
+    docsReference(ctx),
     skillReference(skillPaths),
     TASK_BASICS,
     body,
diff --git a/src/lib/programs/orchestrator/orchestrator-runner.ts b/src/lib/programs/orchestrator/orchestrator-runner.ts
index 6353d8c80..ff10a420b 100644
--- a/src/lib/programs/orchestrator/orchestrator-runner.ts
+++ b/src/lib/programs/orchestrator/orchestrator-runner.ts
@@ -11,7 +11,7 @@
  * stays product-ignorant: it is the queue, the executor, and the loader.
  */
 import { randomUUID } from 'crypto';
-import { existsSync, rmSync } from 'fs';
+import { existsSync, readdirSync, rmSync } from 'fs';
 import * as path from 'path';
 import {
   initializeAgent,
@@ -96,6 +96,30 @@ async function resolveReferenceSkillId(
   return ids.find((id) => id.startsWith(`integration-${framework}-`));
 }
 
+/**
+ * A step-skill (the HOW for one task) may ship per-framework variants — install,
+ * init, capture, and error-tracking each package the framework's docs page, ided
+ * as `<baseId>-<framework>`. Resolve the agent's bare skill id to that variant:
+ * exact `<baseId>-<framework>`, else the first granular variant under it, else
+ * the bare id unchanged (the generic single-variant steps — identify, report,
+ * dashboard, build — and the no-framework case).
+ */
+async function resolveStepSkillId(
+  skillsBaseUrl: string,
+  baseId: string,
+  framework: string | null | undefined,
+): Promise<string> {
+  if (!framework) return baseId;
+  const menu = await fetchSkillMenu(skillsBaseUrl);
+  if (!menu) return baseId;
+  const ids = Object.values(menu.categories)
+    .flat()
+    .map((s) => s.id);
+  const exact = `${baseId}-${framework}`;
+  if (ids.includes(exact)) return exact;
+  return ids.find((id) => id.startsWith(`${baseId}-${framework}-`)) ?? baseId;
+}
+
 export async function runOrchestrator(
   session: WizardSession,
   programConfig: ProgramConfig,
@@ -190,6 +214,7 @@ export async function runOrchestrator(
   // skill — only the example file is read, when the agent's prompt points at it.
   let examplePath: string | undefined;
   let commandmentsPath: string | undefined;
+  let docsPaths: string[] = [];
   const referenceSkillId = session.skillId
     ? await resolveReferenceSkillId(boot.skillsBaseUrl, session.skillId)
     : undefined;
@@ -201,14 +226,34 @@ export async function runOrchestrator(
       path.join(QUEUE_DIR_NAME, 'reference'),
     );
     if (ref.kind === 'ok') {
-      const example = path.join(ref.path, 'references', 'EXAMPLE.md');
+      const refDir = path.join(ref.path, 'references');
+      const example = path.join(refDir, 'EXAMPLE.md');
       if (existsSync(path.join(session.installDir, example))) {
         examplePath = example;
       }
-      const commandments = path.join(ref.path, 'references', 'COMMANDMENTS.md');
+      const commandments = path.join(refDir, 'COMMANDMENTS.md');
       if (existsSync(path.join(session.installDir, commandments))) {
         commandmentsPath = commandments;
       }
+      // Surface the per-framework SDK docs (e.g. `go.md`, `next-js.md`) the
+      // skill packages — the HOW for this framework, and the only HOW signal
+      // for docs-only frameworks with no EXAMPLE.md. Skip the structural files:
+      // EXAMPLE.md and COMMANDMENTS.md are handled above, and the monolith's
+      // numbered workflow files (`1-begin.md` …) are its linear-flow narrative,
+      // not SDK reference — match those by their numeric prefix.
+      const refDirAbs = path.join(session.installDir, refDir);
+      if (existsSync(refDirAbs)) {
+        docsPaths = readdirSync(refDirAbs)
+          .filter(
+            (f) =>
+              f.endsWith('.md') &&
+              f !== 'EXAMPLE.md' &&
+              f !== 'COMMANDMENTS.md' &&
+              !/^\d+-/.test(f),
+          )
+          .sort()
+          .map((f) => path.join(refDir, f));
+      }
     } else {
       logToFile(
         `[orchestrator] reference unavailable: ${ref.kind} (${referenceSkillId})`,
@@ -228,6 +273,7 @@ export async function runOrchestrator(
     host: boot.host,
     examplePath,
     commandmentsPath,
+    docsPaths,
   };
 
   logToFile(
@@ -325,7 +371,12 @@ export async function runOrchestrator(
       // auto-load them and they must never land in the project (or a CI PR).
       // The prompt points the agent at them instead.
       const skillPaths: string[] = [];
-      for (const skillId of resolved.skills) {
+      for (const baseSkillId of resolved.skills) {
+        const skillId = await resolveStepSkillId(
+          boot.skillsBaseUrl,
+          baseSkillId,
+          session.skillId,
+        );
         const result = await installSkillById(
           skillId,
           session.installDir,
