Skip to main content

Host an AI agent HTTP API

App Service Builder can host an HTTP assistant application that sends bounded text requests to a separately configured external model service.

At a glance​

  • Run the agent-web Node 24 sample as a single-turn, tool-free assistant.
  • Explicitly choose an authorized OpenAI model or Azure OpenAI deployment and configure its key server-side.
  • Bound input, output, concurrency, and model wait time; service failures return errors rather than simulated answers.
  • Use this guide for Private Preview development/test only after your contact confirms the environment and sample are ready for you.

Prerequisites​

Use your Private Preview subscription and an available region. Open the Portal or install Builder CLI. The source belongs to the AI assistant repository. See the sample catalog for choices and target-verification prerequisites.

App Service Builder hosts the HTTP application, not the model or a managed agent runtime. The sample deliberately limits agent behavior to one assistant turn without autonomous tools, conversation persistence, or background work. Its external integration uses the documented OpenAI Responses API or Azure OpenAI Responses API in Microsoft Foundry. You separately authorize service access, select a compatible model, and own charges and data-handling decisions. No model availability or production suitability is implied.

Quick start locally​

Fork the sample repository to your account and clone your fork. Run from its repository root, keeping the root builder.yaml with the application. With Node 24:

npm ci --ignore-scripts
npm test
export APP_API_TOKEN="$(node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))")"
npm start

Use curl http://127.0.0.1:8080/health to confirm process liveness. Tests mock the provider boundary and require no provider credential. Model requests remain unavailable until you configure the real service; there is no fake-success fallback. For an opt-in real request, securely supply MODEL_SERVICE=openai, your OPENAI_API_KEY, and an authorized OPENAI_MODEL in the server environment, then restart. Choose a model supporting Responses API text input and max_output_tokens. For Azure OpenAI in Microsoft Foundry, instead supply MODEL_SERVICE=azure-openai, AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com, the existing resource's AZURE_OPENAI_API_KEY, and AZURE_OPENAI_DEPLOYMENT set to your model deployment name. The sample uses Azure's /openai/v1/responses endpoint; other Foundry model providers and hosted-agent runtimes are not implemented. Do not paste keys into shell history or put them in browser code.

In another terminal with the same app token:

curl --fail-with-body http://127.0.0.1:8080/agent \
-H "Authorization: Bearer $APP_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"message":"Explain HTTP in one sentence."}'

Successful output is JSON containing a model-produced reply. Answers are nondeterministic and need safety/quality evaluation for your use case. Stop the server with Ctrl+C.

Request and configuration contract​

ItemSample contract
POST /agentAuthenticated JSON with only message: nonblank text up to 2000 UTF-16 code units; body up to 8192 bytes
Success{"reply":"<text>"}; completed assistant text up to 4000 UTF-16 code units
GET /healthPublic status 200 with OK; process liveness, not provider readiness
GET /Public sample identifier
APP_API_TOKENRequired app bearer credential; at least 32 characters
MODEL_SERVICERequired value openai or azure-openai; no other provider implementation
OPENAI_MODELExplicit authorized model ID; no default
OPENAI_API_KEYServer-side provider credential; never included in model input
AZURE_OPENAI_ENDPOINTAzure provider only: HTTPS https://<resource>.openai.azure.com origin without credentials, custom port, path, query, or fragment
AZURE_OPENAI_DEPLOYMENTAzure provider only: explicit model deployment name
AZURE_OPENAI_API_KEYAzure provider only: server-side resource key; never included in model input
PUBLIC_ORIGINOptional exact HTTPS origin without trailing slash, allowed when a client supplies Origin
Provider callFixed OpenAI URL or the configured Azure resource's /openai/v1/responses; one request, no retries, 512 output tokens, store:false, stream:false, tools:[]
BoundsFour active requests per process, ten-second model deadline, upstream response capped at 65,536 bytes

Incomplete, refused, empty, oversized, or failed model responses return an error. The sample checks for exact credential leaks, but that is not a general guarantee against sensitive-data disclosure. Review the provider's text-generation guidance when adapting the request. The store:false request option is not a promise about all provider retention policies.

Deploy and connect​

Commit and push changes to your fork, retaining its source, lockfile, tests, README, and root builder.yaml. Authorize your fork using source control and keep the app source root at the repository root ("."). The included manifest selects a Node 24 web component on port 8080, starts node server.mjs, and checks /health for status 200.

Keep the fork, branch, and root builder.yaml you prepared above. Builder deploys committed GitHub source, not uncommitted local files.

Open the App Service Builder Portal. Your Azure account needs permission to create and deploy Microsoft.Web/builderApps resources. Creating a resource group also requires permission to create groups in the selected subscription.

  1. Sign in to the Portal with the Microsoft account authorized for your subscription.
  2. Select the subscription and choose Create.
  3. In Connect GitHub, sign in to GitHub and authorize the OAuth App. Keep Use my repository selected to deploy the fork you prepared above. Choose the account or organization that owns your fork, then select that repository and branch. Use Change account if you need a different GitHub account, or Refresh access after changing repository permissions. Select Next.
  4. In Choose approach, confirm the selected repository and branch. Keep Let Builder handle it selected. The App Service Builder GitHub App needs access to this repository to read your code, build it, and deploy your app. Signing in to GitHub alone does not grant this access. If prompted, select Install GitHub App and grant access to your selected repository, or add it to an existing installation. Close the GitHub window to refresh access, or select Refresh access after approval. Select Next when Builder is connected and GitHub App access confirmed are shown.
  5. In App details, enter an app name and select the subscription, resource group, and offered location. To create a resource group, select Create new, enter its name, and choose Resource group region. Select Add. The group appears as (new) and is created when you submit. Its region stores the resource group's metadata and does not change the app's region. Select Next.
  6. On Review and create, confirm the app, repository, branch, subscription, resource group, and app region. Select Create and deploy.
  7. Open the app's Deployments page and wait for the deployment to succeed. In Versions, inspect the source revision, component results, and build logs. Select Deploying to open an in-progress deployment's steps and logs. On Overview, use Browse to open the app URL.

Already prepared a fork? Keep Use my repository selected so you deploy that source, not a second copy. To start with a new sample instead, follow Create from a Portal template. Use GitHub Actions is marked Coming soon; use the Builder-managed approach for this preview.

If group creation fails, app creation does not start. If the group was created before a later failure, it remains in Azure; cancelling does not delete it. Check the existing group and app before retrying, and inspect a group's contents before deleting it separately.

See GitHub authorization requirements for organization approvals and SSO. If app creation succeeds but deployment cannot start, read the error and retry deployment on the existing app rather than creating a duplicate. For “Source revision does not contain builder.yaml”, push the missing manifest before retrying.

For API automation, use the ARM API deployment guide with this same fork, branch, and source root ".". ARM and Bicep infrastructure templates provision the resource; separately authorize and connect this source, then deploy it through CLI or ARM.

Use application variables to set app authentication and model configuration. PUBLIC_ORIGIN is optional for clients that supply Origin; server-side requests do not require it. Choose Save and deploy to capture values in a new version, and follow that deployment to success. There is no runtime-only secret toggle: variables are shared with builds and all components. Keep this compute-only sample's build free of environment dumps, public asset embedding, and credential logging. Saving values does not mutate a running version. The public /health endpoint returns only process liveness, without calling the model or returning configuration. The app requires its bearer credential and validates any supplied Origin value.

After success, use <returned-app-origin>/agent from an authorized server-side client with the same JSON contract. Use HTTPS and retain the app token server-side. The app binds 0.0.0.0:8080; Origin validation is not a substitute for isolated networking or authentication. No browser CORS access is granted. Verify an authenticated request to the deployed app and an actual response from your selected model service. Local tests and health success alone do not prove that model requests work.

Authorization and safety​

Deployed-app authentication covers the platform identity boundary separately from the sample app token. For platform bearer access alongside sample authentication, send the platform credential in X-Embr-Authorization and the sample credential in Authorization. The proxy consumes and removes Authorization when it uses that header for platform authentication. Qualify credential acquisition, audiences, and forwarding on the target; browser login is not a machine-client credential. Shared-token protection and a per-process concurrency cap are development safeguards, not per-user authorization, a distributed rate limit, or a cost budget.

Treat caller input and model output as untrusted. Do not send secrets or sensitive customer data in prompts. Before adding agent tools, validate the caller's scopes/roles and resource ownership server-side for every operation. A prompt, a model decision, or a tool annotation never authorizes writes. Side-effect tools require explicit authorization, bounded execution, and a confirmation design; this sample supplies none. Keep credentials out of source, request bodies, URLs, browser bundles, responses, and logs.

Troubleshooting​

ResultCheck
503Supply a valid app token and all explicit model settings, then deploy the captured version
401Supply the exact app bearer credential and verify the platform header separately
403A supplied Origin must match the exact configured origin
400 or 415Send only bounded, nonblank message text as application/json
429Wait for one of four active requests in this process to finish
502Check provider access, model compatibility, and output limits without exposing upstream credentials/errors
504The model deadline expired; investigate service latency before retrying

Clean up​

Stop local servers, unset credentials/configuration, and revoke the dedicated provider key.

Delete only the test app you created when you no longer need it. App deletion does not remove your GitHub repository, resource group, or separately owned services and user-assigned identities.

Return to the app inventory and choose Delete from the test app's actions. Alternatively, open the app's Settings and select Delete under Danger zone. Confirm the selected app and follow deletion to completion. Deleting from Settings returns you to the home inventory after the deletion request is accepted.

App deletion does not close the external service account. Before sharing the app, verify startup, health, authentication, and a real model request in your preview environment. Use this guide only for an application-owned assistant that calls a separately configured model service. Builder does not provide a managed agent runtime. Use host an MCP server to expose read-only tools to another client instead of owning the assistant's model request.