Skip to content

feat(programs): bundle each orchestrator flow's agent prompts - #1554

Merged
edwinyjlim merged 16 commits into
dag/3-queue-from-frontmatterfrom
dag/4-prompts-in-wizard
Nov 13, 2026
Merged

edwinyjlim merged 16 commits into
dag/3-queue-from-frontmatterfrom
dag/4-prompts-in-wizard

Conversation

@edwinyjlim

@edwinyjlim edwinyjlim commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Each orchestrator program keeps its task prompts in src/programs/<id>/agent/<type>.md. With wizard-agent-dag on, the orchestrator reads these bundled prompts. With the flag off or unset, it fetches context-mill's copy of the flow, as today.

posthog-integration's folder has no planner prompt. With the flag on, its queue comes from the graph its frontmatter declares, and no planner agent runs. The other five programs keep their planners. A fetched flow with no planner prompt fails the run with PHW_AGENT_ORCHESTRATOR_NO_PLANNER, flag on or off.

Stack

The five PRs, in merge order:

PR What it does How it fits in
Menu metadata · PostHog/context-mill#447 Adds a title, description and tags to every skill-menu entry. Ships in a context-mill release. PR 1 reads the tags, and resolves the same without them.
PR 1 · Skill resolver · #1551 Adds the wizard-agent-dag flag and the shared skill resolver the orchestrator uses when it is on. Base of the wizard stack, on main. Every later PR hangs its new path off this flag.
PR 2 · Project traits · #1552 Adds the project traits service and hands the orchestrator the traits skills match on. On PR 1. Supplies the resolver's match keys. Nothing reads a trait beyond the framework yet.
PR 3 · Queue from frontmatter · #1553 Queues a flow that has no planner prompt from the graph its prompts' frontmatter declares. On PR 2. No flow lacks a planner until PR 4 bundles one.
PR 4 · Prompts in the wizard · #1554 (this PR) Bundles each orchestrator flow's prompts in its program. With the flag on, runs read them. Top of the stack, on PR 3. posthog-integration's folder has no planner prompt, so PR 3's queue runs it.

The four wizard PRs merge in that order and ship in one release with wizard-agent-dag off. A run with the flag off or unset behaves as it does on main.

Where a run's prompts come from

flowchart LR
  subgraph wizard["Wizard release"]
    md["src/programs/&lt;id&gt;/agent/*.md"] --> mod["agent-prompts.ts<br/>imports each file as text"]
    mod --> cfg["ProgramConfig.agentPrompts"]
  end
  cm["context-mill release<br/>agent menu and prompts"]
  cfg -- "wizard-agent-dag on" --> registry["Orchestrator's prompt registry"]
  cm -- "wizard-agent-dag off" --> registry
Loading

A bundle that fails to load is reported as an exception with the step orchestrator_bundled_prompts, and the run fetches instead.

Every event sent after the prompts load carries which one the run used as the orchestrator_prompts tag: bundled or context-mill. That tag says which path a run took. The flag's value on an event does not: a pinned run reports the flag as on and still fetches.

Program Flow Prompts Planner prompt Queued by, flag on
posthog-integration integration-v2 12 No The frontmatter graph
error-tracking error-tracking 11 Yes Its planner
replay-vision replay-vision 8 Yes Its planner
feature-flags feature-flags 6 Yes Its planner
metrics metrics 4 Yes Its planner
support support 7 Yes Its planner

What differs from context-mill 1.65.0

The bundled files match the recorded release byte for byte, with two exceptions, both in posthog-integration:

Difference Why
No integrate-posthog.md, the planner prompt The planner queues the same task sets the frontmatter declares, so the wizard queues them itself.
capture adds mcp-analytics to its dependsOn The planner decides this edge case by case, and waits when it cannot tell. The graph always waits. The edge only exists in runs that queue mcp-analytics.

posthog-integration's graph, flag on

Edges a longer path already implies are left out.

flowchart LR
  install --> identify
  init --> identify
  install --> et["error-tracking"]
  init --> et
  identify --> mcp["mcp-analytics"]
  identify --> capture
  mcp --> capture
  capture --> aio["ai-observability"]
  aio --> logs
  capture --> dashboard
  et --> review
  logs --> review
  dashboard --> report
  review --> report
  warehouse -.-> report
Loading

pnpm visual-dags draws every program's graph from its frontmatter, in the waves the orchestrator runs: the sink last, and a task the wizard queues itself just before it.

What a flag-on posthog-integration run does differently

Flag off Flag on
Planning A planner agent runs first None
Task set The planner's The same set, from the frontmatter and the program's excludedTaskTypes and seedTasks
Task labels The planner writes them Each prompt's label
capture and mcp-analytics In parallel when the planner judges they touch different files capture waits
Task prompts, with their tools and models Fetched from context-mill The same text, from the bundle
Skills Installed from context-mill Installed from context-mill

Prompts and skills

With the flag on, a run's prompts come from its wizard release, and its skills still install from context-mill. A bundled prompt names its skills by menu id or by family, so every name must stay on the menu. flow-graphs.test.ts checks the names against the recorded menu.

A local context-mill (--local-context-mill) serves the skills either way, and the prompts only with the flag off.

When a bundled prompt names a skill the loaded menu has under no id and no family, the wizard is older than the skills. The run fails before any task starts, as it does for any missing skill, and the message says to run the latest wizard. Fetched prompts, a menu that did not load and a run with no framework keep the message that asks to try again, so a flag-off run reads as before.

A run pinned to a context-mill release with --context-mill-version fetches its prompts and its skills from that release, flag on or off.

Loading Markdown

A .md import is the file's text, declared in types/markdown.d.ts.

Where How
The build tsdown's loader: { '.md': 'text' }. Each program's prompts land in their own chunk, loaded on first use.
Tests A Vitest plugin, markdownAsText.
A run from source A Node hook, scripts/markdown-loader.no-jest.mjs, passed to tsx by pnpm try, the snapshot script and the e2e harness's host launcher.

Checks

Check Fails when
src/programs/__tests__/agent-prompts.test.ts A program with an agent/ folder doesn't load it, a file in the folder isn't imported, a prompt has no frontmatter or a flag that is not true or false, or a prompt differs from the recorded release beyond the two differences above
src/agent/runner/sequence/orchestrator/__tests__/flow-graphs.test.ts A dependsOn names a task outside its folder, a folder has no single sink or cannot be ordered, a skills entry is missing from the recorded menu, or posthog-integration's graph queues a different task set
pnpm test:warlock, run by every build A bundled prompt trips a rule that would end a run. It scans each agent/ folder as a fetched skill is scanned.
pnpm test:smoke, run by every build The bundle, which now holds the prompts, contains a name that must not ship

Test plan

  • pnpm typecheck
  • pnpm lint
  • pnpm build: the prompts are inlined in six lazy chunks, and the scanner smoke test passes on all six folders
  • pnpm exec vitest run: 288 files pass
  • frontmatter-queue.test.ts: a bundle that fails to load falls back to the fetch, and a fetched flow with no planner fails with its own code
  • A run from source loads the prompts through the Node hook
  • Workbench apps, flag on against off through the CI flag override: the same tasks, skills and prompts per run

🤖 Generated with Claude Code

edwinyjlim and others added 2 commits November 11, 2026 15:28
A .md import is the file's text. tsdown inlines it in the build, a Vitest
plugin loads it in tests, and a Node hook loads it in a run from source:
pnpm try and the TUI host the snapshot and wizard-ci scripts spawn.

Co-Authored-By: Claude <noreply@anthropic.com>
Each orchestrator program keeps its task prompts in agent/<type>.md, and
its agent-prompts.ts imports them as text. With wizard-agent-dag on, the
orchestrator reads the bundled prompts; off, it fetches context-mill's
copy of the flow.

The files match context-mill 1.64.0 byte for byte, with two exceptions in
posthog-integration: its folder has no planner prompt, so a run with the
flag on is queued from the frontmatter, and capture waits for
mcp-analytics, an edge the planner decides case by case.

The scanner smoke test, which every build runs, scans each agent/ folder.
pnpm visual-dags draws every program's graph from its frontmatter.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci ai-observability
  • /wizard-ci basic-integration
  • /wizard-ci feature-flags
  • /wizard-ci mcp-analytics
  • /wizard-ci replay-vision
  • /wizard-ci revenue
  • /wizard-ci self-driving
  • /wizard-ci warehouse
  • /wizard-ci warehouse-seeded

Test an individual app:

  • /wizard-ci ai-observability/anthropic
  • /wizard-ci ai-observability/google-adk
  • /wizard-ci ai-observability/groq
Show more apps
  • /wizard-ci ai-observability/manual-capture
  • /wizard-ci ai-observability/openai
  • /wizard-ci ai-observability/openai-agents
  • /wizard-ci ai-observability/opentelemetry
  • /wizard-ci ai-observability/vercel-ai
  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/flutter
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci feature-flags/django
  • /wizard-ci feature-flags/next-js
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/go-sdk
  • /wizard-ci mcp-analytics/python-sdk
  • /wizard-ci mcp-analytics/ruby-sdk
  • /wizard-ci mcp-analytics/rust-sdk
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci replay-vision/javascript-node
  • /wizard-ci replay-vision/next-js
  • /wizard-ci replay-vision/react-vite
  • /wizard-ci revenue/stripe
  • /wizard-ci self-driving/astro
  • /wizard-ci self-driving/fastapi
  • /wizard-ci self-driving/nuxt
  • /wizard-ci self-driving/react-router
  • /wizard-ci self-driving/sveltekit
  • /wizard-ci warehouse/monorepo-env
  • /wizard-ci warehouse/multi-source-next
  • /wizard-ci warehouse/stripe-node
  • /wizard-ci warehouse/zero-source
  • /wizard-ci warehouse-seeded/next-stripe
  • /wizard-ci warehouse-seeded/next-stripe-declined

Test against a Context Mill branch:

  • /wizard-ci all context-mill:my-branch

Add context-mill:<branch> to any command above to pin the Context Mill branch. It defaults to main.

Results will be posted here when complete.

@edwinyjlim
edwinyjlim added this pull request to stack #1555 November 12, 2026 05:01
@edwinyjlim
edwinyjlim marked this pull request as ready for review November 12, 2026 17:54
@edwinyjlim
edwinyjlim requested review from a team as code owners November 12, 2026 17:54
@edwinyjlim
edwinyjlim requested review from JamesPatrickGill, TueHaulund, ablaszkiewicz, fasyy612, hpouillot and ksvat and removed request for a team November 12, 2026 17:54
@veria-ai

veria-ai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

PR overview

No security issues were found in this pull request.

Reviews

@posthog-security-review-bot posthog-security-review-bot Bot added the security-review Request a security review label Nov 12, 2026
@posthog-security-review-bot

posthog-security-review-bot Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

✅ Security review complete — 217e1417da66

1 finding posted as a review, in 7 min.

Add the security-review label to run again on the latest commit.

@johncwaters johncwaters left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Automated review. Not written by a human.

Verdict: APPROVE

@sarahxsanders sarahxsanders left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a littttle bit worried about creating two copies of the prompts/relying on both being updated here. how can we enforce that they are in sync?

is this temporary/should we discuss if we've outgrown the need for separate context + wizard repos?

@posthog-security-review-bot posthog-security-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-driven security review - findings inline.

Comment thread scripts/visual-dags.no-jest.ts Resolved
@posthog-security-review-bot posthog-security-review-bot Bot removed the security-review Request a security review label Nov 12, 2026
@edwinyjlim edwinyjlim added the security-review Request a security review label Nov 12, 2026
@posthog-security-review-bot

posthog-security-review-bot Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

✅ Security review complete — cb8a9656390b

No findings above the confidence threshold, in 6 min.

Add the security-review label to run again on the latest commit.

@posthog-security-review-bot posthog-security-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-driven security review - no findings.

@posthog-security-review-bot posthog-security-review-bot Bot removed the security-review Request a security review label Nov 12, 2026

@fasyy612 fasyy612 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replay parts look good 👍

@gewenyu99 gewenyu99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some nits

Comment thread scripts/visual-dags.no-jest.ts Resolved
Comment thread src/agent/runner/sequence/README.md Resolved
Comment thread scripts/visual-dags.no-jest.ts Resolved
Comment thread src/agent/agent-prompt-loader.ts Resolved
edwinyjlim and others added 9 commits November 12, 2026 19:33
# Conflicts:
#	scripts/wizard-ci-mcp.no-jest.ts
…kill

A bundled prompt can name a skill the menu no longer publishes. The run
still fails before any task starts, and it now says to run the latest
wizard, since trying again cannot help. Fetched prompts, a menu that did
not load and a run with no framework keep the message that asks to try
again.

Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts:
#	src/agent/runner/sequence/README.md
#	src/agent/runner/sequence/orchestrator/__tests__/frontmatter-queue.test.ts
…ssing planner its own failure

A prompt bundle that fails to load is reported as an exception with the
step `orchestrator_bundled_prompts`, and the run fetches its flow from
context-mill.

A fetched flow with no planner prompt ends the run with
PHW_AGENT_ORCHESTRATOR_NO_PLANNER and a message for the user.

The README says the `orchestrator_prompts` tag is on every event sent
after the prompts load.

Co-Authored-By: Claude <noreply@anthropic.com>
… spells its flags

The parser reads a prompt with no frontmatter as a task with no
dependencies, and any flag value but `true` as false. The check covers
every program that bundles prompts, recorded or not.

Co-Authored-By: Claude <noreply@anthropic.com>
…rator runs them

`pnpm visual-dags` draws the sink in the last wave, and a task the
wizard queues itself that names no dependency in the wave before it. A
missing page opener no longer fails the script after the page is
written.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

5 participants