Skip to content

fix(subagents): keep agent profile fields this app does not own - #794

Merged
agegr merged 1 commit into
agegr:mainfrom
Lingrui98:fix/agent-profile-frontmatter
Sep 11, 2026
Merged

agegr merged 1 commit into
agegr:mainfrom
Lingrui98:fix/agent-profile-frontmatter

Conversation

@Lingrui98

Copy link
Copy Markdown
Contributor

Saving a profile from the Agents editor rebuilt the whole frontmatter from the 11 keys Pi Web knows, so every key the other runtime on those same files reads was dropped: name, skills, extensions, exclude_extensions, allowed_subagents, disallowed_tools, and the ext:<name> selectors inside tools:. In production that turned an orchestrator profile into one that could no longer spawn anything, and silently flipped two profiles from "advisor off" to "advisor on".

What changed

  • saveSubagentProfile round-trips frontmatter keys this app does not own, and carries foreign ext: selectors through tools:.
  • The skills / extensions spellings pi-subagents reads are seeded on the first save and kept in step while they are booleans; a hand-authored whitelist such as extensions: pi-advisor-flow is never rewritten, because the UI has no way to express it.
  • Parsing falls back to those aliases when load_skills / load_extensions are absent, so the editor reflects the state the file actually declares.
  • AGENTS.md documents which keys this app manages and which it must carry through.

Tests

  • lib/subagents.test.mjs — three new cases: unknown-key round-trip on save, alias seeding with whitelist preservation, and alias-based flag fallback.
  • npm test 976 pass, tsc --noEmit and eslint clean.

Found while running Pi Web against a set of agent definitions shared with the pi-subagents extension: those files are the contract between the two, and only one of them was writing them.

Copilot AI lite review requested due to automatic review settings September 10, 2026 09:49

Copilot AI 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.

🟡 Changes recommended

readStoredFrontmatter() can still allow overwriting a file with an unparseable frontmatter block (dropping unmanaged keys), which reintroduces data-loss risk in a key path.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens subagent profile editing so Pi Web no longer drops frontmatter fields it doesn’t own when saving shared agent profile files, preserving compatibility with other runtimes (notably pi-subagents).

Changes:

  • Preserve “unmanaged” frontmatter keys on save, while still updating the subset of keys Pi Web owns.
  • Round-trip foreign ext: tool selectors in tools: instead of stripping them during Pi Web’s built-in tool filtering.
  • Add parsing/saving behavior for skills/extensions alias flags (including whitelist-preservation) plus targeted regression tests and documentation.
File summaries
File Description
lib/subagents.ts Preserves unmanaged frontmatter keys, carries ext: selectors through tools:, and supports alias-based flag fallback/sync for skills/extensions.
lib/subagents.test.mjs Adds regression tests covering unknown-key round-trip, alias seeding/whitelist preservation, and alias fallback behavior.
AGENTS.md Documents which profile frontmatter keys Pi Web manages vs. must preserve for other runtimes.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/subagents.ts
Comment on lines +191 to +198
function readStoredFrontmatter(filePath: string): Record<string, unknown> {
if (!existsSync(filePath)) return {};
try {
return parseFrontmatter(readFileSync(filePath, "utf8")).data ?? {};
} catch {
return {};
}
}
Comment thread lib/subagents.test.mjs
Comment on lines +505 to +506
const file = join(cwd, ".pi", "agents", "fresh.md");
saveProjectSubagentProfile(cwd, profile({ name: "fresh", loadSkills: true, loadExtensions: true }));
Saving a profile from the Agents editor rebuilt the whole frontmatter from
the 11 keys this app knows, silently dropping everything the other runtime
on those same files reads: `name`, `skills`, `extensions`,
`exclude_extensions`, `allowed_subagents`, `disallowed_tools`, and the
`ext:<name>` selectors inside `tools:`. In production that turned an
orchestrator profile into one that could no longer spawn anything.

- saveSubagentProfile round-trips unknown frontmatter keys and carries
  foreign `ext:` selectors through `tools:`
- the `skills` / `extensions` spellings pi-subagents reads are seeded on the
  first save and kept in step while they are booleans; a hand-authored
  whitelist such as `extensions: pi-advisor-flow` is never rewritten
- parsing falls back to those aliases when `load_skills` / `load_extensions`
  are absent, so the editor reflects what the file actually declares
- AGENTS.md documents the ownership split

Tests: lib/subagents.test.mjs (+3 cases: unknown-key round-trip, alias
seeding with whitelist preservation, alias-based flag fallback). npm test
985 pass, tsc --noEmit and eslint clean.
@agegr
agegr force-pushed the fix/agent-profile-frontmatter branch from cb10f23 to a3925c2 Compare September 11, 2026 14:46
@agegr
agegr merged commit 553f2d7 into agegr:main Sep 11, 2026
2 checks passed
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.

3 participants