Skip to content

feat: inject personalization custom instructions into cloud runs#2401

Draft
joshsny wants to merge 2 commits into
mainfrom
posthog-code/inject-personalization-cloud-runs
Draft

feat: inject personalization custom instructions into cloud runs#2401
joshsny wants to merge 2 commits into
mainfrom
posthog-code/inject-personalization-cloud-runs

Conversation

@joshsny
Copy link
Copy Markdown
Contributor

@joshsny joshsny commented May 28, 2026

Problem

Personalization text typed into Settings only reached local agent runs. Cloud runs ignored it, so user preferences like "always create a PR for me" were dropped — surfaced in a Slack thread where multiple folks lost work because cloud tasks never opened a PR before the sandbox was reaped.

The Slack workaround ("loosen the cloud PR-eagerness rules") is a separate, blunter knob. This PR fixes the underlying issue: the user's personalization should always reach the agent's system prompt, on both local and cloud, and it should be injected safely since it is user-generated content.

Changes

  • Shared helper (packages/shared/src/user-instructions.ts) — formatUserCustomInstructions wraps raw user text in <user_custom_instructions> delimiter tags, defangs any nested closing tag the user might have typed, truncates to the same 2,000-char cap the renderer enforces, and prepends a short trust-framing preamble that tells the agent the contents are preferences (not platform instructions that can override safety boundaries).
  • Local main service (apps/code/src/main/services/agent/service.ts) — drops the bare User custom instructions:\n${customInstructions} concatenation in favor of the shared helper, so local runs get the same safe wrapping.
  • Renderer cloud paths (apps/code/src/renderer/api/posthogClient.ts, apps/code/src/renderer/sagas/task/task-creation.ts, apps/code/src/renderer/features/sessions/service/service.ts) — read customInstructions from the settings store and forward it on both cloud-run entry points: createTaskRun (new task) and runTaskInCloud (follow-up / resume). The renderer also PATCHes the freshly created task run's state with { custom_instructions: ... } before the agent server reads it, so the feature works today without waiting for a backend change to thread custom_instructions from request body onto run state.
  • Cloud agent server (packages/agent/src/server/agent-server.ts) — _doInitializeSession reads preTaskRun.state.custom_instructions and passes it to buildSessionSystemPrompt, which merges the wrapped block alongside the existing cloud-task attribution, signed-commit, and PR-publishing rules.

How did you test this?

  • pnpm --filter @posthog/agent typecheck — clean
  • pnpm --filter code typecheck — clean
  • pnpm --filter @posthog/shared new user-instructions.test.ts covers null/empty input, wrapping shape, closing-tag defang (lowercase + uppercase variants), length truncation, and whitespace trimming.
  • vitest run src/server/agent-server.test.ts — 50/50 pass, including five new cases for the personalization block (presence, absence, blank handling, closing-tag defang, merging with a claudeCode.systemPrompt override).
  • Full apps/code vitest run — 1,539/1,546 pass; the 7 remaining failures are pre-existing archive integration tests that require git commit (blocked by the sandbox guard).
  • Did not exercise the cloud sandbox end-to-end manually — the change is gated on backend behavior I cannot run here.

Publish to changelog?

do not publish to changelog


Created with PostHog Code

joshsny added 2 commits May 28, 2026 09:04
User personalization typed in Settings now reaches the agent system prompt
on both local and cloud runs. Previously only local sessions consumed the
text, so cloud tasks ignored preferences like "always create a PR".

- Add a shared `formatUserCustomInstructions` helper that wraps the raw
  text in delimiter tags, defangs any nested closing tag, and reminds the
  agent the contents are user preferences (not platform instructions).
- Local main service uses the helper instead of plain concatenation.
- Renderer forwards `customInstructions` on cloud `createTaskRun` /
  `runTaskInCloud` request bodies and also PATCHes the new run's state
  with `custom_instructions` before the sandbox can read it, so the cloud
  agent server picks up the user's preferences regardless of whether the
  backend has shipped first-class support for the field yet.
- Cloud agent server reads `state.custom_instructions` and appends the
  wrapped block to its system prompt, alongside the existing cloud-task
  attribution and PR-publishing rules.

Generated-By: PostHog Code
Task-Id: 968ebac4-e260-4d8a-a317-fe1e9698e158
- Drop the unused `custom_instructions` request-body field on cloud-run
  options. The backend doesn't accept it; the state PATCH alone is what
  actually gets the value into the cloud sandbox.
- Shorten the helper's trust-framing preamble to one line and trim its
  tests to the four cases that actually matter (null, wrap, defang, cap).
- Inline a small `join` helper in `buildSessionSystemPrompt` instead of
  the longer `segments` wrapper.
- Cut the agent-server tests down to wrap-present + wrap-absent.

Generated-By: PostHog Code
Task-Id: 968ebac4-e260-4d8a-a317-fe1e9698e158
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant