Skip to content

feat(sdk)\!: standardize enhanced system prompt across all sessions#367

Merged
lavaman131 merged 4 commits intomainfrom
lavaman131/feature/enhance-system-prompt
Mar 6, 2026
Merged

feat(sdk)\!: standardize enhanced system prompt across all sessions#367
lavaman131 merged 4 commits intomainfrom
lavaman131/feature/enhance-system-prompt

Conversation

@lavaman131
Copy link
Collaborator

@lavaman131 lavaman131 commented Mar 5, 2026

SUMMARY

This PR standardizes agent behavior by introducing a shared enhanced system prompt that is automatically applied to all SDK sessions (Claude, Copilot, OpenCode). The enhanced prompt enforces:

  • Tool usage policies (prefer playwright-cli over web fetch/search)
  • Testing discipline (invoke testing-anti-patterns skill before test modifications)
  • Software engineering principles (SOLID, design patterns, architectural hygiene)

All custom instructions are now appended to this base prompt rather than replacing it, ensuring consistent guardrails across chat and workflow executions.

BREAKING CHANGES

API Rename: systemPrompt → additionalInstructions

The systemPrompt parameter has been renamed to additionalInstructions across all SDK clients and workflow configurations to better reflect its new append-only behavior.

Before:

session = await client.createSession({
  systemPrompt: "You are a research assistant"
});

After:

session = await client.createSession({
  additionalInstructions: "You are a research assistant"
});

Behavior Change: Default Enhanced Prompt

All sessions now default to using ENHANCED_SYSTEM_PROMPT (defined in src/sdk/enhanced-system-prompt.ts), which includes:

  • Tool usage policies (e.g., prefer playwright-cli over web fetch/search)
  • Testing discipline (e.g., invoke testing-anti-patterns skill before test modifications)
  • Software engineering principles (SOLID, design patterns, architectural hygiene)

Custom instructions are appended to this base prompt rather than replacing it.

CHANGES

Core:

  • Added src/sdk/enhanced-system-prompt.ts with centralized ENHANCED_SYSTEM_PROMPT definition
  • Renamed systemPrompt to additionalInstructions in SessionConfig interface

SDK Clients:

  • ClaudeAgentClient: Use additionalInstructions with preset append mode
  • CopilotClient: Use additionalInstructions with append mode
  • OpenCodeClient: Inject additionalInstructions into prompt parts with XML tags

CLI and Chat:

  • Added --additional-instructions flag to atomic chat command
  • Updated chatCommand to apply enhanced prompt by default via resolveChatAdditionalInstructions()
  • Updated chat UI to remove obsolete systemPrompt handling

Workflows:

  • Renamed systemPrompt to additionalInstructions in workflow node configs
  • Updated workflow graph builder API (removed from SubAgentConfig, AgentNodeConfig, etc.)

Testing:

  • Added comprehensive tests for instruction resolution (resolveChatAdditionalInstructions)
  • Added SDK client tests to verify append-mode behavior
  • Updated existing tests to use additionalInstructions

MIGRATION GUIDE

For SDK users, rename the parameter:

const session = await client.createSession({
-  systemPrompt: "Custom instructions"
+  additionalInstructions: "Custom instructions"
});

For workflow definitions:

graph<State>()
  .subagent({
    id: "researcher",
    agent: "codebase-analyzer",
    task: "Analyze authentication flow",
-   systemPrompt: "Focus on security"
+   additionalInstructions: "Focus on security"
  })

For CLI users:

atomic chat --additional-instructions "Be concise" "review this patch"

IMPLEMENTATION DETAILS

The enhanced prompt is centralized in src/sdk/enhanced-system-prompt.ts and applied differently per SDK:

  • Claude: Uses preset "claude_code" with append mode
  • Copilot: Uses systemMessage with mode: "append"
  • OpenCode: Wraps instructions in <additional_instructions> XML tags within prompt parts (not injected for agent-dispatch prompts)

TESTING NOTES

  • Pre-push checks passed via lefthook
  • All three SDK clients tested with append-mode behavior
  • No database migrations required
  • The enhanced system prompt can be updated centrally in src/sdk/enhanced-system-prompt.ts

IMPACT

This change ensures that all agent sessions—whether initiated through chat, workflows, or direct SDK usage—operate with consistent guardrails and best practices, improving code quality and reducing antipatterns across the board.

Add a shared enhanced prompt and wire it as the fallback system prompt in chat command, chat UI, and workflow graph nodes so all SDK sessions inherit consistent tool-use and engineering guidance.

Assistant-model: gpt-5.3-codex
@claude
Copy link

claude bot commented Mar 5, 2026

PR Review: feat(sdk): enforce enhanced system prompt across sessions

Thanks for the PR! The idea of standardizing agent behavior with a shared system prompt is valuable. Here's my detailed review:


Code Quality Issues

1. Inconsistent System Prompt Override Behavior (Bug)

There's a significant inconsistency in how the enhanced prompt is applied across the three modified files:

File Behavior User Override?
src/commands/chat.ts:698 systemPrompt: ENHANCED_SYSTEM_PROMPT (unconditional) ❌ No
src/ui/chat.tsx:6383 options.systemPrompt ?? ENHANCED_SYSTEM_PROMPT ✅ Yes
src/workflows/graph/nodes.ts:182 systemPrompt ?? sessionConfig?.systemPrompt ?? ENHANCED_SYSTEM_PROMPT ✅ Yes

In chat.ts, the system prompt is always set to ENHANCED_SYSTEM_PROMPT, ignoring any user-provided prompts. This contradicts the PR description which states the feature "allows explicit prompt overrides."

Suggested fix for src/commands/chat.ts:

systemPrompt: userProvidedPrompt ?? ENHANCED_SYSTEM_PROMPT,

2. Potential Double Application

Since chat.ts builds the sessionConfig with ENHANCED_SYSTEM_PROMPT and passes it to startChatUI, and then chat.tsx also applies the fallback logic, the prompt is redundantly evaluated. While not a bug (same value), it suggests the application point should be consolidated to one location.


Test Coverage

No tests were added for this new functionality. Consider adding:

  1. Unit test for the prompt export - Verify ENHANCED_SYSTEM_PROMPT is defined and non-empty
  2. Integration tests for fallback behavior - Verify that:
    • Custom prompts override the default when provided
    • Default is applied when no custom prompt is set
  3. Snapshot test - Lock down the prompt content to catch unintended changes

Example test skeleton:

import { test, expect } from "bun:test";
import { ENHANCED_SYSTEM_PROMPT } from "../sdk/enhanced-system-prompt.ts";

test("ENHANCED_SYSTEM_PROMPT is defined and non-empty", () => {
  expect(ENHANCED_SYSTEM_PROMPT).toBeDefined();
  expect(ENHANCED_SYSTEM_PROMPT.length).toBeGreaterThan(0);
});

test("ENHANCED_SYSTEM_PROMPT contains required sections", () => {
  expect(ENHANCED_SYSTEM_PROMPT).toContain("Tool Usage");
  expect(ENHANCED_SYSTEM_PROMPT).toContain("Software Engineering Principles");
});

Security Considerations

The enhanced prompt correctly uses <EXTREMELY_IMPORTANT> tags to emphasize critical instructions. However:

  • The directive NEVER use web fetch or web search tools could be bypassed if the underlying agent doesn't respect these instructions. Consider whether this needs enforcement at the SDK level.

Performance

No performance concerns - the prompt is a static string constant with minimal overhead.


Best Practices Feedback

Positive:

  • Well-documented new file with clear purpose
  • Good use of template literals for the multi-line prompt
  • Clean PR description with clear summary of changes

Suggestions:

  • Consider adding as const for type narrowing: export const ENHANCED_SYSTEM_PROMPT = \...`.trim() as const;`
  • The prompt content is comprehensive but quite long (~46 lines). Consider whether all sections are necessary for every session, or if some could be conditionally included based on use case.

Summary

Category Status
Code Quality ⚠️ Inconsistency in override behavior needs fixing
Bugs 🔴 chat.ts unconditionally overrides user prompts
Performance ✅ No issues
Security ✅ Reasonable prompt constraints
Test Coverage 🔴 No tests added

Recommendation: Request changes to fix the inconsistent override behavior in chat.ts and add basic test coverage before merging.

@claude claude bot changed the title feat(sdk): enforce enhanced system prompt across sessions feat(sdk): standardize enhanced system prompt across all sessions Mar 5, 2026
Rename session config from systemPrompt to additionalInstructions and append it through provider-native flows instead of overriding system prompts. This keeps default prompts for Claude, Copilot, and OpenCode while aligning workflow and sub-agent nodes with additive instruction behavior.

Assistant-model: openai/gpt-5.3-codex
@claude claude bot changed the title feat(sdk): standardize enhanced system prompt across all sessions feat(sdk)\!: standardize enhanced system prompt across all sessions Mar 5, 2026
@claude
Copy link

claude bot commented Mar 5, 2026

PR Review: feat(sdk)!: standardize enhanced system prompt across all sessions

Summary

This PR introduces a centralized ENHANCED_SYSTEM_PROMPT and standardizes how additional instructions are passed to all SDK clients (Claude, OpenCode, Copilot). The key change renames systemPrompt to additionalInstructions throughout, ensuring prompts are appended to native provider defaults rather than overriding them.


✅ Strengths

  1. Clean Abstraction: The rename from systemPrompt to additionalInstructions accurately reflects the behavior - instructions are appended, not overriding.

  2. Consistent Provider Integration: Each SDK client correctly uses native append mechanisms:

    • Claude: Uses { type: "preset", preset: "claude_code", append: ... }
    • Copilot: Uses { mode: "append", content: ... }
    • OpenCode: Wraps in <additional_instructions> XML tags in the message itself
  3. Smart Agent Dispatch Handling (OpenCode): The buildOpenCodePromptParts function correctly excludes additional instructions from agent-dispatch prompts (line 525-527), avoiding duplication when sub-agents inherit context.

  4. Good Test Coverage: Tests verify:

    • Copilot append-mode session creation (copilot.test.ts:78-123)
    • OpenCode instruction injection vs agent-dispatch exclusion (opencode.events.test.ts:56-166)
    • Workflow node instruction handling (nodes.test.ts:128-180)
  5. Breaking Change Handled Properly: The \! in the PR title correctly flags this as a breaking change since systemPrompt is removed from public interfaces.


⚠️ Concerns & Suggestions

1. Enhanced Prompt Content Assumptions

The ENHANCED_SYSTEM_PROMPT references specific skills (playwright-cli, testing-anti-patterns) that may not be available in all agent configurations:

// src/sdk/enhanced-system-prompt.ts:14-15
- NEVER use web fetch or web search tools. Use the playwright-cli skill instead.
- ALWAYS invoke your testing-anti-patterns skill BEFORE creating or modifying any tests.

Recommendation: Consider adding a note in the docstring or validating skill availability, or make the skill references conditional.

2. Forced Injection in Chat Command

src/commands/chat.ts:698 unconditionally injects ENHANCED_SYSTEM_PROMPT:

additionalInstructions: ENHANCED_SYSTEM_PROMPT,

This doesn't respect any user override. If a user explicitly wants to omit or replace additional instructions, they cannot.

Recommendation: Consider allowing an override via CLI flag or config, e.g.:

additionalInstructions: options.additionalInstructions ?? ENHANCED_SYSTEM_PROMPT,

3. Missing Test for Chat Command Integration

The chat command now passes additionalInstructions, but there's no test verifying this is correctly wired through to the session. Consider adding a test in chat.test.ts or chat.providers.test.ts.

4. Workflow Nodes Remove systemPrompt Without Migration Path

The SubagentConfig and ParallelSubagentNodeConfig interfaces no longer accept systemPrompt:

  • src/workflows/graph/builder.ts:107-108 (removed)
  • src/workflows/graph/nodes.ts:1720 (removed)

If any external workflow definitions rely on systemPrompt, they will silently lose those configurations.

Recommendation: Either:

  • Add a deprecation warning in the builder that logs if systemPrompt is passed
  • Document migration in the PR body/CHANGELOG

5. Inconsistent Default in agentNode

In nodes.ts:178, the session config is built with:

additionalInstructions: additionalInstructions ?? sessionConfig?.additionalInstructions,

This means if additionalInstructions is explicitly passed as undefined, it uses sessionConfig?.additionalInstructions. But the test at nodes.test.ts:157-177 asserts that additionalInstructions: undefined is passed to createSession. Verify this is intentional - it means agentNode does not inherit the enhanced prompt by default.


🔒 Security

No security concerns. The enhanced prompt adds defensive guidance (KISS, DIP, etc.) rather than introducing new capabilities.


📊 Performance

No performance concerns. The string concatenation in buildOpenCodePromptText is O(n) and only occurs once per message.


🧪 Test Coverage Assessment

Component Coverage
Claude client append mode ✅ Covered (claude.test.ts:1203-1210)
Copilot client append mode ✅ Covered (copilot.test.ts:78-123)
OpenCode instruction injection ✅ Covered (opencode.events.test.ts:56-116)
OpenCode agent dispatch exclusion ✅ Covered (opencode.events.test.ts:118-166)
Workflow agentNode ✅ Covered (nodes.test.ts:128-180)
Chat command integration Missing
Enhanced prompt content validation Missing (would be nice but not critical)

Verdict

Approve with minor suggestions. The architectural change is sound and well-implemented. The main recommendations are:

  1. Add a test for chat command → session config wiring
  2. Document migration path for users of systemPrompt in workflows
  3. Consider making the enhanced prompt opt-out capable

Nice work standardizing the prompt injection approach across all three SDK clients! 🎯

Allow chat sessions to accept additional instructions while keeping the enhanced default prompt as the baseline so users can tailor behavior per run.

Assistant-model: openai/gpt-5.3-codex
@claude
Copy link

claude bot commented Mar 5, 2026

PR Review: feat(sdk)!: standardize enhanced system prompt across all sessions

Summary

This PR introduces a centralized ENHANCED_SYSTEM_PROMPT and renames systemPrompt to additionalInstructions across the SDK. Overall, this is a well-structured change that improves consistency across Claude, OpenCode, and Copilot integrations.


Code Quality & Best Practices

Strengths:

  • Clean separation of concerns with enhanced-system-prompt.ts as a single source of truth
  • Good test coverage for the new functionality (chat.test.ts, copilot.test.ts, opencode.events.test.ts, nodes.test.ts)
  • Proper trimming of instructions to handle whitespace-only inputs
  • Consistent API naming (additionalInstructions) across all SDK clients

Suggestions:

  1. src/sdk/enhanced-system-prompt.ts:9-46 - The enhanced prompt contains domain-specific rules (e.g., "use playwright-cli skill", "invoke testing-anti-patterns skill") that assume specific skill availability. Consider documenting these dependencies or making the prompt configurable for environments where these skills may not exist.

  2. src/commands/chat.ts:532-541 - The resolveChatAdditionalInstructions function returns string | undefined but always returns a string (never undefined). The return type should be string for clarity:

    export function resolveChatAdditionalInstructions(
      options: Pick<ChatCommandOptions, "additionalInstructions">
    ): string {  // Not string | undefined

Potential Issues

  1. Breaking Change Handling - The rename from systemPrompt to additionalInstructions is correctly marked as breaking (\!), but ensure downstream consumers (workflows, custom configs) are updated. The removal of systemPrompt from:

    • SpawnSubagentOptions (src/ui/commands/registry.ts)
    • SubAgentConfig (src/workflows/graph/builder.ts)
    • SubagentNodeConfig and ParallelSubagentNodeConfig (src/workflows/graph/nodes.ts)

    ...may break existing workflow definitions that relied on per-agent prompt customization.

  2. OpenCode vs Claude/Copilot Injection Difference - OpenCode injects additional instructions via XML tags in the message (<additional_instructions>...</additional_instructions>), while Claude/Copilot use native append mechanisms. This inconsistency could lead to different behavior:

    • Claude/Copilot: Instructions are part of the system prompt
    • OpenCode: Instructions are prepended to each user message

    This is fine if intentional, but worth documenting.

  3. src/workflows/graph/nodes.ts:181 - In agentNode, the additionalInstructions from config takes precedence over sessionConfig?.additionalInstructions, but there's no way to merge them. If a workflow passes both, the sessionConfig value is silently dropped.


Performance Considerations

  • The ENHANCED_SYSTEM_PROMPT is ~1.5KB of text, which is minimal overhead per session
  • buildOpenCodePromptText creates new strings on each message send; acceptable but could be optimized for high-throughput scenarios if needed

Security Concerns

  • No security issues identified
  • The enhanced prompt enforces good practices (dependency injection, separation of concerns)
  • No user-controlled input reaches the enhanced prompt without validation (trimming)

Test Coverage

Good coverage for:

  • resolveChatAdditionalInstructions behavior (default, appending, blank handling)
  • Copilot session creation with append-mode instructions
  • OpenCode prompt injection (with and without agent dispatch)
  • agentNode session configuration

Recommended additions:

  • Test that Claude SDK correctly receives the appended system prompt (only indirect test via mock in claude.test.ts)
  • Edge case: Very long additionalInstructions string behavior
  • Test buildOpenCodePromptText with special characters/newlines in instructions

Minor Nits

  1. src/sdk/enhanced-system-prompt.ts:14-15 - The tool usage rules reference specific skills. If these skills are renamed, this prompt will become outdated. Consider a more generic formulation or make skill names configurable.

  2. src/cli.ts:103 - The example --additional-instructions "Be concise" "review this patch" may cause confusion—it appears as if "review this patch" is the initial prompt, but the flag only takes one argument. Clarify the example.


Verdict

Approve with minor suggestions. This is a solid refactoring that standardizes agent behavior across SDKs. The breaking changes are well-documented, and test coverage is adequate. Address the return type inconsistency in resolveChatAdditionalInstructions and consider documenting the OpenCode vs Claude/Copilot injection difference.

@claude
Copy link

claude bot commented Mar 5, 2026

PR Review: feat(sdk)!: standardize enhanced system prompt across all sessions

Overall Assessment

This is a well-structured PR that standardizes agent behavior through a shared enhanced system prompt. The breaking change is clearly documented with a migration guide.


✅ Code Quality & Best Practices

Strengths:

  • Clean separation of the enhanced prompt into its own module (src/sdk/enhanced-system-prompt.ts)
  • Consistent API rename (systemPromptadditionalInstructions) across all affected files
  • Well-documented PR description with clear migration guide
  • The resolveChatAdditionalInstructions function properly handles edge cases (blank/whitespace instructions)

Suggestions:

  1. Consider adding a JSDoc example to resolveChatAdditionalInstructions showing the expected output format
  2. The buildOpenCodePromptText function in opencode.ts:489-500 follows the same pattern - good consistency

⚠️ Potential Issues

  1. Silent breaking change: Users passing the old systemPrompt parameter will experience silent failures (no effect). Consider:

    • Adding a deprecation warning in development mode if systemPrompt is detected
    • Or documenting this clearly in release notes with a search/replace migration command
  2. OpenCode sub-agent dispatch: In buildOpenCodePromptParts (line 517-536), when agentName is provided, additionalInstructions is intentionally not injected. The test confirms this is expected, but the reasoning could be documented with a comment explaining why sub-agents shouldn't receive the enhanced prompt.

  3. Test removed in builder.test.ts: The removal of the systemPrompt can be provided as string test reduces coverage. While intentional, consider adding a negative test confirming that passing systemPrompt has no effect.


📊 Performance Considerations

The enhanced system prompt adds ~700-800 tokens to every session. This has implications:

  • Cost: Additional input tokens per API call
  • Context window: Slightly reduced available context for conversation

Consider:

  • Adding the token count as a comment in enhanced-system-prompt.ts for visibility
  • Documenting this in the PR or README so users understand the tradeoff

🔒 Security

No security concerns identified. The prompt contents are static and the XML-like formatting tags are safe styling conventions.


🧪 Test Coverage

Good coverage:

  • resolveChatAdditionalInstructions - default, append, blank cases ✅
  • CopilotClient append-mode behavior ✅
  • OpenCodeClient instruction routing (injection & agent dispatch) ✅
  • agentNode session instructions ✅

Suggestions:

  • Add a test case in claude.test.ts similar to the Copilot test that explicitly verifies append-mode behavior
  • Consider an integration test that verifies end-to-end enhanced prompt application

Minor Nits

  1. src/sdk/enhanced-system-prompt.ts:9 - The template literal has a leading newline before <EXTREMELY_IMPORTANT> which is trimmed. This is fine but could be simplified by starting on the same line.

  2. Consider exporting a ENHANCED_SYSTEM_PROMPT_VERSION constant to help track changes over time.


Summary

Verdict: Approve with minor suggestions 👍

The PR achieves its goal of standardizing agent behavior across all SDK sessions. The code is clean, well-tested, and the breaking change is properly documented. The suggestions above are improvements for future robustness but not blockers.

@lavaman131 lavaman131 merged commit 0c44824 into main Mar 6, 2026
3 checks passed
@lavaman131 lavaman131 deleted the lavaman131/feature/enhance-system-prompt branch March 6, 2026 00:00
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