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}} wiki patterns/ (wiki-first) → profiles/ error DB (fallback) log_analyzer, bug_classifier
{{KNOWN_RTL_BUGS}} wiki bugs/ (wiki-first) → .agent/tasks/ (fallback) log_analyzer, bug_classifier
{{COVERAGE_HOLE_HISTORY}} wiki coverage/ (requires wiki.enabled: true) coverage_analyst
{{WIKI_PATTERN_SUMMARY}} wiki patterns/ statistics (requires wiki.enabled: true) code_generator
{{SESSION_STATE}} .agent/tasks/{task_id}.yaml 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 / OpenCode)

Prompts are authored once as templates and materialized by the installer (install-agents.sh or python -m dv_agentic.cli.install_agents) at Level 1: team and IP rules from project.yaml composition are injected; session state is omitted.

install-agents / install_agents CLI
        ├──► {project}/.claude/agents/{agent}.md
        │       Claude Code YAML (`name`, `description`, `tools`, …) + enriched body
        └──► {project}/.opencode/agents/{agent}.md
                OpenCode YAML (same fields as `*.tmpl.md`) + enriched body

Do not hand-edit generated files for long-term changes — update the template under src/dv_agentic/prompts/ and re-run the installer.

The canonical template files use the *.tmpl.md naming convention (for example code_generator.tmpl.md). They include OpenCode-oriented YAML at the top of the file.

For Claude Code, the installer strips that OpenCode front matter and prepends a Claude-compatible block (see dv_agentic.cli.install_agents).

Example shape for .claude/agents/*.md:

---
name: code_generator
description: Generate and modify SV/UVM code targeting specific coverage bins or bug fixes
tools: Read, Write, Bash
---
{enriched prompt body}

OpenCode outputs under .opencode/agents/ keep the template’s original YAML keys (mode, model, temperature, nested tools permissions, etc.).


File Locations

src/dv_agentic/prompts/          ← canonical templates (part of package)
    orchestrator.tmpl.md
    code_generator.tmpl.md
    ...

{project}/tools/               ← TypeScript tool adapters + `_run_agent.sh`; mirrored into `.opencode/tools/` and `.claude/tools/`
{project}/skills/              ← optional; mirrored into both tool ecosystems

{project}/.claude/agents/      ← generated (Claude format)
{project}/.opencode/agents/    ← generated (OpenCode format, matches tmpl front matter)