You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ai/gen-ai-agents/oci-enterprise-ai-chat/README.md
+50-16Lines changed: 50 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
# OCI Enterprise AI Agents
1
+
# OCI Enterprise AI
2
2
3
3
A chat interface and agent hub for [Oracle Cloud Infrastructure Enterprise AI](https://www.oracle.com/artificial-intelligence/enterprise-ai/). Streaming responses, MCP tool integration, OAuth2 SSO, and a full settings workbench to tailor the assistant to each deployment.
4
4
@@ -21,7 +21,7 @@ Open [http://localhost:3000](http://localhost:3000). On first run, create a `.en
21
21
- Node.js 22+ (the Dockerfile uses `node:22-alpine`)
22
22
- An OCI tenancy with access to **Generative AI** (Projects, inference, vector & semantic stores) and **Generative AI Agents** (memory, agent flows)
23
23
- Locally: `~/.oci/config` with a valid API key
24
-
- In a container: **Resource Principal**configured on the Container Instance
24
+
- In a Container Instance: **Resource Principal**(or **Instance Principal** for a Compute VM)
> **About the Project.** A **Project** is the OCI Generative AI resource that organizes conversations, responses, files, and sandboxes: it's required for any OpenAI-compatible API call. It's also where you configure data retention (max 720h for both responses and conversations), short-term memory compaction, and long-term memory extraction/embedding models. Memory and compaction settings are **set at project creation and cannot be changed later**, so plan ahead. Create one in the OCI Console under *Analytics & AI → Generative AI → Projects*.
@@ -67,7 +75,7 @@ LOG_LEVEL=info
67
75
68
76
### Models
69
77
70
-
Models are **discovered dynamically** via `listModels` against the configured compartment. Whatever is enabled in your tenancy shows up in the model picker. No env var needed.
78
+
Models are defined as a static list in `src/app/page.js` (`STATIC_MODELS`). To add or remove a model available in your tenancy, edit that array. No env var needed.
71
79
72
80
---
73
81
@@ -85,7 +93,7 @@ The browser hits `middleware.js` first (session guard). If the user has a valid
85
93
Real-time SSE streaming, conversation history persisted in OCI Conversation Store and cached locally (IndexedDB), automatic title generation, markdown rendering with code blocks and tables, multi-file attachments.
86
94
87
95
### Model picker
88
-
Switch models per conversation. The list is discovered dynamically from the configured compartment, so anything enabled in your tenancy shows up automatically.
96
+
Switch models per conversation. The list is curated in `src/app/page.js` (`STATIC_MODELS`); add the models your tenancy has enabled.
Add any MCP endpoint (API key, Bearer token, OAuth2 client credentials, or OAuth 2.1). Test the connection, discover tools, and selectively enable individual functions. Tokens persist through a signed-cookie flow, no secrets stored in localStorage.
121
+
Add any MCP endpoint (API key, Bearer token, OAuth2 client credentials, or OAuth 2.1). Test the connection, discover tools, and selectively enable individual functions. OAuth 2.1 tokens persist through a signed-cookie flow. API keys and OAuth 2.0 `client_secret` values currently live in `localStorage` — for a production multi-user deployment, consider sourcing them from server-side env vars instead.
│ └── mockService.js # Mock responses for offline demos
202
214
│
203
215
├── hooks/
204
216
│ └── useChat.js # Streaming chunk processing + state
@@ -232,7 +244,7 @@ src/
232
244

233
245
234
246
### MCP tool invocation
235
-
1. OCI executes MCP tools natively via the Responses API. the app **does not run tools itself**
247
+
1. OCI executes MCP tools natively via the Responses API. The app **does not run tools itself** during chat (only for Test Connection / Refresh in Settings).
236
248
2. For OAuth 2.1 MCP servers (e.g. SDD Generator), the client obtains an access token via `/api/mcp/oauth/*` and passes it to OCI in the tool's `authorization` field
237
249
3. Custom servers use the more generic `/api/mcp` JSON-RPC proxy for discovery and direct invocation (outside OCI)
238
250
@@ -288,11 +300,10 @@ The app runs as a **standalone Next.js build** inside an [OCI Container Instance
288
300
```
289
301
ALL {resource.type='computecontainerinstance', resource.compartment.id='<compartment-ocid>'}
290
302
```
291
-
4.**IAM policies**: `Identity → Policies → Create`. Grant the dynamic group access to GenAI, Conversation Store, and any other services you use:
303
+
4.**IAM policies**: `Identity → Policies → Create`. Grant the dynamic group access to GenAI:
292
304
```
293
305
allow dynamic-group <dg-name> to use generative-ai-family in compartment <compartment-name>
294
306
allow dynamic-group <dg-name> to manage genai-agent-family in compartment <compartment-name>
295
-
allow dynamic-group <dg-name> to manage objects in compartment <compartment-name>
296
307
```
297
308
5.**(SSO only)** Register the app in **IDCS** as a Confidential Application with redirect URI `https://<your-domain>/api/auth/callback/oci`. Save the Client ID + Secret for the env vars.
- When the LB-to-backend connection is HTTP (not HTTPS end-to-end), cookies must **not** carry the `Secure` flag. `mcp-oauth.js` and the IDCS auth code already handle this automatically when running over HTTP.
349
360
- All secrets (Client Secret, Session Secret, Langfuse keys) should be set as **environment variables on the Container Instance**, never baked into the image.
350
361
362
+
### Alternative: deploy on a Compute VM
363
+
364
+
The app also runs on a regular OCI Compute instance using **Instance Principal** auth. Same flow as above with three differences:
365
+
366
+
1.**Dynamic Group**: match the Compute instance instead of Container Instances, e.g.
367
+
```
368
+
ALL {instance.compartment.id = '<compartment-ocid>'}
369
+
```
370
+
or pin to a specific instance: `ALL {instance.id = 'ocid1.instance.oc1...'}`
371
+
2.**No OCIR / image step**: clone the repo on the VM and run `npm install && npm run build && npm start` (or use a systemd unit / pm2). The Dockerfile + image push are not needed.
372
+
3.**Env var**: set `USE_INSTANCE_PRINCIPAL=true` instead of `USE_RESOURCE_PRINCIPAL=true`.
373
+
374
+
The IAM policies and the Load Balancer setup are identical.
375
+
376
+
### Fronting the app with an API Gateway
377
+
378
+
If you put an **API Gateway** in front of the app instead of (or in addition to) a Load Balancer, configure the deployment to forward two headers to the backend:
379
+
380
+
-`Host` — the original public hostname the client used
381
+
-`X-Forwarded-Proto` — `https`
382
+
383
+
Without these, `getBaseUrl()` builds the wrong `redirect_uri` (using the gateway's internal hostname) and IDCS rejects the SSO callback with `redirect_uri_mismatch`. The same applies to the Load Balancer setup — both should pass `Host` and `X-Forwarded-Proto` through.
384
+
351
385
---
352
386
353
387
## Commands
@@ -365,7 +399,7 @@ npm run test # Playwright tests
365
399
## Troubleshooting
366
400
367
401
**`Invalid value for required field 'model'`**
368
-
The model you selected is not available on the OpenAI-compatible endpoint. Pick a different model in Settings → AI, or extend the app to hit the native endpoint.
402
+
The model you selected is not available on the OpenAI-compatible endpoint. Pick a different model from the model selector in the chat header, or extend the app to hit the native endpoint.
369
403
370
404
**`OCI_COMPARTMENT_ID is required`**
371
405
Missing env var. Set it in `.env.local` for local dev or in the Container Instance env for deployment.
@@ -391,7 +425,7 @@ Harmless. Emitted during SSG when charts render with zero-size containers; they
0 commit comments