Skip to content

Commit 52e8b2f

Browse files
Merge pull request #1049 from microsoft/feature/TAS27
feat: Modularity and Infra standardization code changes
2 parents 212b904 + 233f3b5 commit 52e8b2f

367 files changed

Lines changed: 179928 additions & 77655 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.coveragerc

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
agent: speckit.contentpack
3+
---

.github/requirements.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
fastapi==0.137.1
2+
uvicorn==0.49.0
3+
autogen-agentchat==0.7.5
4+
azure-cosmos==4.16.1
5+
azure-monitor-opentelemetry==1.8.8
6+
azure-monitor-events-extension==0.1.0
7+
azure-identity==1.25.3
8+
python-dotenv==1.2.2
9+
python-multipart==0.0.32
10+
opentelemetry-api==1.40.0
11+
opentelemetry-sdk==1.40.0
12+
opentelemetry-exporter-otlp-proto-grpc==1.40.0
13+
opentelemetry-instrumentation-fastapi==0.61b0
14+
opentelemetry-instrumentation-openai==0.61.0
15+
opentelemetry-exporter-otlp-proto-http==1.40.0
16+
17+
semantic-kernel[azure]==1.32.2
18+
azure-ai-projects==1.0.0b11
19+
openai==1.84.0
20+
azure-ai-inference==1.0.0b9
21+
azure-search-documents==12.1.0b1
22+
azure-ai-evaluation==1.11.0
23+
24+
# Date and internationalization
25+
babel==2.18.0
26+
27+
# Testing tools
28+
pytest==8.4.2 # Compatible version for pytest-asyncio
29+
pytest-asyncio==0.24.0
30+
pytest-cov==5.0.0

.github/workflows/deploy-v2.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111
- completed
1212
branches:
1313
- main
14-
- dev-v4
14+
- dev
1515
- hotfix
1616
workflow_dispatch:
1717
inputs:

.github/workflows/deploy-waf.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ jobs:
4545
GPT41_MINI_MIN_CAPACITY: ${{ env.GPT41_MINI_MIN_CAPACITY }}
4646
AZURE_REGIONS: ${{ vars.AZURE_REGIONS }}
4747
run: |
48-
chmod +x infra/scripts/checkquota.sh
49-
if ! infra/scripts/checkquota.sh; then
48+
chmod +x infra/scripts/pre-provision/checkquota.sh
49+
if ! infra/scripts/pre-provision/checkquota.sh; then
5050
# If quota check fails due to insufficient quota, set the flag
51-
if grep -q "No region with sufficient quota found" infra/scripts/checkquota.sh; then
51+
if grep -q "No region with sufficient quota found" infra/scripts/pre-provision/checkquota.sh; then
5252
echo "QUOTA_FAILED=true" >> $GITHUB_ENV
5353
fi
5454
exit 1 # Fail the pipeline if any other failure occurs

0 commit comments

Comments
 (0)