Skip to content

feat(desktop): two-layer agent prompt architecture + dynamic AGENTS.md regeneration#584

Draft
wpfleger96 wants to merge 10 commits into
mainfrom
wpfleger/agent-personas
Draft

feat(desktop): two-layer agent prompt architecture + dynamic AGENTS.md regeneration#584
wpfleger96 wants to merge 10 commits into
mainfrom
wpfleger/agent-personas

Conversation

@wpfleger96
Copy link
Copy Markdown
Collaborator

@wpfleger96 wpfleger96 commented May 14, 2026

Summary

Two changes that give managed agents reliable Sprout platform awareness.

1. Two-layer prompt architecture

Adds a shared [Base] prompt layer injected by the ACP harness on every turn — Sprout CLI reference, communication patterns, startup recovery, and workspace context. Every agent gets platform orientation without duplicating it across personas.

  • base_prompt.md compiled in via include_str!(), prepended as [Base] before [System] (persona) on all turns including heartbeats and initial messages
  • FormatPromptArgs struct replaces positional params on format_prompt()
  • SPROUT_ACP_NO_BASE_PROMPT disables it; SPROUT_ACP_BASE_PROMPT_FILE overrides the compiled-in default
  • Solo/Kit/Scout built-in personas: Sprout-specific bits removed (now in base layer), model/provider reverted to None

2. Dynamic AGENTS.md regeneration

~/.sprout/AGENTS.md now dynamically reflects workspace state. A managed section between <!-- BEGIN/END SPROUT MANAGED --> markers is regenerated whenever agents, personas, or workspace config change.

  • regenerate_nest_context() renders an active agents table into the managed section
  • try_regenerate_nest() hooks in 10 Tauri command functions — all outside lock scope
  • Marker-based merge preserves user edits outside the managed section
  • Atomic writes via tempfile::NamedTempFile; app-startup hook for first-launch currency
  • 19 unit tests including adversarial cases (marker ordering, orphan cleanup, code-block false positives, pipe/newline escaping)

@wpfleger96 wpfleger96 requested a review from wesbillman as a code owner May 14, 2026 18:53
Comment thread crates/sprout-acp/src/base_prompt.md Outdated
Comment thread desktop/src-tauri/src/managed_agents/personas.rs Outdated
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch 2 times, most recently from 23b4eb0 to 035d4c0 Compare May 15, 2026 19:43
wpfleger96 added a commit that referenced this pull request May 15, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 changed the title feat: two-layer prompt architecture for managed agents feat(desktop): two-layer agent prompt architecture + dynamic AGENTS.md regeneration May 15, 2026
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch 5 times, most recently from 350aa8a to 95515fd Compare May 16, 2026 03:26
wpfleger96 added a commit that referenced this pull request May 18, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 95515fd to 8505a9e Compare May 18, 2026 19:34
wpfleger96 added a commit that referenced this pull request May 18, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 8505a9e to 00c1a38 Compare May 18, 2026 22:37
wpfleger96 added a commit that referenced this pull request May 18, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 00c1a38 to 58a3ace Compare May 18, 2026 23:13
wpfleger96 added a commit that referenced this pull request May 18, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 58a3ace to 6db3ab4 Compare May 18, 2026 23:43
wpfleger96 added a commit that referenced this pull request May 18, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 6db3ab4 to bd11938 Compare May 18, 2026 23:48
@wpfleger96 wpfleger96 marked this pull request as draft May 19, 2026 21:31
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from bd11938 to 682d8fe Compare May 19, 2026 21:49
wpfleger96 added a commit that referenced this pull request May 19, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
wpfleger96 added a commit that referenced this pull request May 20, 2026
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 682d8fe to 76c6997 Compare May 20, 2026 19:10
Agents running in Sprout have no platform awareness — they don't know
about channels, MCP tools, @mention syntax, or the other agents in the
workspace. This adds a base layer prompt (compiled into sprout-acp via
include_str!) that gives every agent reliable Sprout context on every
turn, regardless of persona or runtime.

Base layer: platform identity, MCP tool reference, communication
patterns, workspace layout, startup recovery. Persona layer: unchanged
role-specific content (Solo/Kit/Scout behavioral protocols, worktree
discipline, quality bar).

Also adds default model (claude-sonnet-4-20250514) to all three
built-in personas so users don't need to pick at agent creation,
and fixes a merge_personas() bug where .is_some() checks would cause
infinite reset loops once built-ins carry non-None model values.
Consolidated fixes from 5 independent reviewers (3 Claude specialists,
Codex/GPT-5.5, Gemini) plus PLAN author feedback.

Structural: refactor format_prompt() from 6 positional params to
FormatPromptArgs struct — eliminates positional confusion and makes
future additions zero-cost for existing call sites.

Correctness: replace get_channel_history() references in [Context]
hints with get_messages() (the actual MCP tool name), fix $AGENT_CWD
reference in base_prompt.md (env var doesn't exist), fix [Context]
description in PERSONA_PACK_SPEC to match reality.

Config: migrate SPROUT_ACP_BASE_PROMPT_DISABLED from bare env::var
check to proper Config field (no_base_prompt), add base_prompt_file
for runtime override. Change base_prompt type from Option<String> to
Option<&'static str> to reflect compile-time constant nature.

Personas: add provider: Some("claude") alongside model on all three
built-in personas so the UI/runtime agree on the backend. Add comment
documenting merge_personas() canonical-override semantics.

Coverage: prepend [Base] to heartbeat and initial_message paths that
previously bypassed format_prompt(). Add section-ordering test with
full context. Fix trailing-newline triple-gap via trim_end().
base_prompt.md now leads with the sprout CLI (12 subcommand groups from
#585) rather than MCP tools, which are still available but secondary.
Adds the @mention formatting rule (no bold/italic), get_feed type
filtering, and a pointer to nest_agents.md for workspace conventions.

Reverts the hardcoded model/provider on Solo, Kit, and Scout back to
None. The agent binary's own default is the right choice here — pinning
claude-sonnet-4-20250514 is opinionated and will go stale. Users who
want a specific model can set it per-agent via the model picker.
AGENTS.md in ~/.sprout is now dynamically regenerated whenever personas,
agents, or workspace config changes. Agents discover their teammates on
every fresh session via a managed section demarcated by HTML comment
markers. User edits outside the markers are preserved across
regenerations.
BackendKind and RespondTo are only used in test helper constructors.
Fixes identified by crossfire review (Codex + Gemini) and plan author:

- Use tempfile::NamedTempFile for atomic writes instead of deterministic
  .tmp path that races under concurrent regeneration triggers
- Enforce ordered BEGIN/END marker search with line-start anchoring to
  prevent inverted slicing when markers are out of order or mid-line
- Strip orphan BEGIN markers before appending new managed section
- Escape pipe and newline characters in agent/persona names to prevent
  Markdown table corruption
- Rename "Role" column to "Persona" (display_name is a name, not a role)
- Move regenerate_nest_context calls outside lock scope in all mutation
  hooks to reduce lock hold time and eliminate future deadlock risk
- Add 7 adversarial unit tests: marker ordering, orphan cleanup,
  duplicates, code-block false positives, pipe/newline escaping,
  idempotency
nest.rs grew to 770 lines with regenerate_nest_context, marker
helpers, and 19 unit tests. The 500-line default is too tight for
this file — override to 800 following the established pattern.
…uplication

base_prompt.md (injected every turn via [Base]) already has a comprehensive
CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE
constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's
dynamic section now focuses on what's unique to it: active agents and
workspace info.

Also bumps personas.rs file size override from 900 to 950 to accommodate
the merge_personas inequality checks added in the review-fix commit.
Review surfaced 10 findings across 5 independent sources (3 Claude
specialists + Codex + Gemini). Key changes:

- Fix incorrect CLI syntax in base_prompt.md (missing --channel flag,
  positional arg that should be named) and stale nest_agents.md reference
- Apply line-start validation to END_MARKER in find_managed_markers,
  matching the BEGIN_MARKER contract documented in the function comment
- Extract prepend_base_prompt helper to deduplicate [Base] injection
  across format_prompt, dispatch_heartbeat, and initial_message paths
- Move base_prompt_file read from main.rs panic to Config::from_cli
  with proper ConfigError propagation and 1 MB size guard
- Extract try_regenerate_nest helper to consolidate 11 identical
  error-handling blocks across command files
- Sanitize relay_url before AGENTS.md injection (strip CR/LF)
- Fix greedy newline strip in strip_orphan_begin_marker
- Add doc comments for PromptContext.base_prompt lifetime constraint
@wpfleger96 wpfleger96 force-pushed the wpfleger/agent-personas branch from 76c6997 to 42c04f0 Compare May 20, 2026 20:58
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.

2 participants