Agentic Prompt Engineering Blueprint

Personal study notes on creating custom agentic prompts for Claude Code.

The Big Picture

There are 4 types of agentic prompts in Claude Code. Each lives in a specific location and serves a different purpose:

Type Location Creation Method Complexity
Command / Skill .claude/commands/*.md or .claude/skills/<name>/SKILL.md Snippet template (agpc) Simple — write directly
Agent .claude/agents/**/*.md Snippet template (agpa) Simple — write directly
Orchestration .claude/commands/*.md Meta-prompt (plan_w_team.md) Complex — needs generation + team

Since v2.1.3 (Jan 9, 2026), commands and skills are merged — same front matter, same behavior. Skills add optional features like supporting files and auto-invocation by Claude.

Key Insight

  • Commands and Agents are simple enough to scaffold with VS Code snippets and fill in manually.
  • Skills and Orchestration are complex — they need a meta-prompt (a command that generates the actual prompt/plan for you).
  • The meta-prompt itself IS a custom command. So commands are the foundation of everything.

The Meta-Prompt Pattern (Two-Step)

Step 1: Meta-prompt (command) → generates a plan/structure
Step 2: Agents execute/build from that plan

Example: /plan_w_team is a meta-prompt command that:

  1. Takes user requirements as input
  2. Generates a spec file in specs/ with task descriptions
  3. The spec includes team orchestration (which agents to use)
  4. Agents (builder, validator) then execute the plan

What Each Type Does

1. Custom Command (/slash commands)

  • What: A prompt you invoke with /command-name in Claude Code
  • Where: .claude/commands/your-command.md
  • How it works: Front matter defines model, tools, hooks. Body is the prompt instructions. Receives user input via $ARGUMENTS.
  • Example: /plan_w_team create a REST API — runs the planning meta-prompt

All command front matter fields

---
name: my-command                          # Display name
description: What this command does       # Shown in /command list
argument-hint: [user prompt]              # Hint shown during autocomplete
model: opus|sonnet|haiku                  # Model to use
allowed-tools: Task, Bash, Read, Edit, Write, Glob, Grep, WebFetch, WebSearch, ...
disallowed-tools: Task, EnterPlanMode     # Tools to block
disable-model-invocation: false|true      # Prevent auto-invocation
user-invocable: true|false                # Show/hide in /menu
context: fork                             # Run in forked subagent
agent: general-purpose|Explore|Plan       # Subagent type when context: fork
hooks:
  PreToolUse:                             # Before tool executes
    - matcher: "Bash"                     # Regex match tool name
      hooks:
        - type: command
          command: "echo 'pre-hook'"
          timeout: 600
          once: false|true
  PostToolUse:                            # After tool succeeds
    - matcher: "Edit|Write"
      hooks:
        - type: command
          command: "echo 'post-hook'"
          timeout: 600
          once: false|true
  Stop:                                   # When Claude finishes responding
    - hooks:
        - type: command
          command: "echo 'stop-hook'"
          timeout: 600
          once: false|true
  UserPromptSubmit:                       # When user submits prompt
    - hooks:
        - type: command
          command: "echo 'prompt-submit-hook'"
  SessionStart:                           # When session begins
    - matcher: "startup|resume|clear|compact"
      hooks:
        - type: command
          command: "echo 'session-start-hook'"
---

2. Custom Agent (sub-agents)

  • What: A specialized worker that gets spawned by commands or orchestrators
  • Where: .claude/agents/team/your-agent.md
  • How it works: Front matter defines name, model, color, tool restrictions. Body defines the agent’s role and workflow. Uses TaskGet/TaskUpdate to receive and report on tasks.
  • Examples: builder.md (writes code), validator.md (read-only verification)

All agent front matter fields

---
name: builder                             # Unique identifier (lowercase, hyphens)
description: What this agent does         # When Claude should delegate to this agent
model: opus|sonnet|haiku|inherit          # Model to use
color: cyan|yellow|green|red|magenta|blue # Terminal color
tools: Task, Bash, Read, Edit, Write, ... # Tools agent can use (inherits all if omitted)
disallowedTools: Write, Edit, NotebookEdit # Tools to deny
permissionMode: default|acceptEdits|dontAsk|bypassPermissions|plan
maxTurns: 25                              # Max agentic turns before stopping
skills: skill-name                        # Skills to preload
isolation: worktree                       # Run in isolated git worktree
background: false|true                    # Run as background task
hooks:
  PreToolUse:                             # Before tool executes
    - matcher: "Bash"
      hooks:
        - type: command
          command: "echo 'pre-hook'"
          timeout: 600
  PostToolUse:                            # After tool succeeds
    - matcher: "Edit|Write"
      hooks:
        - type: command
          command: "echo 'post-hook'"
          timeout: 600
  Stop:                                   # When agent finishes
    - hooks:
        - type: command
          command: "echo 'stop-hook'"
          timeout: 600
  SubagentStart:                          # When a sub-agent spawns
    - matcher: "builder"
      hooks:
        - type: command
          command: "echo 'subagent-start-hook'"
  SubagentStop:                           # When a sub-agent finishes
    - matcher: "builder"
      hooks:
        - type: command
          command: "echo 'subagent-stop-hook'"
  TaskCompleted:                          # When a task marked completed
    - hooks:
        - type: command
          command: "echo 'task-completed-hook'"
  TeammateIdle:                           # When teammate about to go idle
    - hooks:
        - type: command
          command: "echo 'teammate-idle-hook'"
---

3. Custom Skill (= Command, merged since v2.1.3)

Since v2.1.3 (Jan 9, 2026), commands and skills are merged. .claude/commands/review.md and .claude/skills/review/SKILL.md both create /review and work the same way.

  • What: A reusable capability with specialized knowledge
  • Where: .claude/skills/<skill-name>/SKILL.md
  • Same front matter as commands — model, description, allowed-tools, hooks, etc.

What skills add over commands:

Feature Commands Skills
Location .claude/commands/*.md .claude/skills/<name>/SKILL.md
Supporting files No Yes — templates, scripts, examples in same directory
Auto-invocation by Claude No Yes — Claude loads skill automatically when relevant
disable-model-invocation Supported Supported — prevent Claude from auto-triggering
user-invocable: false Supported Supported — hide from / menu, only Claude can use
Nested discovery (monorepo) No Yes — auto-discovers from subdirectories

Skills are the recommended path. Commands still work but skills support more features.

Skill directory structure:

my-skill/
├── SKILL.md           # Main instructions (required)
├── template.md        # Template for Claude to fill in
├── examples/
│   └── sample.md      # Example output
└── scripts/
    └── validate.sh    # Script Claude can execute

Key Differences: Command/Skill vs Agent

Even though commands and skills are merged, agents are fundamentally different. Here’s a clear comparison:

Feature Command / Skill Agent (Sub-agent)
Invocation User calls with /command-name or Claude auto-invokes Claude delegates automatically based on description, or user asks “use the X agent”
Parameters Takes $ARGUMENTS from user input No user parameters — receives a task/prompt from Claude
Context Runs inline in main conversation (unless context: fork) Always runs in isolated context — separate context window, own system prompt
Parallel execution No — one at a time in main conversation Yes — multiple agents can run in parallel
Git isolation No Yes — isolation: worktree gives agent its own git worktree copy
Background execution No Yes — background: true or Ctrl+B to background a running agent
Persistent memory No Yes — memory: user|project|local for cross-session learning
Permission mode Inherits from session Own permissionMode
Turn limit No limit maxTurns — cap how many turns before agent stops
Tool restrictions allowed-tools / disallowed-tools tools / disallowedTools
Preload skills N/A skills field
MCP servers Inherits from session mcpServers — can specify which MCP servers agent has access to
Visual indicator None color field — colored background in terminal UI
Can spawn sub-agents No (unless context: fork) No — sub-agents cannot spawn other sub-agents
Resume No Yes — can resume with full previous context preserved

When to use which?

Use Command/Skill when you want reusable prompts or workflows that run in the main conversation context. Good for: code generation templates, review checklists, deploy scripts, quick actions.

Use Agent when the task needs isolation, parallelism, or independent execution. Good for: code review (read-only), testing (verbose output), research (parallel exploration), specialized workers in team orchestration.

Rule of thumb: If you’d invoke it yourself with /name, make it a command/skill. If Claude should delegate to it automatically as a worker, make it an agent.

4. Team Orchestration (meta-prompt + agents)

  • What: A meta-prompt that creates a plan, then coordinates multiple agents to build it
  • Where: The meta-prompt is a command (.claude/commands/plan_w_team.md), agents are in .claude/agents/team/
  • How it works:
    1. User runs /plan_w_team [requirements]
    2. Command generates a spec file in specs/ directory
    3. Spec includes team orchestration section (which agents, what tasks)
    4. Stop hooks validate the output file exists and has required sections
    5. Agents (builder, validator) execute the plan using TaskCreate/TaskUpdate

Concrete example — plan_w_team.md flow

User: /plan_w_team create a REST API for user management

→ Meta-prompt analyzes requirements
→ Creates specs/user-management-api.md with:
    - Task Description
    - Objective
    - Relevant Files
    - Step by Step Tasks (using TaskCreate)
    - Acceptance Criteria
    - Team Orchestration (builder + validator assignments)
→ Stop hooks validate the spec file:
    - validate_new_file.py — checks file was created in specs/
    - validate_file_contains.py — checks all required sections exist

Required files for plan_w_team.md:

.claude/
├── commands/
│   └── plan_w_team.md          # The meta-prompt command
├── agents/team/
│   ├── builder.md              # Executes tasks (writes code)
│   └── validator.md            # Verifies work (read-only)
├── hooks/validators/
│   ├── validate_new_file.py    # Stop hook: checks file created
│   └── validate_file_contains.py # Stop hook: checks required sections
specs/                           # Output directory for generated plans

All Available Tool Names

For use in allowed-tools, disallowed-tools, or disallowedTools:

Tool Purpose
Task Spawn subagents
TaskOutput Read subagent output
Bash Execute shell commands
Glob Find files by pattern
Grep Search file contents
Read Read file contents
Edit Replace text in files
Write Create/overwrite files
NotebookEdit Edit Jupyter notebooks
WebFetch Fetch web content
WebSearch Search the internet
AskUserQuestion Prompt user for input
EnterPlanMode Switch to planning mode
ExitPlanMode Exit planning mode
Skill Invoke skills

MCP Tools: Pattern mcp__<server>__<tool> (e.g., mcp__memory__create_entities)

Tool Restriction Syntax:

  • Task(agent_name) — allow only specific subagent types
  • Bash(pattern *) — pattern-based restrictions
  • Skill(skill-name) — restrict individual skills

All Hook Events Reference

Event When Matcher Can Block
SessionStart Session begins/resumes startup, resume, clear, compact No
UserPromptSubmit User submits prompt No Yes
PreToolUse Before tool executes Tool name regex Yes
PermissionRequest Permission dialog appears Tool name regex Yes
PostToolUse After tool succeeds Tool name regex Feedback only
PostToolUseFailure After tool fails Tool name regex No
Notification Notification sent permission_prompt, idle_prompt No
SubagentStart Subagent spawns Agent type name No
SubagentStop Subagent finishes Agent type name Yes
Stop Claude finishes responding No Yes
TeammateIdle Teammate about to go idle No Yes
TaskCompleted Task marked completed No Yes
ConfigChange Config file changes user_settings, project_settings Yes
PreCompact Before context compaction manual, auto No
SessionEnd Session terminates clear, logout No

Hook Handler Types

# Command hook — runs a shell command
- type: command
  command: "path/to/script.sh"
  timeout: 600          # seconds
  async: false          # run in background
  once: true            # run once per session (skills only)

# Prompt hook — sends a prompt to a model
- type: prompt
  prompt: "Your prompt... $ARGUMENTS"
  model: haiku          # default: fast model
  timeout: 30

# Agent hook — runs a full agent
- type: agent
  prompt: "Your prompt... $ARGUMENTS"
  model: haiku
  timeout: 60

Key Concept: once vs Self-Validating Hooks

once: true = run the hook one time only, then skip it for the rest of the session.

once: false (or omitted) = run the hook every time the matcher triggers.

Self-validating pattern (blocks Claude until validation passes):

  • Use a Stop hook (not PostToolUse) with once: false or omit once
  • If the validator script returns exit code 1 (fail), Claude is blocked from stopping and must keep working
  • Claude will retry until the validator passes (exit code 0)
# ONE-TIME CHECK — runs once after first Edit/Write, then never again
PostToolUse:
  - matcher: "Edit|Write"
    hooks:
      - type: command
        command: "uv run validator.py"
        once: true                        # only once

# SELF-VALIDATING — blocks Claude from finishing until it passes
Stop:
  - hooks:
      - type: command
        command: "uv run validator.py"    # exit 1 = blocked, exit 0 = pass
                                          # no "once" = runs every time

This is how plan_w_team.md ensures the spec file is actually created with all required sections — the Stop hook keeps blocking until it’s right.

What is uv run?

uv is a fast Python package manager/runner by Astral (same team behind ruff linter). Install with brew install uv.

uv run script.py runs a Python script and automatically handles dependencies declared in the script header:

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["requests"]
# ///

This is why hook validator scripts use uv run — no need to manually pip install anything. The script declares what it needs and uv handles it.

Example from plan_w_team.md:

command: >-
  uv run $CLAUDE_PROJECT_DIR/.claude/hooks/validators/validate_new_file.py
  --directory specs
  --extension .md

$CLAUDE_PROJECT_DIR is an environment variable that points to your project root, so the hook script path works regardless of the current working directory.

VS Code Snippet Templates

Installation

1. Snippet file location (global — works in all projects):

  • VS Code: ~/Library/Application Support/Code/User/snippets/markdown.json
  • Cursor: ~/Library/Application Support/Cursor/User/snippets/markdown.json

2. Required VS Code/Cursor settings (enable snippets in Markdown files):

Add to User Settings JSON (Cmd+Shift+P → “Open User Settings JSON”):

{
  "[markdown]": {
    "editor.quickSuggestions": {
      "other": "on",
      "comments": "off",
      "strings": "off"
    },
    "editor.snippetSuggestions": "top"
  }
}

Without this setting, typing snippet prefixes in .md files won’t trigger autocomplete.

Available Snippets

Prefix Type Description
agpc Command .claude/commands/*.md — ALL command front matter fields with all hook types. Delete what you don’t need.
agpa Agent .claude/agents/**/*.md — ALL agent front matter fields including permissionMode, maxTurns, isolation, all hook types. Delete what you don’t need.
agpn Body only Just markdown sections (Purpose, Variables, Instructions, Workflow, Report). No front matter.

How to Use

  1. Create a new .md file in the correct location (e.g., .claude/commands/my-command.md)
  2. Type the snippet prefix (e.g., agpc)
  3. Select from autocomplete (or press Ctrl+Space to trigger it)
  4. Tab through placeholders to fill in values — some have dropdown choices (e.g., model: opus|sonnet|haiku)
  5. Delete any fields you don’t need — snippets include everything so you can pick and choose

Summary

Simple (use snippets)          Complex (use meta-prompts)
├── Commands/Skills (agpc)     └── Orchestration (/plan_w_team)
└── Agents (agpa)                  ↓
                               Meta-prompts ARE commands
                               that generate other prompts

Commands = Skills (merged in v2.1.3). Use .claude/skills/ when you need supporting files or auto-invocation. Use .claude/commands/ for simple single-file prompts. Both work identically.

The foundation: everything is built on commands/skills. Simple things get a snippet template. Complex things get a meta-prompt command that generates the structure for you.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top