|
| 1 | +--- |
| 2 | +plugin: add-to-gallery |
| 3 | +--- |
| 4 | + |
| 5 | +# Creating SharePoint Agents (.agent Files) with PowerShell |
| 6 | + |
| 7 | +## Summary |
| 8 | + |
| 9 | +I have written a script to automate the creation of .agent files which you can then add to your sites & libraries. In the script you can then specify the details for the copilot i.e. name, welcome message, starter prompts & sources for the agent i.e. specific files, folders, libraries or sites that the agent is then grounded on. The script uses search to find the site ids, web ids and unique Ids of documents. |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +**Minimum Steps To Success** |
| 15 | + |
| 16 | +* Enter a URL of a SharePoint site you have access to. |
| 17 | +* Run the script (you will be asked for the following:) |
| 18 | + * Name of the SharePoint Agent |
| 19 | + * Description of the Agent |
| 20 | + * Custom welcome message for the Agent |
| 21 | + * Instructions for the Agent |
| 22 | + * Enter at least one Starter Prompt i.e "How can you help me?" |
| 23 | + * Enter at least one SharePoint source (File, Folder, Library or Site) |
| 24 | +* Add created <Agent Name>.agent file to /SiteAssets/Copilots folder. |
| 25 | + |
| 26 | +Further details on my [blog article](https://www.leonarmston.com/2025/01/creating-sharepoint-agents-with-powershell/) (External Site) |
| 27 | + |
| 28 | +### Prerequisites |
| 29 | + |
| 30 | +Account that runs the script needs access to all of the locations where the files, folders, libraries or sites to be used in the agent are located. |
| 31 | + |
| 32 | +# [PnP PowerShell](#tab/pnpps) |
| 33 | + |
| 34 | +```powershell |
| 35 | +$url = "https://contoso.sharepoint.com/sites/Syntex" |
| 36 | +
|
| 37 | +
|
| 38 | +Connect-PnPOnline -Url $url -Interactive |
| 39 | +
|
| 40 | +# Function to prompt user for conversation starters |
| 41 | +function Get-ConversationStarters { |
| 42 | + $conversationStarters = @() |
| 43 | + while ($true) { |
| 44 | + $text = Read-Host "Enter a starter prompt (or press Enter to finish)" |
| 45 | + if ($text -eq "" -and $conversationStarters.Count -eq 0) { |
| 46 | + Write-Host "You must enter at least one starter prompt." |
| 47 | + } elseif ($text -eq "") { |
| 48 | + break |
| 49 | + } else { |
| 50 | + $conversationStarters += @{ text = $text } |
| 51 | + } |
| 52 | + } |
| 53 | + return $conversationStarters |
| 54 | +} |
| 55 | +
|
| 56 | +# Function to prompt user for capabilities |
| 57 | +function Get-Capabilities { |
| 58 | + $items_by_sharepoint_ids = @() |
| 59 | + $items_by_url = @() |
| 60 | + while ($true) { |
| 61 | + $type = Read-Host "Enter capability type (File, Site, Library, Folder) (or press Enter to finish)" |
| 62 | + $path = Read-Host "Enter path (or press Enter to finish)" |
| 63 | + if ($type -eq "" -or $path -eq "") { break } |
| 64 | +
|
| 65 | + switch ($type) { |
| 66 | + "File" { |
| 67 | +
|
| 68 | + <#{ |
| 69 | + "list_id": "50f033bf-f372-48ac-8bd6-6af3f421a1c6", |
| 70 | + "name": "PnP Recognition Letter - Leon.pdf", |
| 71 | + "site_id": "18dfc66a-2fa5-4b83-adf5-8726b62a6861", |
| 72 | + "type": "File", |
| 73 | + "unique_id": "9328a5ca-dd8e-4e46-a51e-782e53d7275d", |
| 74 | + "url": "https://leonarmstonmvp.sharepoint.com/sites/Syntex/Shared%20Documents/PnP%20Recognition%20Letter%20-%20Leon.pdf", |
| 75 | + "web_id": "b0224f93-49be-4957-8e22-edbb489c937e" |
| 76 | + }#> |
| 77 | +
|
| 78 | + $searchQuery = Submit-PnPSearchQuery -Query "Path:`"$path`"" -All -SelectProperties "ListId","FileType","SiteTitle","IdentityListItemId","Path","IdentityWebId" |
| 79 | +
|
| 80 | +
|
| 81 | + $capability = @{ |
| 82 | + list_id = $searchQuery.ResultRows[0].ListId |
| 83 | + name = $searchQuery.ResultRows[0].OriginalPath.Split("/")[-1] |
| 84 | + site_id = $searchQuery.ResultRows[0].IdentitySiteCollectionId |
| 85 | + type = $type |
| 86 | + unique_id = $searchQuery.ResultRows[0].IdentityListItemId |
| 87 | + url = $searchQuery.ResultRows[0].Path |
| 88 | + web_id = $searchQuery.ResultRows[0].IdentityWebId |
| 89 | + } |
| 90 | + $items_by_sharepoint_ids += $capability |
| 91 | + } |
| 92 | + "Site" { |
| 93 | + <#{ |
| 94 | + "list_id": "00000000-0000-0000-0000-000000000000", |
| 95 | + "name": "Projects Hub", |
| 96 | + "site_id": "171f7026-6c47-45ce-a734-21f0ee741965", |
| 97 | + "type": "Site", |
| 98 | + "unique_id": "00000000-0000-0000-0000-000000000000", |
| 99 | + "url": "https://leonarmstonmvp.sharepoint.com/sites/ProjectsHub", |
| 100 | + "web_id": "b0224f93-49be-4957-8e22-edbb489c937e" |
| 101 | + }#> |
| 102 | +
|
| 103 | + $searchQuery = Submit-PnPSearchQuery -Query "Path:`"$path`" contentclass:`"STS_Site`"" -All -SelectProperties "ListId","FileType","SiteTitle","IdentityListItemId","Path","IdentityWebId","IdentitySiteId" |
| 104 | +
|
| 105 | + $capability = @{ |
| 106 | + list_id = "00000000-0000-0000-0000-000000000000" |
| 107 | + name = $searchQuery.ResultRows[0].SiteTitle |
| 108 | + site_id = $searchQuery.ResultRows[0].IdentitySiteCollectionId |
| 109 | + type = $type |
| 110 | + unique_id = "00000000-0000-0000-0000-000000000000" |
| 111 | + url = $searchQuery.ResultRows[0].SPWebUrl |
| 112 | + web_id = $searchQuery.ResultRows[0].IdentityWebId |
| 113 | + } |
| 114 | + $items_by_url += $capability |
| 115 | + } |
| 116 | + "Folder" { |
| 117 | + <# |
| 118 | + { |
| 119 | + "list_id": "a1ed0c2f-aa4c-4a4f-a3ce-23c745fe17d0", |
| 120 | + "name": "NORR", |
| 121 | + "site_id": "18dfc66a-2fa5-4b83-adf5-8726b62a6861", |
| 122 | + "type": "Folder", |
| 123 | + "unique_id": "057676b7-9212-44cb-8321-d5df359be4d7", |
| 124 | + "url": "https://leonarmstonmvp.sharepoint.com/sites/Syntex/DrawingPlansDiffCompanies/NORR", |
| 125 | + "web_id": "b0224f93-49be-4957-8e22-edbb489c937e" |
| 126 | + } |
| 127 | + #> |
| 128 | + $searchQuery = Submit-PnPSearchQuery -Query "Path:`"$path`" IsContainer:true" -All -SelectProperties "ListId","FileType","SiteTitle","IdentityListItemId","Path","IdentityWebId","IdentitySiteId" |
| 129 | +
|
| 130 | + $capability = @{ |
| 131 | + list_id = $searchQuery.ResultRows[0].ListId |
| 132 | + name = $searchQuery.ResultRows[0].Title |
| 133 | + site_id = $searchQuery.ResultRows[0].SiteId |
| 134 | + type = $type |
| 135 | + unique_id = $searchQuery.ResultRows[0].UniqueId -replace "{","" -replace "}","".Trim() |
| 136 | + url = $searchQuery.ResultRows[0].OriginalPath |
| 137 | + web_id = $searchQuery.ResultRows[0].WebId |
| 138 | + } |
| 139 | + $items_by_url += $capability |
| 140 | + } |
| 141 | + "Library" { |
| 142 | + <# { |
| 143 | + "list_id": "e042afcd-15d9-4790-a125-264e3b80cdaf", |
| 144 | + "name": "Autofill", |
| 145 | + "site_id": "18dfc66a-2fa5-4b83-adf5-8726b62a6861", |
| 146 | + "type": "Folder", |
| 147 | + "unique_id": "00000000-0000-0000-0000-000000000000", |
| 148 | + "url": "https://leonarmstonmvp.sharepoint.com/sites/Syntex/Autofill", |
| 149 | + "web_id": "b0224f93-49be-4957-8e22-edbb489c937e" |
| 150 | + } |
| 151 | + #> |
| 152 | + $searchQuery = Submit-PnPSearchQuery -Query "Path:`"$path`" contentclass:`"STS_List_DocumentLibrary`"" -All -SelectProperties "ListId","FileType","SiteTitle","IdentityListItemId","Path","IdentityWebId","IdentitySiteId" |
| 153 | +
|
| 154 | + $capability = @{ |
| 155 | + list_id = $searchQuery.ResultRows[0].ListId |
| 156 | + name = $searchQuery.ResultRows[0].Title |
| 157 | + site_id = $searchQuery.ResultRows[0].SiteId |
| 158 | + type = "Folder" |
| 159 | + unique_id = "00000000-0000-0000-0000-000000000000" |
| 160 | + url = $searchQuery.ResultRows[0].OriginalPath.Split("/Forms")[0] |
| 161 | + web_id = $searchQuery.ResultRows[0].WebId |
| 162 | + } |
| 163 | + $items_by_url += $capability |
| 164 | + } |
| 165 | + default { |
| 166 | + Write-Host "Invalid type entered. Please enter either File, Site, or Folder." |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | + return @{ items_by_sharepoint_ids = $items_by_sharepoint_ids; items_by_url = $items_by_url } |
| 171 | +} |
| 172 | +
|
| 173 | +# Prompt user for name |
| 174 | +$name = Read-Host "Enter a custom name for the SharePoint Agent (or press Enter to use the default `"Leon's Agent`")" |
| 175 | +if($name -eq "") |
| 176 | +{ |
| 177 | + $name = "Leon's Agent" |
| 178 | +} |
| 179 | +Write-Host " Name: $name" |
| 180 | +
|
| 181 | +
|
| 182 | +$description = Read-Host "Enter a custom description for the SharePoint Agent (or press Enter to use the default 'This is an agent curated based on the content from the selected file sources.')" |
| 183 | +if($description -eq "") |
| 184 | +{ |
| 185 | + $description = "This is an agent curated based on the content from the selected file sources." |
| 186 | +} |
| 187 | +Write-Host " Description: $description" |
| 188 | +
|
| 189 | +$welcomeMessageText = Read-Host "Enter a custom welcome message for the SharePoint Agent (or press Enter to use the default 'Welcome! Enhance your productivity with this Copilot agent. Start a conversation by asking a question or selecting one of the suggested prompts.')" |
| 190 | +if($welcomeMessageText -eq "") |
| 191 | +{ |
| 192 | + $welcomeMessageText = "Welcome! Enhance your productivity with this Copilot agent. Start a conversation by asking a question or selecting one of the suggested prompts." |
| 193 | +} |
| 194 | +Write-Host " Welcome Message: $welcomeMessageText" |
| 195 | +
|
| 196 | +$instructions = Read-Host "Enter custom instructions for the agent (or press Enter to use the default 'Provide helpful, accurate, and relevant information while maintaining a professional and courteous tone.')" |
| 197 | +if($instructions -eq "") |
| 198 | +{ |
| 199 | + $instructions = "Provide helpful, accurate, and relevant information while maintaining a professional and courteous tone." |
| 200 | +} |
| 201 | +Write-Host " Instructions: $instructions" |
| 202 | +
|
| 203 | +# Get user input |
| 204 | +$conversationStarters = Get-ConversationStarters |
| 205 | +$capabilities = Get-Capabilities |
| 206 | +
|
| 207 | +# Create JSON structure |
| 208 | +$json = @{ |
| 209 | + customCopilotConfig = @{ |
| 210 | + conversationStarters = @{ |
| 211 | + conversationStarterList = @($conversationStarters) |
| 212 | + welcomeMessage = @{ |
| 213 | + text = $welcomeMessageText |
| 214 | + } |
| 215 | + } |
| 216 | + gptDefinition = @{ |
| 217 | + capabilities = @( |
| 218 | + @{ |
| 219 | + items_by_sharepoint_ids = $capabilities.items_by_sharepoint_ids |
| 220 | + items_by_url = $capabilities.items_by_url |
| 221 | + name = "OneDriveAndSharePoint" |
| 222 | + } |
| 223 | + ) |
| 224 | + description = $description |
| 225 | + instructions = $instructions |
| 226 | + name = $name |
| 227 | + } |
| 228 | + icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" |
| 229 | + } |
| 230 | + schemaVersion = "0.2.0" |
| 231 | +} |
| 232 | +
|
| 233 | +# Convert to JSON and save to file |
| 234 | +$json | ConvertTo-Json -Depth 10 | Out-File "$($name).agent" |
| 235 | +
|
| 236 | +Write-Host "JSON file generated: $($name).agent" |
| 237 | +
|
| 238 | +``` |
| 239 | +[!INCLUDE [More about PnP PowerShell](../../docfx/includes/MORE-PNPPS.md)] |
| 240 | +*** |
| 241 | + |
| 242 | + |
| 243 | +## Contributors |
| 244 | + |
| 245 | +| Author(s) | |
| 246 | +|-----------| |
| 247 | +| Leon Armston | |
| 248 | + |
| 249 | +[!INCLUDE [DISCLAIMER](../../docfx/includes/DISCLAIMER.md)] |
| 250 | +<img src="https://m365-visitor-stats.azurewebsites.net/script-samples/scripts/spo-dev-agent-config-creation" aria-hidden="true" /> |
0 commit comments