> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dotbot.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Run the question delivery service

> Deploy and run the dotbot server that delivers needs-input questions to people over Teams, Email, Jira, and Slack and stores their answers.

The question delivery service is the server side of dotbot's human-in-the-loop flow. When a task reaches `needs-input`, dotbot sends the question to this service, which delivers it to a person over Teams, email, Jira, or Slack and collects the answer. The service is an ASP.NET Core application built on the Microsoft 365 Agents SDK, targeting .NET 9, and is designed to run in Azure App Service. The client refers to it as the "mothership".

This page covers running and deploying the service. For the client side, the `mothership` settings block and how dotbot routes a question, see [Teams integration](/guides/teams-integration).

## How it fits the needs-input flow

When the AI cannot proceed without a decision, it calls the `task_set_status` MCP tool to move the task to `needs-input` and records the question on the task. dotbot's notification client reads the `mothership` settings block and posts the question to the service. The service delivers it on the configured channel, waits for the person to answer, and stores the answer. dotbot polls for the answer on its `poll_interval_seconds` interval, attaches it to the paused task, and resumes the pipeline.

## Channels

The service delivers to any enabled channel. It exposes `POST /api/notify` and routes the question per channel:

| Channel | Delivery                          | Answer path                                                                              |
| ------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| Teams   | Adaptive Card                     | The person taps a choice; the answer returns through the Bot Service to `/api/messages`. |
| Email   | Microsoft Graph `sendMail` (HTML) | The message includes a magic-link URL to the `/respond` page.                            |
| Jira    | REST comment on the issue         | The comment includes a magic-link URL to the `/respond` page.                            |
| Slack   | `chat.postMessage` (Block Kit)    | The message includes a magic-link URL to the `/respond` page.                            |

For email, Jira, and Slack, the recipient clicks the magic link and answers on the `/respond` Razor page. For Teams, the recipient answers directly in the card. Either way, the answer is persisted to Azure Blob Storage.

## Question types

The service supports five question types:

| Type              | What the person does                                                                                                                                 |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `singleChoice`    | Picks one option.                                                                                                                                    |
| `multiChoice`     | Picks one or more options.                                                                                                                           |
| `approval`        | Approves or rejects a proposal. This type also carries attached documents for review, absorbing what was previously a separate document review type. |
| `freeText`        | Writes a free-form answer.                                                                                                                           |
| `priorityRanking` | Orders a set of items by priority.                                                                                                                   |

## Where answers are stored

Each answer is persisted as a flat JSON record in Azure Blob Storage, in the `answers` container. The record holds the answer and responder fields at the top level, and it deliberately does not duplicate the question or the recipient list. When dotbot reads the answers, the service assembles each stored record into the full response envelope it returns over the API.

## Running locally

Prerequisites for local development:

* .NET 9 SDK
* Azure CLI
* Terraform 1.6 or later
* An Azure subscription

Run the service from the repository:

```powershell theme={null}
dotnet run --project src/Dotbot.Server
```

The service listens on `http://localhost:5048`. Teams, Bot Service, and the magic-link channels need a public endpoint, so expose the local port with a dev tunnel or ngrok, then point the Bot Service messaging endpoint at the tunnel URL.

## Required configuration

The service reads its configuration from `appsettings` files and user secrets. Several keys are required at startup, and the service fails fast if they are missing. Keep secrets in `appsettings.Development.json` (gitignored) or in user secrets, not in source control. The required keys are:

* `MicrosoftAppTenantId`, `MicrosoftAppId`, and `MicrosoftAppPassword` for the Agents SDK and Bot Service authentication.
* `BlobStorage:AccountUri` or `BlobStorage:ConnectionString`. One of the two is required for answer storage.
* `ApiSecurity:ApiKey`, the shared secret checked against the `X-Api-Key` request header.
* `TokenValidation` and `Connections` settings for token validation and the service connection.
* `DeliveryChannels` settings for Email, Jira, and Slack, needed only for the channels you enable.

<Warning>
  Do not commit credentials. Store the API key, app password, and channel secrets in `appsettings.Development.json` or in user secrets, both of which stay off source control.
</Warning>

## Deploying to Azure

The service ships with Terraform under `terraform/` and a `scripts/Deploy.ps1` deployment script. Provision the infrastructure first, then deploy the application:

```powershell theme={null}
cd terraform
terraform init
terraform plan
terraform apply
```

```powershell theme={null}
.\scripts\Deploy.ps1
```

Terraform provisions the resource group, the Entra ID app, the App Service Plan and App Service, and the Bot Service with its Teams channel. If you already have an Entra ID app, set `create_azuread_app = false` and supply the existing app ID and password in your Terraform variables instead of letting Terraform create one. After `terraform apply`, read the bot credentials from the Terraform outputs and use them in your local configuration.
