|
| 1 | +--- |
| 2 | +description: Create a new content pack (agent team + data + knowledge base) using the reference template and step-by-step guide. |
| 3 | +--- |
| 4 | + |
| 5 | +# Content Packs |
| 6 | + |
| 7 | +Optional, drop-in extensions to the Multi-Agent Custom Automation Engine. A pack |
| 8 | +ships everything needed to add a domain-specific agent team **without touching |
| 9 | +core code**. |
| 10 | + |
| 11 | +The core solution works fine when the `content_packs/` folder is empty or absent. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Folder Structure |
| 16 | + |
| 17 | +``` |
| 18 | +content_packs/ |
| 19 | +└── <pack_name>/ |
| 20 | + ├── pack.json # optional — declares search indexes + blob uploads |
| 21 | + ├── agent_teams/ |
| 22 | + │ └── *.json # required — one or more team config files (any name) |
| 23 | + ├── datasets/ # optional — source data for grounding |
| 24 | + │ ├── data/*.csv |
| 25 | + │ └── docs/*.pdf |
| 26 | + └── scripts/ # optional — pack-local utilities |
| 27 | +``` |
| 28 | + |
| 29 | +- `<pack_name>` should be lowercase snake_case (e.g. `pet_food`, `legal_review`). |
| 30 | +- JSON files inside `agent_teams/` can be named anything — the upload script |
| 31 | + globs all `*.json` files in that directory. |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## Designing Your Agent Team |
| 36 | + |
| 37 | +Every pack needs at least one team config JSON in `agent_teams/`. The agents you |
| 38 | +create should be tailored to your domain — there is no fixed pattern. Consider: |
| 39 | + |
| 40 | +**What does the user need?** Design agents around the tasks your users will |
| 41 | +perform, not around a template. Ask yourself: |
| 42 | + |
| 43 | +| Question | Design decision | |
| 44 | +|----------|----------------| |
| 45 | +| Does the team need to look up data? | Add a **ResearchAgent** with `use_knowledge_base: true` | |
| 46 | +| Does it need to generate images? | Add an agent with `use_toolbox: true` and the appropriate `toolbox_filter` | |
| 47 | +| Should it ask the user clarifying questions? | Set `user_responses: true` on the relevant agent | |
| 48 | +| Are there multiple distinct tasks? | Add specialist agents and a **TriageAgent** to route between them | |
| 49 | +| Is it a simple Q&A over data? | A single agent with KB access may be enough — no triage needed | |
| 50 | + |
| 51 | +**Examples from this repo:** |
| 52 | + |
| 53 | +| Pack | Agents | Why | |
| 54 | +|------|--------|-----| |
| 55 | +| `content_gen` | Triage → Planning → Research → TextContent → ImageContent → Compliance | Complex creative workflow with multiple output types | |
| 56 | +| `contract_compliance` | Triage → Research → Analysis | Document review with KB lookup | |
| 57 | +| `hr_onboarding` | Single team (no KB) | Workflow-only, no data grounding needed | |
| 58 | + |
| 59 | +**Key rules:** |
| 60 | +- Every agent needs a unique `input_key` (used for routing between agents). |
| 61 | +- The `team_id` must be a valid UUID using only hex characters (0-9, a-f). |
| 62 | + Use the pattern `00000000-0000-0000-0000-00000000NNNN` where NNNN is unique. |
| 63 | +- At least one `starting_tasks` entry is required (the example prompt shown in the UI). |
| 64 | + |
| 65 | +### Required Fields (validation will reject uploads without these) |
| 66 | + |
| 67 | +**Team-level:** |
| 68 | +```jsonc |
| 69 | +{ |
| 70 | + "id": "1", |
| 71 | + "team_id": "00000000-0000-0000-0000-000000000008", |
| 72 | + "name": "Your Team Name", |
| 73 | + "status": "visible", // REQUIRED — team won't appear in UI without this |
| 74 | + "deployment_name": "gpt-4.1-mini", |
| 75 | + ... |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +**Each agent must include `type`:** |
| 80 | +```jsonc |
| 81 | +{ |
| 82 | + "input_key": "my_agent", |
| 83 | + "type": "", // REQUIRED — empty string is fine, but field must exist |
| 84 | + "name": "MyAgent", |
| 85 | + ... |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +**Each starting task must include `created`, `creator`, `logo`:** |
| 90 | +```jsonc |
| 91 | +"starting_tasks": [ |
| 92 | + { |
| 93 | + "id": "task-1", |
| 94 | + "name": "Example Task", |
| 95 | + "prompt": "A sample prompt users can click to start", |
| 96 | + "created": "", // REQUIRED — empty string is fine |
| 97 | + "creator": "", // REQUIRED — empty string is fine |
| 98 | + "logo": "" // REQUIRED — empty string is fine |
| 99 | + } |
| 100 | +] |
| 101 | +``` |
| 102 | + |
| 103 | +> Missing any of these fields results in a 400 error during upload. |
| 104 | +> Use an existing pack (e.g. `hr_onboarding/agent_teams/hr.json`) as a |
| 105 | +> reference for the full required schema. |
| 106 | +
|
| 107 | +--- |
| 108 | + |
| 109 | +## Data & Knowledge Bases |
| 110 | + |
| 111 | +If your agents need to search domain-specific data, you need three things wired together: |
| 112 | + |
| 113 | +``` |
| 114 | +CSV/PDF ──► AI Search Index ──► Knowledge Base (MCP) ──► Agent |
| 115 | + (pack.json) (seed_knowledge_bases.py) (agent_teams/*.json) |
| 116 | +``` |
| 117 | + |
| 118 | +### Step 1 — Add your data |
| 119 | + |
| 120 | +Put source files in `datasets/data/`. Supported formats: |
| 121 | + |
| 122 | +| Format | How it's indexed | |
| 123 | +|--------|-----------------| |
| 124 | +| CSV | One document per row. Columns become searchable fields. | |
| 125 | +| PDF/DOCX | Uploaded to blob; use `blob_indexes` in `pack.json` for document-crack indexing. | |
| 126 | + |
| 127 | +### Step 2 — Create `pack.json` |
| 128 | + |
| 129 | +```jsonc |
| 130 | +{ |
| 131 | + "name": "your_pack", |
| 132 | + "description": "What this pack does", |
| 133 | + "search_indexes": [ |
| 134 | + { |
| 135 | + "index_name": "your-pack-data-index", |
| 136 | + "csv_path": "datasets/data/your_data.csv", |
| 137 | + "key_field": "id", |
| 138 | + "title_field": "product_name" |
| 139 | + } |
| 140 | + ], |
| 141 | + "blob_uploads": [ |
| 142 | + { |
| 143 | + "container": "your-pack-dataset", |
| 144 | + "source": "datasets/data", |
| 145 | + "pattern": "*.csv" |
| 146 | + } |
| 147 | + ] |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +The `index_name` must be globally unique on your search service and will be |
| 152 | +referenced in the KB registration. |
| 153 | + |
| 154 | +### Step 3 — Register the Knowledge Base |
| 155 | + |
| 156 | +Add an entry to `infra/scripts/post-provision/seed_knowledge_bases.py` in the `KNOWLEDGE_BASES` |
| 157 | +dict. Place it before the `# ── Example Pack ──` comment block: |
| 158 | + |
| 159 | +```python |
| 160 | + # ── Your Pack ── |
| 161 | + "your-pack-data-kb": { |
| 162 | + "description": "What this KB provides", |
| 163 | + "model": { |
| 164 | + "kind": "azureOpenAI", |
| 165 | + "azureOpenAIParameters": { |
| 166 | + "resourceUri": AI_SERVICES_ENDPOINT, |
| 167 | + "deploymentId": "gpt-4.1-mini", |
| 168 | + "modelName": "gpt-4.1-mini", |
| 169 | + }, |
| 170 | + }, |
| 171 | + "sources": [ |
| 172 | + { |
| 173 | + "name": "your-pack-data-ks", |
| 174 | + "description": "What the source data contains", |
| 175 | + "index_name": "your-pack-data-index", # Must match pack.json |
| 176 | + "searchable_fields": ["content", "title"], |
| 177 | + }, |
| 178 | + ], |
| 179 | + }, |
| 180 | +``` |
| 181 | + |
| 182 | +**Naming convention (must be consistent across files):** |
| 183 | + |
| 184 | +| Item | Pattern | Example | |
| 185 | +|------|---------|---------| |
| 186 | +| KB name (dict key) | `<pack>-<purpose>-kb` | `pet-food-catalog-kb` | |
| 187 | +| Knowledge Source name | `<pack>-<purpose>-ks` | `pet-food-catalog-ks` | |
| 188 | +| Search index name | `<pack>-<purpose>-index` | `pet-food-catalog-index` | |
| 189 | + |
| 190 | +### Step 4 — Connect agents to the KB |
| 191 | + |
| 192 | +In your team config JSON, set these fields on the agent that needs search: |
| 193 | + |
| 194 | +```jsonc |
| 195 | +"use_knowledge_base": true, |
| 196 | +"knowledge_base_name": "your-pack-data-kb" // Must match the key in seed_knowledge_bases.py |
| 197 | +``` |
| 198 | + |
| 199 | +The agent's `system_message` should instruct it to **always use the search tool** |
| 200 | +and **never hallucinate data**. |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +## Registering in the Deployment Script |
| 205 | + |
| 206 | +Edit `infra/scripts/post-provision/Selecting-Team-Config-And-Data.ps1`. Search for `NEW CONTENT PACK` |
| 207 | +— each insertion point has a comment template. There are **4 things** to do: |
| 208 | + |
| 209 | +| # | What | Where | |
| 210 | +|---|------|-------| |
| 211 | +| 1 | Add `Write-Host "N. Your Pack Name"` | Menu display section | |
| 212 | +| 2 | Add `elseif ($useCaseSelection -eq "N") { ... }` | Selection handler | |
| 213 | +| 3 | Add deployment block (team config upload + `Deploy-ContentPack`) | After Content Gen block | |
| 214 | +| 4 | Add `-or $useCaseSelection -eq "N"` to network/KB/success conditions | Only if pack has data | |
| 215 | + |
| 216 | +After adding your entry, update `$allOption` to `N + 1` so "All" is always last. |
| 217 | + |
| 218 | +--- |
| 219 | + |
| 220 | +## Agent Tool Options Reference |
| 221 | + |
| 222 | +| Field | Type | Purpose | |
| 223 | +|-------|------|---------| |
| 224 | +| `use_knowledge_base` | bool | Connects a Foundry IQ KB as an MCP search tool | |
| 225 | +| `knowledge_base_name` | string | Name of the KB (must exist in `seed_knowledge_bases.py`) | |
| 226 | +| `use_file_search` | bool | Attaches an Azure AI vector store for file-level RAG | |
| 227 | +| `vector_store_name` | string | Name of the vector store in Foundry | |
| 228 | +| `use_toolbox` | bool | Connects MCP toolbox tools (e.g., `generate_marketing_image`) | |
| 229 | +| `toolbox_filter` | string | Tag filter for which toolbox tools are available | |
| 230 | +| `coding_tools` | bool | Enables code interpreter sandbox | |
| 231 | +| `user_responses` | bool | Allows the agent to pause and ask the user a question | |
| 232 | + |
| 233 | +> **`user_responses` guidance:** Default to `false` unless the user explicitly |
| 234 | +> asks for the agent to collect human feedback or ask clarifying questions. |
| 235 | +> When `false`, the agent runs autonomously without pausing for input. Only set |
| 236 | +> to `true` on agents whose design requires them to ask the user a question |
| 237 | +> mid-workflow (e.g., an intake agent gathering requirements). |
| 238 | +
|
| 239 | +--- |
| 240 | + |
| 241 | +## Deploying |
| 242 | + |
| 243 | +```bash |
| 244 | +# 1. Deploy infrastructure |
| 245 | +azd up |
| 246 | + |
| 247 | +# 2. Provision pack resources — select your pack or "All" |
| 248 | +./infra/scripts/post-provision/Selecting-Team-Config-And-Data.ps1 -ResourceGroup <rg> |
| 249 | +``` |
| 250 | + |
| 251 | +--- |
| 252 | + |
| 253 | +## Checklist |
| 254 | + |
| 255 | +- [ ] `content_packs/<pack>/agent_teams/` has at least one valid JSON team config |
| 256 | +- [ ] `team_id` is a valid hex UUID (0-9, a-f only) |
| 257 | +- [ ] `starting_tasks` has at least one example prompt |
| 258 | +- [ ] If using a KB: `pack.json` exists with matching `index_name` |
| 259 | +- [ ] If using a KB: `datasets/data/` contains the source files |
| 260 | +- [ ] If using a KB: entry added to `seed_knowledge_bases.py` with matching names |
| 261 | +- [ ] If using a KB: agent has `use_knowledge_base: true` + correct `knowledge_base_name` |
| 262 | +- [ ] Agent `system_message` tells it to search (not hallucinate) |
| 263 | +- [ ] Pack registered in `Selecting-Team-Config-And-Data.ps1` (all 4 locations) |
| 264 | +- [ ] `$allOption` updated if you added a new menu number |
| 265 | + |
| 266 | +--- |
| 267 | + |
| 268 | +## Removing a Pack |
| 269 | + |
| 270 | +Delete the pack folder. Previously uploaded team configs remain in Cosmos until |
| 271 | +deleted via `DELETE /api/v4/team_configs/{team_id}`. Search indexes and blob |
| 272 | +containers are also left in place — clean up with `az search` / `az storage`. |
| 273 | + |
0 commit comments