Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ This template uses Azure Key Vault to store all connections to communicate betwe

This template also uses [Managed Identity](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview) for local development and deployment.

To ensure continued best practices in your own repository, we recommend that anyone creating solutions based on our templates ensure that the [Github secret scanning](https://docs.github.com/code-security/secret-scanning/about-secret-scanning) setting is enabled.
To ensure continued best practices in your own repository, we recommend that anyone creating solutions based on our templates ensure that the [GitHub secret scanning](https://docs.github.com/code-security/secret-scanning/about-secret-scanning) setting is enabled.

You may want to consider additional security measures, such as:

Expand Down
2 changes: 1 addition & 1 deletion TRANSPARENCY_FAQS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ The system allows users to review, reorder and approve steps generated in a plan

## What operational factors and settings allow for effective and responsible use of Multi Agent: Custom Automation Engine – Solution Accelerator?
Effective and responsible use of the Multi Agent: Custom Automation Engine – Solution Accelerator depends on several operational factors and settings. The system is designed to perform reliably and safely across a range of business tasks that it was evaluated for. Users can customize certain settings, such as the planning language model used by the system, the types of tasks that agents are assigned, and the specific actions that agents can take (e.g., sending emails or scheduling orientation sessions for new employees). However, it's important to note that these choices may impact the system's behavior in real-world scenarios.
For example, selecting a planning language model that is not well-suited to the complexity of the tasks may result in lower accuracy and performance. Similarly, assigning tasks that are outside the system's intended scope may lead to errors or incomplete results. Users can choose the LLM that is optimized for responsible use. The default LLM is GPT-4o which inherits the existing RAI mechanisms and filters from the LLM provider. Caching is enabled by default to increase reliability and control cost. We encourage developers to review [OpenAI’s Usage policies](https://openai.com/policies/usage-policies/) and [Azure OpenAI’s Code of Conduct](https://learn.microsoft.com/en-us/legal/cognitive-services/openai/code-of-conduct) when using GPT-40. To ensure effective and responsible use of the accelerator, users should carefully consider their choices and use the system within its intended scope.
For example, selecting a planning language model that is not well-suited to the complexity of the tasks may result in lower accuracy and performance. Similarly, assigning tasks that are outside the system's intended scope may lead to errors or incomplete results. Users can choose the LLM that is optimized for responsible use. The default LLM is GPT-4.1 which inherits the existing RAI mechanisms and filters from the LLM provider. Caching is enabled by default to increase reliability and control cost. We encourage developers to review [OpenAI’s Usage policies](https://openai.com/policies/usage-policies/) and [Azure OpenAI’s Code of Conduct](https://learn.microsoft.com/en-us/legal/cognitive-services/openai/code-of-conduct) when using GPT-4.1. To ensure effective and responsible use of the accelerator, users should carefully consider their choices and use the system within its intended scope.
2 changes: 1 addition & 1 deletion docs/AVMPostDeploymentGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Before starting the post-deployment process, ensure you have the following:

2. **[Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)** <small>(v2.50+)</small> - Command-line tool for managing Azure resources

3. **[Python](https://www.python.org/downloads/)** <small>(v4.9+ recommended)</small> - Required for data processing scripts
3. **[Python](https://www.python.org/downloads/)** <small>(v3.9+ recommended)</small> - Required for data processing scripts

4. **[Git](https://git-scm.com/downloads/)** - Version control system for cloning the repository
5. **[Bicep CLI](https://learn.microsoft.com/azure/azure-resource-manager/bicep/install)** <small>(v0.33.0+)</small> - Required for compiling infrastructure templates
Expand Down
2 changes: 1 addition & 1 deletion docs/AzureGPTQuotaSettings.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
3. **Go to** the `Management Center` from the bottom-left navigation menu.
4. Select `Quota`
- Click on the `GlobalStandard` dropdown.
- Select the required **GPT model** (`GPT-4o`)
- Select the required **GPT model** (`GPT-4.1`)
- Choose the **region** where the deployment is hosted.
5. Request More Quota or delete any unused model deployments as needed.
26 changes: 22 additions & 4 deletions docs/SampleQuestions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ To help you get started, here are some **Sample Prompts** you can ask in the app
## **Teams**
Select the Team option from the top-left section, then click Continue after choosing the desired team.

> _Note: Five teams are available only if all teams are selected during post-deployment; otherwise, only selected teams are visible._
> _Note: Six teams are available only if all teams are selected during post-deployment; otherwise, only selected teams are visible._
- Retail
- HR
- Marketing
- RFP
- Contract Compliance
- Retail Marketing Content Generation

![Application](images/samplequestion_1.png)

Expand Down Expand Up @@ -68,7 +69,6 @@ _Sample operation:_
department: hr, role: manager, start date: 11/23/2025, orientation date: 11/25/2025, location: onsite, email: js@contoso.com, mentor: Jim Shorts, benefits package: standard, ID Card: yes, salary: 70000, Laptop : Dell 14 Plus
```
> _Observe: It will trigger "Generating Plan Action" and "Proposed Plan" with 4 or more Steps_
</br>

- Task: Click on **"Approve Task Plan"** Button.
> _Note: Average response time is around 01 minute 15 seconds._ <br>
Expand All @@ -89,7 +89,6 @@ _Sample operation:_

> _Note: Average response time is 10–15 minutes._ <br>
> _Observe: It will trigger the "Generating Plan Action" and give the Proposed Plan with 5 or more Steps_
</br>

- Task: Click on **"Approve Task Plan"** Button.
> _Note: Average response time is around 01 minute._ <br>
Expand All @@ -110,12 +109,31 @@ _Sample operation:_

> _Note: Average response time is 10–15 minutes._ <br>
> _Observe: It will trigger the "Generating Plan Action" and give the Proposed Plan with 4 or more Steps_
</br>

- Task: Click on **"Approve Task Plan"** Button.
> _Note: Average response time is around 01 minute._ <br>
> _Observe: It goes into "Thinking Process", "Processing your plan" and "coordinating with AI Agents"._ <br>
> _Review the output._

### **Retail Marketing Content Generation Scenario**
If you select the Retail Marketing Content Generation team, follow the prompts below.

>**Agents Used:** Triage, Planning, Research, Text Content, Image Content, Compliance

The Retail Marketing Content Generation Scenario allows users to generate end-to-end marketing assets (copy + image) for retail campaigns, grounded in the Contoso Paint product catalog. Key tasks include:

_Sample operation:_

- Task: Switch to the **"Retail Marketing Content Generation Team"** from the top left section and click **"Continue"** button.
- Task: From the Quick Tasks, select **"Generate a social media post"** and submit it.

> _Note: Average response time is 30–60 seconds for plan generation._ <br>
> _Observe: It will trigger the "Generating Plan Action" and give the Proposed Plan with 5 or more Steps (Planning → Research → Text Content → Image Content → Compliance)._

- Task: Click on **"Approve Task Plan"** Button.
> _Note: Average response time is around 02–03 minutes (image generation included)._ <br>
> _Observe: It goes into "Thinking Process", "Processing your plan" and "coordinating with AI Agents". The final output includes marketing copy (headline, body, CTA, hashtags), a rendered campaign image, and a compliance review._ <br>
> _Review the output._


This structured approach ensures that users receive automated, AI-coordinated task execution and intelligent responses from specialized agents.
2 changes: 1 addition & 1 deletion docs/TroubleShootingSteps.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,4 @@ Use these as quick reference guides to unblock your deployments.
---------------------------------

💡 Note: If you encounter any other issues, you can refer to the [Common Deployment Errors](https://learn.microsoft.com/en-us/azure/azure-resource-manager/troubleshooting/common-deployment-errors) documentation.
If the problem persists, you can also raise an bug in our [MACAE Github Issues](https://github.com/microsoft/Multi-Agent-Custom-Automation-Engine-Solution-Accelerator/issues) for further support.
If the problem persists, you can also raise a bug in our [MACAE GitHub Issues](https://github.com/microsoft/Multi-Agent-Custom-Automation-Engine-Solution-Accelerator/issues) for further support.
10 changes: 5 additions & 5 deletions docs/mcp_server.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
Capturing the notes from auth install before deleting for docs...

### Auth section:
Requires and app registration as in azure_app_service_auth_setup.md so not deployed by default.
Requires an app registration as in azure_app_service_auth_setup.md so not deployed by default.

To setup basic auth with FastMCP - bearer token - you can integrate with Azure by using it as your token provider.

``` from fastmcp.server.auth import JWTVerifier```

```
auth = JWTVerifier(
jwks_uri="https://login.microsoftonline.com/52b39610-0746-4c25-a83d-d4f89fadedfe/discovery/v2.0/keys",
#issuer="https://login.microsoftonline.com/52b39610-0746-4c25-a83d-d4f89fadedfe/v2.0",
jwks_uri="https://login.microsoftonline.com/<your-tenant-id>/discovery/v2.0/keys",
#issuer="https://login.microsoftonline.com/<your-tenant-id>/v2.0",
# This issuer is not correct in the docs. Found by decoding the token.
issuer="https://sts.windows.net/52b39610-0746-4c25-a83d-d4f89fadedfe/",
issuer="https://sts.windows.net/<your-tenant-id>/",
algorithm="RS256",
audience="api://7a95e70b-062e-4cd3-a88c-603fc70e1c73"
audience="api://<your-app-client-id>"
)
```

Expand Down
2 changes: 1 addition & 1 deletion docs/quota_check.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Check Quota Availability Before Deployment

Before deploying the accelerator, **ensure sufficient quota availability** for the required model.
> **For Global Standard | GPT-4o - the capacity to at least 150k tokens for optimal performance.**
> **For Global Standard | GPT-4.1 — ensure a capacity of at least 150k tokens for optimal performance.**

### Login if you have not done so already
```
Expand Down
2 changes: 1 addition & 1 deletion src/App/src/commonComponents/modules/ChatExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const ChatExample: React.FC = () => {
<div className="bot-tag">BOT</div>
</div>
<div className="message-content">
You got it! I've initiated a background check and everything looks good to go— You're ready to move onto helping Jessica set up and Office 365 account. Want me to hand that over to your Manager Agent?
You got it! I've initiated a background check and everything looks good to go — you're ready to move on to helping Jessica set up an Office 365 account. Want me to hand that over to your Manager Agent?
</div>
<div className="message-actions">
<button className="action-button">👍</button>
Expand Down
2 changes: 1 addition & 1 deletion src/App/src/components/common/TeamSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ const TeamSelector: React.FC<TeamSelectorProps> = ({
Are you sure you want to delete "{teamToDelete?.name}"?
</DialogTitle>
<Text className={styles.deleteConfirmText}>
This team configurations and its agents are shared across all users in the system. Deleting this team will permanently remove it for everyone, and this action cannot be undone.
This team configuration and its agents are shared across all users in the system. Deleting this team will permanently remove it for everyone, and this action cannot be undone.
</Text>
</DialogBody>
<div className={styles.deleteDialogActions}>
Expand Down
2 changes: 1 addition & 1 deletion src/App/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/setupTests.ts'],
setupFiles: ['./src/setupTests.tsx'],
css: true,
},
resolve: {
Expand Down
2 changes: 1 addition & 1 deletion src/backend/auth/auth_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_tenantid(client_principal_b64):
# Decode the base64 header to get the JSON string
decoded_bytes = base64.b64decode(client_principal_b64)
decoded_string = decoded_bytes.decode("utf-8")
# Convert the JSON string1into a Python dictionary
# Convert the JSON string into a Python dictionary
user_info = json.loads(decoded_string)
# Extract the tenant ID
tenant_id = user_info.get("tid") # 'tid' typically holds the tenant ID
Expand Down
2 changes: 1 addition & 1 deletion src/backend/common/utils/otlp_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

def configure_oltp_tracing(endpoint: str = None) -> trace.TracerProvider:
# Configure Tracing
tracer_provider = TracerProvider(resource=Resource({"service.name": "macwe"}))
tracer_provider = TracerProvider(resource=Resource({"service.name": "macae"}))
processor = BatchSpanProcessor(OTLPSpanExporter())
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
Expand Down
22 changes: 11 additions & 11 deletions src/tests/backend/common/utils/test_otlp_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def test_configure_oltp_tracing_default_parameters(
result = configure_oltp_tracing()

# Verify Resource creation
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})

# Verify TracerProvider creation
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
Expand Down Expand Up @@ -126,7 +126,7 @@ def test_configure_oltp_tracing_with_endpoint_parameter(
result = configure_oltp_tracing(endpoint=endpoint)

# Verify the same behavior as default case (endpoint parameter is currently unused)
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down Expand Up @@ -162,7 +162,7 @@ def test_configure_oltp_tracing_with_none_endpoint(
result = configure_oltp_tracing(endpoint=None)

# Verify the same behavior as default case
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down Expand Up @@ -269,7 +269,7 @@ def test_configure_oltp_tracing_tracer_provider_creation_error(
configure_oltp_tracing()

# Verify Resource was created but subsequent operations were not called
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_exporter.assert_not_called()
mock_processor.assert_not_called()
mock_trace.set_tracer_provider.assert_not_called()
Expand Down Expand Up @@ -297,7 +297,7 @@ def test_configure_oltp_tracing_exporter_creation_error(
configure_oltp_tracing()

# Verify creation up to exporter was called
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()

Expand Down Expand Up @@ -332,7 +332,7 @@ def test_configure_oltp_tracing_processor_creation_error(
configure_oltp_tracing()

# Verify creation up to processor was called
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down Expand Up @@ -369,7 +369,7 @@ def test_configure_oltp_tracing_add_span_processor_error(
configure_oltp_tracing()

# Verify all creation steps were called
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down Expand Up @@ -407,7 +407,7 @@ def test_configure_oltp_tracing_set_tracer_provider_error(
configure_oltp_tracing()

# Verify all steps up to set_tracer_provider were called
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down Expand Up @@ -452,7 +452,7 @@ def test_configure_oltp_tracing_service_name_configuration(
result = configure_oltp_tracing()

# Verify service name is set correctly
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})

# Verify the resource is used in TracerProvider
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
Expand Down Expand Up @@ -487,7 +487,7 @@ def test_configure_oltp_tracing_call_sequence(

# Verify call sequence using call order
expected_calls = [
call({"service.name": "macwe"}), # Resource creation
call({"service.name": "macae"}), # Resource creation
]
mock_resource.assert_has_calls(expected_calls)

Expand Down Expand Up @@ -542,7 +542,7 @@ def test_configure_oltp_tracing_with_empty_string_endpoint(
result = configure_oltp_tracing(endpoint="")

# Verify same behavior as default (endpoint parameter is unused in current implementation)
mock_resource.assert_called_once_with({"service.name": "macwe"})
mock_resource.assert_called_once_with({"service.name": "macae"})
mock_tracer_provider_class.assert_called_once_with(resource=mock_resource_instance)
mock_exporter.assert_called_once_with()
mock_processor.assert_called_once_with(mock_exporter_instance)
Expand Down
Loading