|
700 | 700 |
|
701 | 701 |
|
702 | 702 | <li class="md-nav__item"> |
703 | | - <a href="../../reference/lpb-cli.md" class="md-nav__link"> |
| 703 | + <a href="../../reference/lpb-cli/" class="md-nav__link"> |
704 | 704 |
|
705 | 705 |
|
706 | 706 |
|
|
728 | 728 |
|
729 | 729 |
|
730 | 730 | <li class="md-nav__item"> |
731 | | - <a href="../../reference/lpb-config.md" class="md-nav__link"> |
| 731 | + <a href="../../reference/lpb-config/" class="md-nav__link"> |
732 | 732 |
|
733 | 733 |
|
734 | 734 |
|
|
756 | 756 |
|
757 | 757 |
|
758 | 758 | <li class="md-nav__item"> |
759 | | - <a href="../../reference/env-vars.md" class="md-nav__link"> |
| 759 | + <a href="../../reference/env-vars/" class="md-nav__link"> |
760 | 760 |
|
761 | 761 |
|
762 | 762 |
|
|
784 | 784 |
|
785 | 785 |
|
786 | 786 | <li class="md-nav__item"> |
787 | | - <a href="../../reference/config-repo.md" class="md-nav__link"> |
| 787 | + <a href="../../reference/config-repo/" class="md-nav__link"> |
788 | 788 |
|
789 | 789 |
|
790 | 790 |
|
|
812 | 812 |
|
813 | 813 |
|
814 | 814 | <li class="md-nav__item"> |
815 | | - <a href="../../reference/lpb-memory-overview.md" class="md-nav__link"> |
| 815 | + <a href="../../reference/lpb-memory-overview/" class="md-nav__link"> |
816 | 816 |
|
817 | 817 |
|
818 | 818 |
|
|
1018 | 1018 |
|
1019 | 1019 | <h1 id="subagent-spawning-pattern-browser-testing">Subagent Spawning Pattern — Browser Testing<a class="headerlink" href="#subagent-spawning-pattern-browser-testing" title="Permanent link">¶</a></h1> |
1020 | 1020 | <h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">¶</a></h2> |
1021 | | -<p>When spawning subagents for browser testing, use the following pattern to ensure isolated sessions and structured JSON output.</p> |
| 1021 | +<p>When spawning subagents for browser testing, use the following pattern to ensure |
| 1022 | +isolated sessions and structured JSON output.</p> |
1022 | 1023 | <h2 id="steps">Steps<a class="headerlink" href="#steps" title="Permanent link">¶</a></h2> |
1023 | 1024 | <h3 id="1-generate-a-unique-session-id">1. Generate a Unique Session ID<a class="headerlink" href="#1-generate-a-unique-session-id" title="Permanent link">¶</a></h3> |
1024 | | -<div class="highlight"><pre><span></span><code><span class="nv">SESSION_ID</span><span class="o">=</span><span class="k">$(</span>npx<span class="w"> </span>tsx<span class="w"> </span>bin/session-uuid.ts<span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">PI_WORKTREE_ID</span><span class="si">}</span><span class="s2">-<test-name>"</span><span class="k">)</span> |
| 1025 | +<div class="highlight"><pre><span></span><code><span class="nv">SESSION_ID</span><span class="o">=</span><span class="k">$(</span>session-uuid<span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">PI_WORKTREE_ID</span><span class="si">}</span><span class="s2">-<test-name>"</span><span class="k">)</span> |
1025 | 1026 | </code></pre></div> |
1026 | 1027 | <p>Example output: <code>pi-main-abc123-login-flow-7f3a9b2c</code></p> |
1027 | 1028 | <h3 id="2-load-the-system-prompt-template">2. Load the System Prompt Template<a class="headerlink" href="#2-load-the-system-prompt-template" title="Permanent link">¶</a></h3> |
1028 | | -<div class="highlight"><pre><span></span><code><span class="nv">PROMPT</span><span class="o">=</span><span class="k">$(</span>cat<span class="w"> </span>subagent-browser-prompt.txt<span class="k">)</span> |
| 1029 | +<div class="highlight"><pre><span></span><code><span class="nv">PROMPT</span><span class="o">=</span><span class="k">$(</span>cat<span class="w"> </span>/opt/pi-support/config/subagent-browser-prompt.txt<span class="k">)</span> |
1029 | 1030 | </code></pre></div> |
1030 | | -<p>The template at <code>subagent-browser-prompt.txt</code> includes: |
| 1031 | +<p>The template at <code>/opt/pi-support/config/subagent-browser-prompt.txt</code> includes: |
1031 | 1032 | - The JSON schema the subagent must produce |
1032 | 1033 | - Instructions for using agent-browser with bundled Chrome |
1033 | 1034 | - Metrics collection steps (vitals, a11y, snapshot)</p> |
1034 | 1035 | <h3 id="3-spawn-the-subagent">3. Spawn the Subagent<a class="headerlink" href="#3-spawn-the-subagent" title="Permanent link">¶</a></h3> |
1035 | | -<div class="highlight"><pre><span></span><code><span class="c1">// Via the subagent tool in Pi:</span> |
1036 | | -<span class="nx">subagent</span><span class="p">({</span> |
1037 | | -<span class="w"> </span><span class="nx">agent</span><span class="o">:</span><span class="w"> </span><span class="s2">"researcher"</span><span class="p">,</span> |
1038 | | -<span class="w"> </span><span class="nx">task</span><span class="o">:</span><span class="w"> </span><span class="sb">`Run browser test on https://example.com:</span> |
| 1036 | +<p>Use the Pi <code>Agent</code> tool with <code>subagent_type: "browser-automation"</code>:</p> |
| 1037 | +<div class="highlight"><pre><span></span><code><span class="nx">Agent</span><span class="p">(</span> |
| 1038 | +<span class="w"> </span><span class="nx">description</span><span class="o">:</span><span class="w"> </span><span class="s2">"Browser test on https://example.com"</span><span class="p">,</span> |
| 1039 | +<span class="w"> </span><span class="nx">subagent_type</span><span class="o">:</span><span class="w"> </span><span class="s2">"browser-automation"</span><span class="p">,</span> |
| 1040 | +<span class="w"> </span><span class="nx">prompt</span><span class="o">:</span><span class="w"> </span><span class="sb">`Run browser test on https://example.com:</span> |
1039 | 1041 | <span class="sb"> 1. Navigate to the URL</span> |
1040 | 1042 | <span class="sb"> 2. Verify the page loads correctly</span> |
1041 | 1043 | <span class="sb"> 3. Check for accessibility issues</span> |
1042 | 1044 | <span class="sb"> 4. Measure performance metrics</span> |
1043 | 1045 |
|
1044 | | -<span class="sb"> Session ID: </span><span class="si">${</span><span class="nx">SESSION_ID</span><span class="si">}</span> |
1045 | | -<span class="sb"> Prompt: </span><span class="si">${</span><span class="nx">PROMPT</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span> |
1046 | | -<span class="w"> </span><span class="nx">outputSchema</span><span class="o">:</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s2">"subagent-browser-schema.json"</span><span class="p">)),</span> |
1047 | | -<span class="p">});</span> |
| 1046 | +<span class="sb"> Session ID: </span><span class="si">${</span><span class="nx">SESSION_ID</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span> |
| 1047 | +<span class="w"> </span><span class="nx">thinking</span><span class="o">:</span><span class="w"> </span><span class="s2">"low"</span><span class="p">,</span> |
| 1048 | +<span class="w"> </span><span class="nx">isolation</span><span class="o">:</span><span class="w"> </span><span class="s2">"worktree"</span> |
| 1049 | +<span class="p">)</span> |
1048 | 1050 | </code></pre></div> |
1049 | 1051 | <h3 id="4-collect-and-validate-the-result">4. Collect and Validate the Result<a class="headerlink" href="#4-collect-and-validate-the-result" title="Permanent link">¶</a></h3> |
1050 | | -<div class="highlight"><pre><span></span><code><span class="c1"># Pipe subagent output to the validator</span> |
1051 | | -<span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">SUBAGENT_OUTPUT</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>npx<span class="w"> </span>tsx<span class="w"> </span>bin/validate-subagent-output.ts |
1052 | | - |
1053 | | -<span class="c1"># Close the browser session to prevent zombie processes</span> |
1054 | | -agent-browser<span class="w"> </span>--session<span class="w"> </span><span class="s2">"</span><span class="nv">$SESSION_ID</span><span class="s2">"</span><span class="w"> </span>close |
| 1052 | +<p>The subagent returns structured output directly via its completion. Close the |
| 1053 | +browser session when done:</p> |
| 1054 | +<div class="highlight"><pre><span></span><code>agent-browser<span class="w"> </span>--session<span class="w"> </span><span class="s2">"</span><span class="nv">$SESSION_ID</span><span class="s2">"</span><span class="w"> </span>close |
1055 | 1055 | </code></pre></div> |
1056 | 1056 | <h3 id="5-retry-on-failure-max-3-attempts">5. Retry on Failure (Max 3 Attempts)<a class="headerlink" href="#5-retry-on-failure-max-3-attempts" title="Permanent link">¶</a></h3> |
1057 | | -<div class="highlight"><pre><span></span><code><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">validate</span><span class="p">,</span><span class="w"> </span><span class="nx">buildRepairPrompt</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./bin/validate-subagent-output"</span><span class="p">;</span> |
1058 | | - |
1059 | | -<span class="kd">let</span><span class="w"> </span><span class="nx">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">spawnSubagent</span><span class="p">(</span><span class="nx">task</span><span class="p">);</span> |
1060 | | -<span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">validate</span><span class="p">(</span><span class="nx">output</span><span class="p">);</span> |
1061 | | -<span class="kd">let</span><span class="w"> </span><span class="nx">attempts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span> |
1062 | | - |
1063 | | -<span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">.</span><span class="nx">success</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">attempts</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">3</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
1064 | | -<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">repairPrompt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">buildRepairPrompt</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">error</span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="nx">originalTask</span><span class="p">);</span> |
1065 | | -<span class="w"> </span><span class="nx">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">spawnSubagent</span><span class="p">(</span><span class="nx">repairPrompt</span><span class="p">);</span> |
1066 | | -<span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">validate</span><span class="p">(</span><span class="nx">output</span><span class="p">);</span> |
1067 | | -<span class="w"> </span><span class="nx">attempts</span><span class="o">++</span><span class="p">;</span> |
1068 | | -<span class="p">}</span> |
1069 | | - |
1070 | | -<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
1071 | | -<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="sb">`Test failed after </span><span class="si">${</span><span class="nx">attempts</span><span class="si">}</span><span class="sb"> attempts: </span><span class="si">${</span><span class="nx">result</span><span class="p">.</span><span class="nx">error</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span> |
1072 | | -<span class="p">}</span> |
| 1057 | +<p>If the output needs validation, use the support utility:</p> |
| 1058 | +<div class="highlight"><pre><span></span><code><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">SUBAGENT_OUTPUT</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>tsx<span class="w"> </span>/opt/pi-support/validate-subagent-output.ts |
| 1059 | +agent-browser<span class="w"> </span>--session<span class="w"> </span><span class="s2">"</span><span class="nv">$SESSION_ID</span><span class="s2">"</span><span class="w"> </span>close |
1073 | 1060 | </code></pre></div> |
1074 | 1061 | <h2 id="key-points">Key Points<a class="headerlink" href="#key-points" title="Permanent link">¶</a></h2> |
1075 | 1062 | <ul> |
1076 | 1063 | <li><strong>Always use bundled Chrome</strong> (not CDP) for subagents</li> |
1077 | 1064 | <li><strong>Always set <code>AGENT_BROWSER_SESSION</code></strong> to a unique value</li> |
1078 | | -<li><strong>Always pass the JSON schema</strong> in the subagent's prompt</li> |
1079 | 1065 | <li><strong>Always validate</strong> the output on the parent side</li> |
1080 | 1066 | <li><strong>Always retry</strong> with a repair prompt if validation fails</li> |
1081 | 1067 | <li><strong>Cap at 3 attempts</strong> to avoid infinite loops</li> |
| 1068 | +<li><strong>Close browser sessions</strong> — without it, Chrome processes become zombies</li> |
1082 | 1069 | </ul> |
1083 | 1070 | <h2 id="file-reference">File Reference<a class="headerlink" href="#file-reference" title="Permanent link">¶</a></h2> |
1084 | 1071 | <table> |
1085 | 1072 | <thead> |
1086 | 1073 | <tr> |
1087 | | -<th>File</th> |
| 1074 | +<th>Path</th> |
1088 | 1075 | <th>Purpose</th> |
1089 | 1076 | </tr> |
1090 | 1077 | </thead> |
1091 | 1078 | <tbody> |
1092 | 1079 | <tr> |
1093 | | -<td><code>bin/session-uuid.ts</code></td> |
| 1080 | +<td><code>session-uuid</code> (installed at <code>/opt/pi-support/bin/</code>)</td> |
1094 | 1081 | <td>Generate unique session IDs</td> |
1095 | 1082 | </tr> |
1096 | 1083 | <tr> |
1097 | | -<td><code>subagent-browser-schema.json</code></td> |
| 1084 | +<td><code>/opt/pi-support/schemas/browser-validation-schema.json</code></td> |
1098 | 1085 | <td>Unified JSON schema (all fields)</td> |
1099 | 1086 | </tr> |
1100 | 1087 | <tr> |
1101 | | -<td><code>subagent-browser-prompt.txt</code></td> |
| 1088 | +<td><code>/opt/pi-support/config/subagent-browser-prompt.txt</code></td> |
1102 | 1089 | <td>System prompt template</td> |
1103 | 1090 | </tr> |
1104 | 1091 | <tr> |
1105 | | -<td><code>bin/validate-subagent-output.ts</code></td> |
| 1092 | +<td><code>/opt/pi-support/validate-subagent-output.ts</code></td> |
1106 | 1093 | <td>Parent-side validation utility</td> |
1107 | 1094 | </tr> |
| 1095 | +<tr> |
| 1096 | +<td><code>/opt/pi-support/browser-validate.ts</code></td> |
| 1097 | +<td>Browser validation entry point</td> |
| 1098 | +</tr> |
1108 | 1099 | </tbody> |
1109 | 1100 | </table> |
1110 | 1101 |
|
|
0 commit comments