Enterprise AI Relay — Setup Guide
EnterpriseRoute all DFFS AI traffic through a server you control. Your AI credentials never leave your infrastructure, prompts and responses stay inside your data boundary, and you can connect to private or on-premise AI endpoints that are not reachable from the public internet.
Before you start — getting the relay files
This guide describes deploying two files, ai-relay.html and ai-relay.php. Both are a free download, together in ai-relay.zip — Enterprise files →. They aren’t license-gated: DFFS only reaches a relay through the AIRelayPath setting, which is Enterprise-only, so you can review them before buying.
You do not have to host anything at all. Setting up a relay requires an Enterprise-tier license and a PHP-capable web server you control — but it is optional. The AI Assistant also works with no API key and no relay: copy or download the assembled prompt, run it in whatever AI tool your organization already approves, and paste or import the result. Administrators can alternatively supply their own API key to keep the exchange inline. Both are covered in the AI Assistant guide. Host a relay when you want the inline experience and want every request to stay on your own infrastructure.
Why a relay is needed at all: AI provider APIs reject direct cross-origin calls from a browser, so any in-browser AI feature needs a same-origin hop. Running that hop yourself means prompts, responses and credentials stay entirely within your infrastructure.
How it works
SharePoint Online
└── DFFS loads ai-relay.html in a hidden iframe
└── postMessage (prompt + nonce) ──→ ai-relay.html
└── fetch (same-origin) ──→ ai-relay.php
└── HTTPS ──→ AI provider endpoint
└── streaming chunks ──→ back to SharePoint
- DFFS loads
ai-relay.htmlin a hidden iframe hosted on your server. - The HTML page receives the prompt via
postMessagefrom the DFFS parent window, validates the origin, then forwards it toai-relay.phpon the same server. ai-relay.phpholds the API credentials (never exposed to the browser) and calls the configured AI provider.- Streaming response chunks are forwarded back to DFFS via
postMessageas they arrive.
Files
| File | Purpose |
|---|---|
ai-relay.html | Browser-side bridge. Hosted publicly. Validates origins and relays postMessages to the PHP backend. |
ai-relay.php | Server-side backend. Holds credentials, calls the AI API, streams the response. |
Both files must be in the same folder on your web server.
Prerequisites
| Requirement | Details |
|---|---|
| Web server | IIS, Apache, nginx, Azure App Service, or any PHP-capable host |
| PHP 8.1 or later | With the php-curl extension enabled |
| Output buffering disabled | Required for streaming — see Server configuration |
| HTTPS | The relay URL must be https:// — mixed-content restrictions prevent HTTP iframes in SharePoint |
| Network access to AI endpoint | The relay server must be able to reach the AI API — the AI endpoint does not need to be public |
| DFFS Enterprise license | The enterprise relay feature requires an Enterprise-tier license |
Step 1 — Deploy the files
Copy ai-relay.html and ai-relay.php to the same folder on your web server. The folder must be reachable over HTTPS from the public internet (SharePoint Online loads the HTML file as an iframe).
The PHP backend (ai-relay.php) does not need to be publicly accessible by end users — it is called only by the HTML page via a same-origin fetch. You can restrict direct access to it at the web-server or firewall level if desired.
Step 2 — Configure ai-relay.html
Open ai-relay.html and edit the ALLOWED_ORIGINS array near the top of the script:
const ALLOWED_ORIGINS = [
"https://yourtenant.sharepoint.com",
// "https://yourtenant-admin.sharepoint.com",
];
Replace yourtenant with your SharePoint tenant subdomain. Add one entry per origin that should be permitted to call the relay. The origin must be in the format https://<tenant>.sharepoint.com with no trailing slash.
Important: the same origins must also be listed in
ai-relay.php(see Step 3). Both files enforce the origin check independently.
Step 3 — Configure ai-relay.php
Open ai-relay.php and make the following changes.
3a — Set the allowed origins
Find the ALLOWED_ORIGINS constant and add the same origins as in ai-relay.html:
const ALLOWED_ORIGINS = [
"https://yourtenant.sharepoint.com",
];
3b — Choose your AI provider
Set AI_PROVIDER to one of the supported values:
const AI_PROVIDER = "azure_openai"; // change to your provider
| Value | Provider |
|---|---|
azure_openai | Azure OpenAI Service (recommended for enterprise) |
claude | Anthropic Claude — direct API or ZDR contract |
openai | OpenAI — direct API or enterprise contract |
gemini | Google Gemini REST API or Vertex AI |
aws_bedrock | AWS Bedrock — requires additional setup (see below) |
ollama | Self-hosted / on-premise (Ollama, vLLM, LM Studio, llama.cpp) |
3c — Set credentials and provider-specific settings
Credentials are read from environment variables — never hardcode an API key in the file. Set the environment variables in your web server configuration, App Service application settings, or a .env loader.
Azure OpenAI Service
The most common enterprise choice. Runs entirely within your Azure tenant. Supports private endpoints and Managed Identity (no API key required).
Environment variables:
| Variable | Value |
|---|---|
DFFS_AI_KEY | Your API key from the Azure portal — or leave empty to use Managed Identity |
AZURE_OPENAI_RESOURCE | The resource name (e.g. my-openai-resource) |
AZURE_OPENAI_DEPLOYMENT | The deployment name (e.g. gpt-4o-prod) |
Find these values in: Azure portal → your OpenAI resource → Keys and Endpoint, and Deployments → your deployment name.
Managed Identity (preferred — no keys to manage):
- Assign a system-assigned identity to the App Service or VM hosting the relay.
- Grant the identity the Cognitive Services OpenAI User role on the Azure OpenAI resource.
- Leave
DFFS_AI_KEYempty. The relay fetches a token from the Azure Instance Metadata Service (IMDS) automatically.
Private endpoint:
If your Azure OpenAI resource has a private endpoint, replace the public URL in callAzureOpenAI() with your private endpoint hostname:
https://your-resource.privatelink.openai.azure.com/openai/deployments/...
This works as long as the relay server is on a VNet that can reach the private endpoint.
Anthropic Claude
Environment variable: DFFS_AI_KEY — your Anthropic API key.
For a ZDR (zero-data-retention) contract, the endpoint URL is the same — ZDR is enforced at the Anthropic account level, not by a different URL. Set the model in AI_CONFIG["claude"]["model"] if you want to use a specific version.
OpenAI
Environment variable: DFFS_AI_KEY — your OpenAI API key.
OpenAI enterprise contracts include zero-data-retention by default. Set AI_CONFIG["openai"]["model"] to your preferred model (default: gpt-4o).
Google Gemini / Vertex AI
Environment variable: DFFS_AI_KEY — your Gemini API key (for the public API).
For Vertex AI (enterprise — VPC Service Controls, CMEK):
- Uncomment the Vertex AI URL block in
callGemini(). - Set
AI_CONFIG["gemini"]["project_id"]and"location"(or use environment variables). - Replace API key auth with a GCP service account token (
Authorization: Bearer <token>). The service account needs the Vertex AI User role.
AWS Bedrock
AWS Bedrock requires AWS Signature Version 4 (SigV4) request signing, which cannot be done without a library. Three options are available:
Option 1 — AWS PHP SDK (recommended):
composer require aws/aws-sdk-php
Attach an IAM role to the host (EC2, ECS, Lambda, App Runner) with the permissions bedrock:InvokeModel and bedrock:InvokeModelWithResponseStream. No API key is needed — the SDK picks up credentials from the role automatically. See the comments in callAwsBedrock() in ai-relay.php for the full code example.
Option 2 — Lambda proxy (no SDK required):
Deploy a small AWS Lambda (Node.js or Python) that wraps Bedrock and exposes a plain REST endpoint via API Gateway with an API key. The relay then calls that endpoint like any other HTTP API — no SigV4 needed in PHP.
Option 3 — Bedrock Access Gateway (open source):
github.com/aws-samples/bedrock-access-gateway provides an OpenAI-compatible /v1/chat/completions frontend for Bedrock. Once deployed, set AI_PROVIDER to openai and point the base_url at your gateway.
On-premise / self-hosted (Ollama, vLLM, LM Studio, llama.cpp)
Most self-hosted inference servers expose an OpenAI-compatible /v1/chat/completions endpoint.
Environment variable: OLLAMA_URL — the base URL of your inference server (e.g. http://ollama-host:11434).
The AI host does not need to be internet-accessible — only the relay server needs a network route to it. This makes the ollama provider suitable for completely air-gapped environments.
For vLLM with token authentication, set AI_CONFIG["ollama"]["api_key"] (or a corresponding environment variable).
Examples of compatible servers and their default URLs:
| Server | Default URL |
|---|---|
| Ollama | http://localhost:11434 |
| vLLM | http://vllm-host:8000 |
| LM Studio | http://localhost:1234 |
| llama.cpp server | http://localhost:8080 |
Step 4 — Register the relay URL in DFFS
Add an item to the DFFS_Settings list on the ModernDFFS_Central site (see the reusable-content-setup.md guide for how to create this list):
| Field | Value |
|---|---|
| Title | AIRelayPath |
| SettingValue | The full HTTPS URL to ai-relay.html on your server |
Example:
https://relay.contoso.com/dffs/ai-relay.html
DFFS reads this value on load and routes all AI requests through that URL instead of the default BYOK relay.
Server configuration
Disable output buffering (required for streaming)
Streaming responses will not work if the web server buffers output. Configuration varies by server:
PHP (php.ini or .htaccess):
output_buffering = Off
nginx — add to your location block:
fastcgi_buffering off;
proxy_buffering off;
Apache — add to your VirtualHost or .htaccess:
Header set X-Accel-Buffering "no"
The PHP script also sends X-Accel-Buffering: no and calls ob_implicit_flush(true) automatically.
HTTPS / TLS
The relay must be served over HTTPS. SharePoint Online will not load an HTTP iframe due to mixed-content restrictions. Use a valid certificate from a public CA (Let’s Encrypt, DigiCert, etc.) or your organization’s internal CA if the cert is trusted on all client machines.
Network topology
The relay server must be reachable from the public internet (SharePoint loads it). The AI endpoint does not need to be public — only the relay server needs a route to it. This allows the relay to call private or VPC-isolated endpoints:
SharePoint Online
│ [public HTTPS]
▼
Relay server (publicly accessible)
│ [private network / VNet / VPC]
▼
AI endpoint (private — e.g. Azure OpenAI private endpoint, Bedrock VPC endpoint, Ollama on internal host)
Examples:
| Cloud | Topology |
|---|---|
| Azure | App Service (public) + VNet Integration → Azure OpenAI private endpoint |
| AWS | ECS/EC2 in public subnet → VPC endpoint → Bedrock |
| On-premise | IIS/Apache in DMZ → internal Ollama or vLLM server |
Security notes
- Credentials never reach the browser. The HTML page intentionally ignores any
apiKeysent from DFFS — credentials are held only inai-relay.phpon your server. - Origin validation is enforced independently in both
ai-relay.html(viaALLOWED_ORIGINS) andai-relay.php(viaALLOWED_ORIGINSand CORS headers). Both must list your tenant origin. - Restrict PHP access at the web-server or firewall level if you want to prevent direct calls to
ai-relay.phpfrom outside SharePoint (e.g. from curl or Postman). Since the PHP file is same-origin with the HTML, blocking external access to it does not affect normal DFFS usage. - Use environment variables for all credentials — never hardcode API keys in the PHP file.
- Zero-data-retention (ZDR): The relay does not affect ZDR guarantees. Because prompts flow through your server (not through DFFS infrastructure), your enterprise data agreement with the AI provider applies end-to-end. ZDR is enforced at the provider API level.
Verification
After completing setup, open any DFFS form configurator on a site covered by the Enterprise license:
- Go to the AI tab.
- An Enterprise AI relay banner should appear, showing that the relay is configured and ready. No API key input is shown.
- Enter a short test prompt and click Send to AI. The response should stream in within a few seconds.
If the banner shows “No enterprise relay has been configured”, verify that the AIRelayPath item exists in DFFS_Settings and that the URL is correct.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| AI tab shows “No enterprise relay configured” | AIRelayPath missing from DFFS_Settings or wrong key name | Add the item; key is case-sensitive |
| Relay banner shown but Send returns a timeout | Relay URL unreachable from the user’s browser | Verify the HTTPS URL is public and the certificate is valid |
HTTP 403 from ai-relay.php | Origin not in ALLOWED_ORIGINS in the PHP file | Add your https://<tenant>.sharepoint.com to the PHP ALLOWED_ORIGINS array |
| Streaming stops mid-response / no chunks | Output buffering enabled on the server | Disable buffering (see Server configuration) |
HTTP 500 from ai-relay.php | php-curl extension not installed, or wrong credentials | Enable php-curl; check environment variables are set and readable by the web server process |
| Azure OpenAI returns 401 with Managed Identity | Identity not assigned or missing role | Assign a system-assigned identity and grant it the “Cognitive Services OpenAI User” role on the OpenAI resource |
| AWS Bedrock returns 501 | Stub not replaced with SDK implementation | Follow the SDK or Lambda proxy instructions in Step 3 |
ai-relay.html loads but nothing happens | Parent origin not in HTML ALLOWED_ORIGINS | Add https://<tenant>.sharepoint.com to the ALLOWED_ORIGINS array in ai-relay.html |
Related
- AI Assistant — guide — the feature itself, response modes, scoping and prompts.
- Reusable Content — guide — how the central site and its
DFFS_Settingslist are created. - Architecture & Security Overview — full data-flow and security documentation for review teams.