Skip to content

Commit f6e5e74

Browse files
MattPuacharlesvien
andauthored
fix: hide loop builder instructions from chat (#3720)
Co-authored-by: Charles Vien <charles.v@posthog.com>
1 parent 3d7fc62 commit f6e5e74

3 files changed

Lines changed: 44 additions & 9 deletions

File tree

packages/ui/src/features/loops/hooks/useLoopBuilderTask.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
useInboxCloudTaskRunner,
55
} from "@posthog/ui/features/inbox/hooks/useInboxCloudTaskRunner";
66
import { useCallback, useMemo, useRef } from "react";
7-
import { buildLoopBuilderPrompt } from "../loopBuilderPrompt";
7+
import { buildLoopBuilderSystemInstructions } from "../loopBuilderPrompt";
88

99
interface UseLoopBuilderTaskReturn {
1010
/** Start an auto-mode cloud session that builds a loop from `instructions` and navigate to it. */
@@ -30,13 +30,18 @@ export function useLoopBuilderTask(context?: {
3030

3131
const buildInput = useCallback(
3232
(ctx: InboxCloudTaskInputContext): TaskCreationInput => {
33-
const prompt = buildLoopBuilderPrompt({
34-
instructions: instructionsRef.current,
33+
const userPrompt = instructionsRef.current.trim();
34+
const hasSeed = !!userPrompt;
35+
const systemInstructions = buildLoopBuilderSystemInstructions({
36+
hasSeed,
3537
context: contextRef.current,
3638
});
39+
// createTask rejects empty content and the saga drops customInstructions without message text
40+
const taskContent = hasSeed ? userPrompt : "Build a loop";
3741
return {
38-
content: prompt,
39-
taskDescription: prompt,
42+
content: taskContent,
43+
taskDescription: taskContent,
44+
customInstructions: systemInstructions,
4045
// Building a loop is pure PostHog-MCP work (loops-list, integrations-list,
4146
// loops-create); it never touches a working tree. Run repo-less so the
4247
// sandbox skips the clone and isn't tied to some arbitrary default repo.

packages/ui/src/features/loops/loopBuilderPrompt.test.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
import { describe, expect, it } from "vitest";
2-
import { buildLoopBuilderPrompt } from "./loopBuilderPrompt";
2+
import {
3+
buildLoopBuilderPrompt,
4+
buildLoopBuilderSystemInstructions,
5+
} from "./loopBuilderPrompt";
36

47
describe("buildLoopBuilderPrompt", () => {
58
it("embeds the seed instructions when provided", () => {
69
const prompt = buildLoopBuilderPrompt({
710
instructions: "Summarize failing CI runs",
811
});
12+
expect(prompt).toContain("Summarize failing CI runs");
913
expect(prompt).toContain(
10-
"Here's what I want automated:\n\nSummarize failing CI runs",
14+
"The user's message describes what they want automated.",
1115
);
1216
expect(prompt).not.toContain("Start by asking me");
1317
});
1418

19+
it("keeps the user prompt out of system instructions", () => {
20+
const instructions = buildLoopBuilderSystemInstructions({
21+
hasSeed: true,
22+
});
23+
24+
expect(instructions).toContain(
25+
"The user's message describes what they want automated.",
26+
);
27+
expect(instructions).not.toContain("Summarize failing CI runs");
28+
});
29+
1530
it.each([
1631
{ name: "absent", instructions: undefined },
1732
{ name: "whitespace-only", instructions: " \n" },

packages/ui/src/features/loops/loopBuilderPrompt.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,28 @@ export function buildLoopBuilderPrompt({
1313
}): string {
1414
const seed = instructions?.trim();
1515

16+
return [
17+
seed || undefined,
18+
buildLoopBuilderSystemInstructions({ hasSeed: !!seed, context }),
19+
]
20+
.filter((part): part is string => !!part)
21+
.join("\n\n");
22+
}
23+
24+
export function buildLoopBuilderSystemInstructions({
25+
hasSeed,
26+
context,
27+
}: {
28+
hasSeed: boolean;
29+
context?: { folderId: string; name: string };
30+
}): string {
1631
return `Your job in this session is to help me create a Loop for this PostHog project, then create it for me.
1732
1833
A Loop is a named, cloud-executed agent automation: instructions the agent runs whenever a trigger fires (a schedule, a GitHub event, or an API call). Loops run unattended in a sandbox and can post results, open pull requests, and keep a context up to date.
1934
2035
${
21-
seed
22-
? `Here's what I want automated:\n\n${seed}\n`
36+
hasSeed
37+
? "The user's message describes what they want automated.\n"
2338
: `Start by asking me what I want automated, and offer a couple of concrete ideas.\n`
2439
}${
2540
context

0 commit comments

Comments
 (0)