Skip to content

Prompt System Architecture

Design Principle

Prompts are the primary artifact. The agentic system is a context supplier, not a prompt generator.

prompts/{agent}.md          ← canonical, version-controlled, standalone-ready
        │   dv-agentic PromptLoader reads this file
        │   and fills {{PLACEHOLDER}} blocks with real context
enriched system prompt      ← sent to LLM by the agent runtime

A prompt must be useful at all three levels of enrichment:

Level 0 — Raw file, used directly in any AI tool. No injection. Agent asks user for missing context.

Level 1 — Base file + team profile patch injected. Agent knows VIP API, coding rules, simulator.

Level 2 — Level 1 + project vplan + session state injected. Agent operates fully autonomously within budget.


Placeholder Convention

Placeholders use {{UPPER_SNAKE_CASE}} and are always in the Project Context section at the bottom of each prompt.

The Project Context section is always separated by a horizontal rule and a clear comment explaining it is injected content. This makes it visually obvious in standalone use that the section is absent/empty.

Placeholder Registry

Placeholder Source Used by
{{TEAM_RULES}} profiles/teams/{team}/prompt_patch.md code_generator, spec_analyst
{{IP_TYPE_RULES}} profiles/ip-types/{ip}/protocol_rules.yaml code_generator, bug_classifier, coverage_analyst
{{VIP_INDEX}} profiles/teams/{team}/vip_index.yaml code_generator
{{PROJECT_VPLAN_SUMMARY}} .agent/vplan.yaml (summarised) coverage_analyst, spec_analyst
{{KNOWN_ERROR_PATTERNS}} profiles/ error DB log_analyzer
{{KNOWN_RTL_BUGS}} .agent/memory.db log_analyzer, bug_classifier
{{SESSION_STATE}} .agent/memory.db current session all agents

If a placeholder has no data to inject (e.g. no team profile configured), the PromptLoader removes the placeholder line entirely rather than leaving {{PLACEHOLDER}} visible. The prompt must still be coherent after removal.


PromptLoader Contract

class PromptLoader:
    """Loads and enriches agent prompt templates.

    Standalone use:
        loader = PromptLoader()
        prompt = loader.load("code_generator")
        # Returns raw prompt with all {{}} removed (Level 0)

    Augmented use:
        loader = PromptLoader(project_config=config, session=session)
        prompt = loader.load("code_generator")
        # Returns fully enriched prompt (Level 1 or 2)
    """

    def load(self, agent_name: str) -> str:
        """Return the final system prompt string for the given agent."""

    def _inject(self, template: str, context: dict[str, str]) -> str:
        """Replace {{KEY}} with context[KEY], remove unmatched placeholders."""

No template language beyond {{KEY}} substitution. No Jinja2, no conditional blocks inside the prompt file itself. Complexity lives in the Python loader, not in the prompt syntax.


prompt_patch.md Format

Team profiles supply a prompt_patch.md that is injected as-is into {{TEAM_RULES}}. It must be written in natural language that reads coherently inside the parent prompt, not as a config file.

<!-- profiles/teams/team_io/prompt_patch.md -->
<!-- Injected into {{TEAM_RULES}} — write as natural prose/rules, not YAML -->

## Team IO Coding Rules

Naming: all sequences must follow `io_{feature}_{scenario}_seq` format.

VIP usage: never call `pcie_vip_driver::send_raw()` directly.
Always use the sequence-level API (`pcie_tlp_seq`, `pcie_cfg_seq`).

Simulator: Xcelium 25.03 with IMC 24.06. Coverage DB at `cov_work/`.

Forbidden patterns:
- Hardcoded transaction sizes (use `cfg.max_payload_size`)
- `fork/join` inside sequences (use UVM phasing instead)

Subagent .md Files (Claude Code / Cursor / OpenCode)

The .agent/subagents/{agent}.md files used by AI coding tools are generated from the same base prompt, not separately authored:

install-agents.sh runs PromptLoader at Level 1
(team + IP rules injected, session state omitted)
.agent/subagents/code_generator.md   ← written to disk
        ├── symlink → .claude/agents/code_generator.md
        └── symlink → .cursor/rules/code_generator.md

These files are generated, not edited by hand. The canonical source is always src/dv_agentic/prompts/code_generator.md.

The YAML front matter required by Claude Code / Cursor is prepended by the installer, not present in the source prompt:

---
name: code_generator
description: Generate and modify SV/UVM code targeting specific coverage bins or bug fixes
tools: [read_file, write_file, run_bash]
---
{enriched prompt body}

File Locations

src/dv_agentic/prompts/          ← canonical source (part of package)
    code_generator.md
    log_analyzer.md
    coverage_analyst.md
    bug_classifier.md
    spec_analyst.md
    sim_controller.md
    wave_analyzer.md
    orchestrator.md
    reporter.md

{project}/.agent/subagents/      ← generated by install-agents.sh (gitignore or commit)
    code_generator.md            ← Level 1 enriched + YAML front matter
    log_analyzer.md
    ...

{project}/.claude/agents/        ← symlinks to .agent/subagents/
{project}/.cursor/rules/         ← symlinks to .agent/subagents/