| 1 | --- |
| 2 | name: a0-create-agent |
| 3 | description: Create a new Agent Zero agent profile (subordinate). Covers where profiles live (user / plugin-distributed / project-scoped), the agent.yaml schema, the prompt inheritance & override model, and optional profile-specific tools and extensions. Use for any "create/add/new agent profile" request. |
| 4 | version: 1.0.0 |
| 5 | tags: ["agents", "profile", "create", "new", "subordinate"] |
| 6 | trigger_patterns: |
| 7 | - "create agent" |
| 8 | - "new agent profile" |
| 9 | - "add agent profile" |
| 10 | - "make agent profile" |
| 11 | - "agent profile template" |
| 12 | - "build agent profile" |
| 13 | --- |
| 14 | |
| 15 | # Create an Agent Zero Agent Profile |
| 16 | |
| 17 | > [!IMPORTANT] |
| 18 | > Do **not** create new profiles in `/a0/agents/` — that directory is reserved for core framework profiles (`default`, `agent0`, `developer`, `hacker`, `researcher`, `_example`). User profiles belong in `/a0/usr/agents/<profile_name>/`. |
| 19 | |
| 20 | Related skills: `/a0/skills/a0-development/SKILL.md` (broader framework guide) | `/a0/skills/a0-create-plugin/SKILL.md` (bundle a profile inside a plugin). |
| 21 | |
| 22 | Primary references: |
| 23 | - `/a0/agents/_example/` — the canonical reference profile (tool + extension + prompt overrides) |
| 24 | - `/a0/agents/default/` — the base profile every other profile inherits from |
| 25 | - `/a0/plugins/AGENTS.md` — plugin-distributed profiles + per-profile config |
| 26 | |
| 27 | --- |
| 28 | |
| 29 | ## Existing Profile Pattern |
| 30 | |
| 31 | The built-in profiles are intentionally split into two layers: |
| 32 | |
| 33 | 1. `agent.yaml` is tiny metadata for discovery and delegation: |
| 34 | - `title` |
| 35 | - `description` |
| 36 | - `context` |
| 37 | 2. The actual profile behavior usually lives in `prompts/agent.system.main.specifics.md`. |
| 38 | |
| 39 | Use the shipped profiles as calibration: |
| 40 | |
| 41 | | Profile | Pattern to copy | |
| 42 | |---|---| |
| 43 | | `agent0` | Minimal top-level assistant identity | |
| 44 | | `developer` | Rich capabilities, methodology, output requirements | |
| 45 | | `researcher` | Rich capabilities, methodology, evidence standards | |
| 46 | | `hacker` | Short, direct operational identity plus optional environment override | |
| 47 | | `_example` | Minimal demo of prompt/tool/extension override surfaces | |
| 48 | |
| 49 | For most new profiles, create `agent.yaml` plus one strong `agent.system.main.specifics.md`. Add other prompt overrides, tools, or extensions only when the blueprint explicitly needs them. |
| 50 | |
| 51 | --- |
| 52 | |
| 53 | ## Step 0: Progressive Intake |
| 54 | |
| 55 | Do not ask the user a long form. New users are easily overwhelmed. Guide them with lossy compression: ask only the next highest-value question, one or two questions per turn maximum. |
| 56 | |
| 57 | Default assumptions unless the user says otherwise: |
| 58 | |
| 59 | - Scope: user profile in `/a0/usr/agents/<name>`. |
| 60 | - Models: inherit global/project `_model_config`. |
| 61 | - Response contract: keep the standard Agent Zero JSON tool-call contract. |
| 62 | - Extras: no custom tools or lifecycle extensions. |
| 63 | - Prompt strategy: `agent.yaml` plus `prompts/agent.system.main.specifics.md`. |
| 64 | |
| 65 | Recommended interview flow: |
| 66 | |
| 67 | 1. First ask only: |
| 68 | - "What should this agent be excellent at?" |
| 69 | - Optionally: "Do you already have a name/title in mind?" |
| 70 | 2. After the purpose is clear, propose a short summary with inferred `name`, `title`, `description`, and `context`, then ask for confirmation or corrections. |
| 71 | 3. Ask about behavior only if needed: |
| 72 | - "Should it work more like a concise specialist, a rigorous researcher, a code-heavy implementer, or something else?" |
| 73 | 4. Ask about advanced options only when the user's request implies them: |
| 74 | - custom output format |
| 75 | - a profile-specific model preset |
| 76 | - custom tools |
| 77 | - lifecycle extensions |
| 78 | - plugin/project scope |
| 79 | 5. Before writing files, show the compact blueprint summary and ask for confirmation. |
| 80 | 6. Only after confirmation, produce the full AgentProfileBlueprint JSON in Step 1 and write files from it. |
| 81 | |
| 82 | Never open with all blueprint fields. Do not mention obscure paths until they matter. Hide defaults, but use them. |
| 83 | |
| 84 | If the user gives a broad idea, infer sensible defaults and mark uncertainties in `validation.open_questions` instead of stalling. |
| 85 | |
| 86 | --- |
| 87 | |
| 88 | ## Step 1: Create an AgentProfileBlueprint JSON |
| 89 | |
| 90 | Before writing files, produce exactly one valid JSON object in a fenced `json` block using this schema. This blueprint is the source of truth. Do not require a utility model or prose post-processing to extract fields. |
| 91 | |
| 92 | ```json |
| 93 | { |
| 94 | "schema": "agent_zero.agent_profile_blueprint.v1", |
| 95 | "status": "draft", |
| 96 | "profile": { |
| 97 | "scope": "user", |
| 98 | "root": "/a0/usr/agents", |
| 99 | "name": "data-analyst", |
| 100 | "title": "Data Analyst", |
| 101 | "description": "Agent specialized in data analysis, visualization, and statistical modeling.", |
| 102 | "context": "Use this agent for data analysis tasks, creating visualizations, statistical analysis, and working with datasets in Python." |
| 103 | }, |
| 104 | "behavior": { |
| 105 | "role": "You are a specialized data analysis agent.", |
| 106 | "primary_capabilities": [ |
| 107 | "Python data analysis with pandas, numpy, and scipy", |
| 108 | "Data visualization with matplotlib, seaborn, and plotly", |
| 109 | "Statistical modeling and hypothesis testing" |
| 110 | ], |
| 111 | "operating_principles": [ |
| 112 | "Inspect data before drawing conclusions", |
| 113 | "Prefer reproducible code and explicit assumptions", |
| 114 | "Explain uncertainty and limitations" |
| 115 | ], |
| 116 | "workflow": [ |
| 117 | "Clarify the question and available data", |
| 118 | "Profile and clean the dataset", |
| 119 | "Run analysis with appropriate methods", |
| 120 | "Visualize and interpret results" |
| 121 | ], |
| 122 | "output_preferences": [ |
| 123 | "Concise findings first", |
| 124 | "Tables or charts when useful", |
| 125 | "Reproducible code when analysis is performed" |
| 126 | ] |
| 127 | }, |
| 128 | "prompt_strategy": { |
| 129 | "base_pattern": "specifics_only", |
| 130 | "override_rationale": [ |
| 131 | "Use agent.system.main.specifics.md for role, expertise, and process.", |
| 132 | "Keep the inherited communication contract unchanged." |
| 133 | ], |
| 134 | "root_prompt_overrides": [ |
| 135 | { |
| 136 | "file": "agent.system.main.communication.md", |
| 137 | "reason": "Only include if the profile needs a different response JSON schema or output format." |
| 138 | } |
| 139 | ] |
| 140 | }, |
| 141 | "llm_config": { |
| 142 | "enabled": false, |
| 143 | "path": "/a0/usr/agents/data-analyst/plugins/_model_config/config.json", |
| 144 | "source": "inherit_scoped", |
| 145 | "model_preset": null, |
| 146 | "notes": [ |
| 147 | "Do not put model settings in agent.yaml.", |
| 148 | "Only create this config file if the user wants this profile to select a specific global model preset.", |
| 149 | "Scoped _model_config config stores only model_preset." |
| 150 | ] |
| 151 | }, |
| 152 | "files": [ |
| 153 | { |
| 154 | "path": "/a0/usr/agents/data-analyst/agent.yaml", |
| 155 | "kind": "yaml", |
| 156 | "content": "title: Data Analyst\ndescription: Agent specialized in data analysis, visualization, and statistical modeling.\ncontext: Use this agent for data analysis tasks, creating visualizations, statistical analysis, and working with datasets in Python.\n" |
| 157 | }, |
| 158 | { |
| 159 | "path": "/a0/usr/agents/data-analyst/prompts/agent.system.main.specifics.md", |
| 160 | "kind": "markdown", |
| 161 | "content": "## Your role\n\nYou are a specialized data analysis agent.\n\n## Expertise\n- Python data analysis with pandas, numpy, and scipy\n- Data visualization with matplotlib, seaborn, and plotly\n- Statistical modeling and hypothesis testing\n\n## Process\n1. Clarify the question and available data\n2. Profile and clean the dataset\n3. Run analysis with appropriate methods\n4. Visualize and interpret results\n" |
| 162 | } |
| 163 | ], |
| 164 | "optional_components": { |
| 165 | "extra_prompt_overrides": [], |
| 166 | "tools": [], |
| 167 | "extensions": [] |
| 168 | }, |
| 169 | "validation": { |
| 170 | "needs_user_confirmation": true, |
| 171 | "unique_name_checked": false, |
| 172 | "yaml_valid": false, |
| 173 | "open_questions": [] |
| 174 | } |
| 175 | } |
| 176 | ``` |
| 177 | |
| 178 | Rules for the blueprint: |
| 179 | |
| 180 | - Output strict JSON: no comments, no trailing commas, no markdown inside string values except the intended file content. |
| 181 | - `profile.name` must be lowercase letters, numbers, hyphens, or underscores only. |
| 182 | - `prompt_strategy.root_prompt_overrides` must list any inherited root `/prompts` files being considered or replaced and why. |
| 183 | - If a root prompt override is only a possibility, list it in `prompt_strategy` but do not add it to `files` until confirmed. |
| 184 | - `llm_config.enabled` controls whether a profile-scoped `_model_config/config.json` file is created. Keep it `false` when the preset should inherit from broader project/global settings. |
| 185 | - `files[*].content` must be the exact file content to write. |
| 186 | - Include only files that should actually be created. |
| 187 | - Set `status` to `draft` until all required choices are known; set it to `ready` only after resolving open questions. |
| 188 | - Ask the user to confirm or edit the blueprint before writing files unless they explicitly authorized immediate creation. |
| 189 | |
| 190 | --- |
| 191 | |
| 192 | ## Step 2: Required Fields |
| 193 | |
| 194 | The blueprint must contain these required profile inputs: |
| 195 | |
| 196 | | Input | Rule | Example | |
| 197 | |---|---|---| |
| 198 | | **name** (directory name) | lowercase letters, numbers, hyphens or underscores; must be unique across profile search paths | `data-analyst` | |
| 199 | | **title** | human-readable display name shown in the UI | `Data Analyst` | |
| 200 | | **description** | one-line specialization summary | `Agent specialized in data analysis, visualization, and statistical modeling.` | |
| 201 | | **context** | instructions telling the *superior* agent when to delegate to this profile | `Use this agent for data analysis tasks, creating visualizations, statistical analysis, and working with datasets in Python.` | |
| 202 | |
| 203 | > [!NOTE] |
| 204 | > `agent.yaml` has **only** these three content fields (`title`, `description`, `context`). Do not add model, temperature, or `allowed_tools` fields to `agent.yaml`. A profile-specific preset selection lives in a companion `_model_config` plugin config file, and tool availability is controlled by plugin activation. |
| 205 | |
| 206 | --- |
| 207 | |
| 208 | ## Step 3: Write Files from the Blueprint |
| 209 | |
| 210 | After the user confirms the blueprint, create exactly the paths listed in `files`. |
| 211 | |
| 212 | ``` |
| 213 | <PROFILE_ROOT>/<name>/ |
| 214 | ├── agent.yaml # Required |
| 215 | ├── prompts/ # Optional — prompt overrides |
| 216 | ├── tools/ # Optional — profile-specific tools |
| 217 | └── extensions/ # Optional — profile-specific extensions |
| 218 | ``` |
| 219 | |
| 220 | `agent.yaml`: |
| 221 | |
| 222 | ```yaml |
| 223 | title: Data Analyst |
| 224 | description: Agent specialized in data analysis, visualization, and statistical modeling. |
| 225 | context: Use this agent for data analysis tasks, creating visualizations, statistical |
| 226 | analysis, and working with datasets in Python. |
| 227 | ``` |
| 228 | |
| 229 | A profile with only `agent.yaml` is valid — it inherits everything from `default/`. Add the sections below only when you need to change something. |
| 230 | |
| 231 | --- |
| 232 | |
| 233 | ## Step 4: Optional profile-specific model preset |
| 234 | |
| 235 | Agent Zero does **not** read model settings from `agent.yaml`. The `_model_config` plugin is always enabled and supports per-agent-profile preset selection. If the user wants this profile to use a specific existing global preset, create a companion config file: |
| 236 | |
| 237 | | Profile scope | Model config path | |
| 238 | |---|---| |
| 239 | | User profile | `/a0/usr/agents/<profile>/plugins/_model_config/config.json` | |
| 240 | | Plugin-distributed profile | `/a0/usr/plugins/<plugin>/agents/<profile>/plugins/_model_config/config.json` | |
| 241 | | Project-scoped profile | `<project>/.a0proj/agents/<profile>/plugins/_model_config/config.json` | |
| 242 | |
| 243 | Scoped `_model_config/config.json` files contain only the selected global preset name. Preset definitions are managed centrally in Model Configuration and are not copied into profiles. |
| 244 | |
| 245 | Profile-scoped selection: |
| 246 | |
| 247 | ```json |
| 248 | { |
| 249 | "model_preset": "Research" |
| 250 | } |
| 251 | ``` |
| 252 | |
| 253 | Rules: |
| 254 | |
| 255 | - Ask whether the profile should inherit its scoped preset or select an existing global preset. |
| 256 | - Verify the preset exists before adding the file. If new model choices are needed, create a global preset through Model Configuration first. |
| 257 | - Do not store API keys or model dictionaries in this file; API keys and preset definitions are managed centrally. |
| 258 | - Add this file to `files` only when `llm_config.enabled` is `true`. |
| 259 | |
| 260 | --- |
| 261 | |
| 262 | ## Step 5: Override prompts (the most common customization) |
| 263 | |
| 264 | Profiles inherit all prompts from `/a0/prompts/` and from `/a0/agents/default/`. To change behavior, drop a file with the **same filename** into `<PROFILE_ROOT>/<name>/prompts/`. The loader searches profile-specific prompts first and falls back to the defaults. |
| 265 | |
| 266 | ### The canonical override: `agent.system.main.specifics.md` |
| 267 | |
| 268 | This is the designated extension slot for profile-specific role, identity, and behavior instructions. The file ships **empty** in both `/a0/prompts/agent.system.main.specifics.md` and `/a0/agents/default/prompts/agent.system.main.specifics.md` precisely so profiles can fill it in without fighting the base prompt. It is included from `agent.system.main.md` right after `agent.system.main.role.md`, so whatever you put here layers on top of the inherited role. |
| 269 | |
| 270 | **Every shipped profile in `/a0/agents/` overrides this file** — a good sanity check that this is the right place for your specialization. Look at the existing profiles for concrete shape: |
| 271 | |
| 272 | | Profile | What its `agent.system.main.specifics.md` does | |
| 273 | |---|---| |
| 274 | | `/a0/agents/agent0/prompts/agent.system.main.specifics.md` | Establishes the top-level user-facing agent's behavior | |
| 275 | | `/a0/agents/developer/prompts/agent.system.main.specifics.md` | Full "Master Developer" role + process spec (most elaborate example) | |
| 276 | | `/a0/agents/hacker/prompts/agent.system.main.specifics.md` | Concise red/blue team pentester identity | |
| 277 | | `/a0/agents/researcher/prompts/agent.system.main.specifics.md` | Research methodology and deliverable expectations | |
| 278 | | `/a0/agents/_example/prompts/agent.system.main.specifics.md` | Minimal demo override (fictional "Agent Zero" persona) | |
| 279 | |
| 280 | Start by copying whichever existing profile's `specifics.md` is closest to your target, then rewrite. |
| 281 | |
| 282 | Example `agent.system.main.specifics.md` for a data analyst: |
| 283 | |
| 284 | ```markdown |
| 285 | ## Your role |
| 286 | |
| 287 | You are a specialized data analysis agent. |
| 288 | Your expertise includes: |
| 289 | - Python data analysis (pandas, numpy, scipy) |
| 290 | - Data visualization (matplotlib, seaborn, plotly) |
| 291 | - Statistical modeling and hypothesis testing |
| 292 | - SQL queries and database analysis |
| 293 | - Data cleaning and preprocessing |
| 294 | |
| 295 | ## Process |
| 296 | 1. Understand the data and the question |
| 297 | 2. Choose appropriate tools and methods |
| 298 | 3. Execute analysis with `code_execution_tool` |
| 299 | 4. Visualize results when applicable |
| 300 | 5. Provide clear interpretation of findings |
| 301 | ``` |
| 302 | |
| 303 | ### High-value inherited prompt levers |
| 304 | |
| 305 | The root `/a0/prompts` directory contains powerful defaults. A profile can override any of these by placing a file with the same name in `<PROFILE_ROOT>/<name>/prompts/`. Use this when the requested profile needs a different protocol, not just a different specialty. |
| 306 | |
| 307 | | File | Override when the user wants... | |
| 308 | |---|---| |
| 309 | | `agent.system.main.communication.md` | A different response contract, such as no `thoughts` array, a different JSON schema, plain Markdown answers, or a domain-specific output envelope. This is the main lever for output format changes. | |
| 310 | | `agent.system.main.solving.md` | A different problem-solving loop, delegation policy, verification standard, or autonomy level. | |
| 311 | | `agent.system.main.tips.md` | Different file-handling, skill-use, memory, or operational best-practice defaults. | |
| 312 | | `agent.system.main.environment.md` | A different runtime/environment description than the default Kali/Docker Agent Zero environment. | |
| 313 | | `agent.system.main.role.md` | A fundamentally different base identity. Rare; prefer `specifics.md` unless replacing the base role is intentional. | |
| 314 | | `agent.system.tool.response.md` | Different final-response tool instructions, such as stricter final formatting or use of includes for long output. | |
| 315 | | `fw.user_message.md` / `fw.ai_response.md` | Different framework message wrapping. Advanced and fragile; override only with a clear reason. | |
| 316 | |
| 317 | When a blueprint includes any of these, add an entry to `prompt_strategy.root_prompt_overrides` and include the exact override file in `files`. |
| 318 | |
| 319 | ### Secondary overrides (use only when needed) |
| 320 | |
| 321 | | File | When to override | Shipped example | |
| 322 | |---|---|---| |
| 323 | | `agent.system.main.role.md` | Replace the base role framing wholesale (rare — most profiles layer via `specifics.md` instead) | `/a0/agents/agent0/prompts/agent.system.main.role.md` | |
| 324 | | `agent.system.main.communication.md` | Change reply format / communication style | `/a0/agents/developer/prompts/agent.system.main.communication.md`, `/a0/agents/researcher/prompts/...` | |
| 325 | | `agent.system.main.environment.md` | Describe a non-default runtime environment | `/a0/agents/hacker/prompts/agent.system.main.environment.md` (Kali/Docker) | |
| 326 | | `agent.system.tool.<name>.md` | Document a profile-specific tool (see Step 6) | `/a0/agents/_example/prompts/agent.system.tool.example_tool.md` | |
| 327 | |
| 328 | > [!TIP] |
| 329 | > Only override what you actually need to change. Copying unchanged prompt files creates silent drift when the framework updates the originals — `specifics.md` is safe to own because its default is empty by design. |
| 330 | |
| 331 | --- |
| 332 | |
| 333 | ## Step 6 (optional): Profile-specific tools |
| 334 | |
| 335 | Drop a Python tool class in `<PROFILE_ROOT>/<name>/tools/<tool_name>.py`: |
| 336 | |
| 337 | ```python |
| 338 | from helpers.tool import Tool, Response |
| 339 | |
| 340 | class ExampleTool(Tool): |
| 341 | async def execute(self, **kwargs): |
| 342 | test_input = kwargs.get("test_input", "") |
| 343 | return Response( |
| 344 | message=f"Example tool executed with test_input: {test_input}", |
| 345 | break_loop=False, |
| 346 | ) |
| 347 | ``` |
| 348 | |
| 349 | Two important rules: |
| 350 | |
| 351 | 1. To make the tool visible in the system prompt, add `prompts/agent.system.tool.<tool_name>.md` describing its usage and JSON call schema. The prompt loader auto-includes every file matching `agent.system.tool.*.md`. |
| 352 | 2. Placing a file with the same name as a core tool (e.g. `tools/response.py`) **replaces** the core tool for this profile only. See `/a0/agents/_example/tools/response.py` for a redefinition example. |
| 353 | |
| 354 | --- |
| 355 | |
| 356 | ## Step 7 (optional): Profile-specific extensions |
| 357 | |
| 358 | Lifecycle hooks go in `<PROFILE_ROOT>/<name>/extensions/<hook_point>/_NN_<name>.py`. The `_NN_` prefix controls execution order. |
| 359 | |
| 360 | Example — rename the agent at init (`/a0/agents/_example/extensions/agent_init/_10_example_extension.py`): |
| 361 | |
| 362 | ```python |
| 363 | from helpers.extension import Extension |
| 364 | |
| 365 | class ExampleExtension(Extension): |
| 366 | async def execute(self, **kwargs): |
| 367 | self.agent.agent_name = "SuperAgent" + str(self.agent.number) |
| 368 | ``` |
| 369 | |
| 370 | Available hook points mirror the framework's own `/a0/extensions/python/<point>/` directories — see `a0-development/SKILL.md` for the full list. |
| 371 | |
| 372 | --- |
| 373 | |
| 374 | ## Step 8: Test the new profile |
| 375 | |
| 376 | 1. The profile is picked up on next agent initialization — no restart of individual conversations needed, but a fresh agent/subordinate spawn is required. |
| 377 | 2. From the superior agent, delegate to it via `call_subordinate` using the profile's **directory name** (not the title). |
| 378 | 3. Verify: |
| 379 | - Title appears correctly in the UI agent selector. |
| 380 | - Role override (if any) takes effect in the new agent's system prompt. |
| 381 | - Profile-specific tools are callable and their prompt files are included. |
| 382 | |
| 383 | If the profile does not appear, check: |
| 384 | - Directory name matches the `^[a-z0-9_-]+$` pattern and is unique. |
| 385 | - `agent.yaml` parses as valid YAML. |
| 386 | - It is placed in one of the recognized search paths (see Step 0). |
| 387 | |
| 388 | --- |
| 389 | |
| 390 | ## Reference: Complete `_example` profile layout |
| 391 | |
| 392 | ``` |
| 393 | /a0/agents/_example/ |
| 394 | ├── agent.yaml |
| 395 | ├── prompts/ |
| 396 | │ ├── agent.system.main.specifics.md # role override |
| 397 | │ └── agent.system.tool.example_tool.md # tool usage prompt |
| 398 | ├── tools/ |
| 399 | │ ├── example_tool.py # new tool |
| 400 | │ └── response.py # redefines core response tool |
| 401 | └── extensions/ |
| 402 | └── agent_init/ |
| 403 | └── _10_example_extension.py # init-time hook |
| 404 | ``` |
| 405 | |
| 406 | Copy this shape when in doubt — it demonstrates every customization surface a profile supports. |
| 407 | |
| 408 | --- |
| 409 | |
| 410 | ## Quick checklist |
| 411 | |
| 412 | - [ ] Confirmed profile scope (user / plugin / project) |
| 413 | - [ ] Produced and confirmed `agent_zero.agent_profile_blueprint.v1` JSON |
| 414 | - [ ] Confirmed whether the model preset inherits or needs a profile-specific `_model_config/config.json` selection |
| 415 | - [ ] Directory name is unique and matches allowed characters |
| 416 | - [ ] `agent.yaml` contains exactly `title`, `description`, `context` |
| 417 | - [ ] Prompt overrides only include files that actually change behavior |
| 418 | - [ ] Any new tool has a matching `agent.system.tool.<name>.md` |
| 419 | - [ ] Profile tested via `call_subordinate` in a fresh conversation |