In the previous post, I showed how to call the Oracle Private AI Services Container LLM Service from Oracle AI Database 26ai over HTTP.

That setup is useful for development, testing, or internal proof-of-concept environments. For production deployments, you should use HTTPS so that traffic between the database and the container is encrypted and authenticated.

In this post, we’ll use a similar approach, but instead of generating vector embeddings, we’ll call the Oracle Private AI Services Container LLM Service to generate a text response with an LLM.

The main objective is to allow developers to invoke LLM text generation directly from the database.

The package function DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT is a native Oracle AI Database 26ai feature designed to interact with Large Language Models. It allows a user to send a prompt from the database to an AI model, such as the Oracle Private AI Services Container LLM Service, and receive a generated text response.

A similar text-generation API is also available in the lighter-weight DBMS_VECTOR package through DBMS_VECTOR.UTL_TO_GENERATE_TEXT.

As in the privious HTTP example, we’ll ask an LLM a simple question:

input := 'What is SQL?';

Compared to the HTTP example, HTTPS requires a few additional configuration steps:

  • A TLS certificate, so the database can trust the container endpoint.
  • Use of the OS trust store of Oracle Linux instead of a database wallet.
  • An API key credential, so calls to the LLM Service are authenticated.

It is also good practice to run the Oracle Private AI Services Container on a separate host from Oracle AI Database 26ai. LLM inference can require significant CPU, memory, or GPU resources. Running the service separately helps keep database workloads isolated from LLM inference workloads.

To get a quick overview about the topics covered, the post is divided into the following sections:

Let’s get started.

Accessing the Oracle Private AI Services Container LLM Service over HTTPS

Prerequisite – A running Oracle Private AI Services Container

I’m going to assume that the Oracle Private AI Services Container is already installed, configured, and running with HTTP/SSL enabled.

Please refer to the Oracle Private AI Services Container User Guide for installation and configuration instructions.

For this blog post, the container exposes the LLM Service over HTTPS on port 8443.

In this example, I use the container image private-ai:large-gpu-infer-26.2.1.0.0. This image includes vLLM and GPU support, which allows the Oracle Private AI Services Container LLM Service to serve the Ministral-3-3B-Reasoning-2512 model through the chat completions endpoint exposed on the server “your-fully-qualified-hostname”.

This model is shipped inside the container and no additional downloads are required. You can also use other models; those will need to be downloaded separately.

Step 1. Copy the container certificate to the database server

After configuring the Oracle Private AI Services Container for HTTPS (TLS), a certificate file, for example cert.pem, is available on the container host.

For example:

/home/opc/secrets/cert.pem

Copy this certificate to the database server using scp, sftp, or another secure copy method.

For this example, we’ll place it here:

/home/oracle/temp/cert.pem

Next, verify the fully qualified hostname of the container host:

hostname -f

Example output:

your-fully-qualified-hostname

The hostname used in the HTTPS URL must match the certificate. If the certificate was created for a different hostname, TLS validation will fail.

Step 2. Copy the container certificate into the OS trust store directory

Starting with Oracle AI Database 26ai, a database wallet is no longer required for well-known CA root certificates when those certificates are already available in the local operating-system trust store.

The following steps apply to an Oracle Linux system.

a. Verify the Oracle Linux version:

cat /etc/oracle-release

A response looks similar to this:

Oracle Linux Server release 9.5

b. Copy the container’s cert.pem file into the OS trust store directory.

sudo cp /home/oracle/temp/cert.pem /etc/pki/ca-trust/source/anchors/

c. Run the update-ca-trust command so the new certificate is added to the OS trust store.

sudo update-ca-trust

d. Verify that the certificate has been applied.

trust list | more

A response looks similar to this:

pkcs11:id=%BA%80%B8%D5%3C%4B%F3%3E%D9%A8%FB%86%06%A3%70%21%A6%CD%DF%5A;type=cert
    type: certificate
    label: container-server
    trust: anchor
    category: authority

Step 3. Get the API key from the container host

For HTTPS, the call to the Oracle Private AI Services Container LLM Service must be authenticated.

On the container host, locate the API key file. For example:

/home/opc/secrets/api-key

Copy the value from this file.

You’ll need this key value to list the available models, to invoke the LLM endpoint, and later when you create a database credential.

Step 4. Verify the HTTPS endpoint

Before configuring the database, verify that the HTTPS endpoint is reachable from the database server.

Run the following command:

curl -I https://your-fully-qualified-hostname:8443/health

A successful response looks similar to this:

HTTP/1.1 200 OK
date: Tue, 23 Jun 2026 13:15:26 GMT
x-ratelimit-limit-requests: 3000
x-ratelimit-remaining-requests: 2999
x-ratelimit-reset-requests: 1
x-server-id: 3c66bfe8-b586-4b8f-b258-a93d058ce074
content-length: 0

The 200 OK status confirms that the container is reachable over HTTPS and that the certificate can be used to validate the endpoint.

After verifying that the container is running, you can query the models endpoint to see which models are currently available through the Oracle Private AI Services Container LLM Service.

In an HTTPS setup, add the API key from the container host using Bearer authentication.

Run the following command:

curl --header "Authorization: Bearer your_api_key_from_container_host" \  https://your-fully-qualified-hostname:8443/v1/models | jq

The jq utility formats the JSON response for easier reading.

On Oracle Linux, you can install jq with: 

sudo dnf install –y jq 

On Ubuntu Linux, use: 

sudo apt install –y jq 

The response should include the available models, including the Ministral-3-3B-Reasoning-2512 model.

{
  "data": [
    {
      "id": "Ministral-3-3B-Reasoning-2512",
      "modelDeployedTime": "2026-07-31T14:38:47.516225405Z",
      "modelSize": "7.20G",
      "modelCapabilities": [
        "TEXT_GENERATION"
      ]
    },
...  
}

Next, test the LLM Service endpoint directly with curl.

The text generation endpoint is:

/v1/chat/completions

Again, in an HTTPS setup, add the API key from the container host using Bearer authentication.

Run the following command:

curl -i --cacert /home/oracle/temp/cert.pem \
  https://your-fully-qualified-hostname:8443/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_api_key_from_container_host" \
  -d '{
        "model": "Ministral-3-3B-Reasoning-2512",
        "messages": [
          {
            "role": "user",
            "content": "What is SQL?"
          }
        ],
        "max_tokens": 128,
        "temperature": 0
      }'

If the service is configured correctly, the response payload should contain generated text for the question “What is SQL?”, for example:

SQL, or Structured Query Language, is a standard language used to manage and query data stored in relational databases. 
...

Step 5. Grant network access from the database

Oracle Database controls outbound network access with network ACLs. Before a database user can call an the Oracle Private AI Services Container LLM Service over HTTP, a DBA must grant the required network permission.

In this example, the database user is:

vectordb

The container host is:

your-fully-qualified-hostname

The HTTPS port is:

8443

Run the following PL/SQL block as the PDB’s SYS or SYSTEM user:

sql
BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host       => 'your-fully-qualified-hostname',
    lower_port => 8443,
    upper_port => 8443,
    ace        => xs$ace_type(
                    privilege_list => xs$name_list('http'),
                    principal_name => 'vectordb',
                    principal_type => xs_acl.ptype_db));
END;
/

This grants the vectordb schema permission to make HTTPS calls to the specified host and port.

The example uses the http privilege because that is the privilege needed for HTTP and HTTPS calls through the database networking APIs. You could also grant connect, but that provides broader capabilities than required here.

Step 6. Verify the network ACL

Run the following command as user vectordb and check the ACL entry:

SELECT host, lower_port, upper_port, privilege, status
FROM user_host_aces;

The expected output should include a row similar to this:

HOST                          LOWER_PORT UPPER_PORT PRIVILEGE STATUS
----------------------------- ---------- ---------- --------- -------
your-fully-qualified-hostname 8443       8443       HTTP      GRANTED

This confirms that the current schema can call:

https://your-fully-qualified-hostname:8443/...

If the ACL is missing or incorrect, the PL/SQL call will fail. A common error is:

ORA-29273: HTTP request failed

To get more details, run:

SELECT UTL_HTTP.GET_DETAILED_SQLERRM;

A response looks similar to this:

GET_DETAILED_SQLERRM
--------------------------------------------------------------------------------
ORA-24247: network access denied by access control list (ACL)

This usually means that the ACL was not granted, was granted to the wrong user, or was created for the wrong host or port. Please see the Troubleshooting section of this post for steps to resolve the issue. 

Step 7. Create a credential for the API key

Connect as the database user that will call the LLM Service.

If you already have a credential from an earlier test, you can drop it first. This is also useful when rotating API keys.

BEGIN
  DBMS_VECTOR_CHAIN.DROP_CREDENTIAL('PRIVATEAI_LLM_CRED');
EXCEPTION
  WHEN OTHERS THEN NULL;
END;
/

Create the credential and store the API key in access_token:

DECLARE
  jo JSON_OBJECT_T;
BEGIN
  jo := JSON_OBJECT_T();
  jo.put('access_token', 'your_api_key_from_container_host');

  DBMS_VECTOR_CHAIN.CREATE_CREDENTIAL(
    credential_name => 'PRIVATEAI_LLM_CRED',
    params          => json(jo.to_string));
END;
/

The credential name PRIVATEAI_LLM_CRED will be referenced in the JSON parameters used by DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT.

Call the LLM Service and generate text from PL/SQL

We can now call the Oracle Private AI Services Container LLM Service from PL/SQL over HTTPS. The PL/SQL example is useful for procedural applications, while the SQL example in the next section is convenient for ad hoc testing, demonstrations, and SQL-based workflows.

The following block sends the question “What is SQL?” to the model and prints the generated answer.

SET SERVEROUTPUT ON

DECLARE
  input  CLOB;
  params CLOB;
  output CLOB;
BEGIN
  input := 'What is SQL?';

  params := '
  {
    "provider": "privateai",
    "credential_name": "PRIVATEAI_LLM_CRED",
    "url": "https://your-fully-qualified-hostname:8443/v1/chat/completions",
    "model": "Ministral-3-3B-Reasoning-2512",
    "temperature": 0,
    "max_tokens": 256,
    "transfer_timeout": 30
  }';

  output := DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(
              input,
              json(params));

  DBMS_OUTPUT.PUT_LINE(output);

  IF output IS NOT NULL THEN
    DBMS_LOB.FREETEMPORARY(output);
  END IF;

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLERRM);
    DBMS_OUTPUT.PUT_LINE(SQLCODE);
END;
/

A typical response may look like this:

SQL, or Structured Query Language, is a standard language used to store, query, update, and manage data in relational databases.

Let’s look at the important parts of the JSON payload.

{
  "provider": "privateai",
  "credential_name": "PRIVATEAI_LLM_CRED",
  "url": "https://your-fully-qualified-hostname:8443/v1/chat/completions",
  "model": "Ministral-3-3B-Reasoning-2512",
  "temperature": 0,
  "max_tokens": 256,
  "transfer_timeout": 30
}

The parameters are:

  • provider: “privateai” – Identifies the Oracle Private AI Services LLM Service provider.
  • credential_name: Required to authenticate against the container.
  • url: Points to the HTTPS text generation endpoint. 
  • model : Identifies the model used to generate the response, for example “Ministral-3-3B-Reasoning-2512”. 
  • temperature: Controls the variability of the generated text. 
  • max_tokens: Sets the maximum response length. 
  • transfer_timeout: Maximum wait time before timeout.

DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT sends the prompt and parameters to the configured LLM Service and returns the generated text response.

The first request to the model may take a little longer than later requests. This is expected because the model may need to be loaded into memory before it can generate a response. Once loaded, subsequent requests are usually faster.

Call the LLM Service and generate text from SQL

The same LLM Service can also be called directly from SQL.

First, define the parameter JSON as a SQL*Plus bind variable:

VAR params CLOB;

BEGIN
  :params := '{
    "provider": "privateai",
    "credential_name": "PRIVATEAI_LLM_CRED",
    "url": "https://your-fully-qualified-hostname:8443/v1/chat/completions",
    "model": "Ministral-3-3B-Reasoning-2512",
    "temperature": 0,
    "max_tokens": 256,
    "transfer_timeout": 30
  }';
END;
/

Configure the SQL*Plus output::

SET LONG 100000
SET LONGCHUNKSIZE 100000
SET LINESIZE 200
SET PAGESIZE 0
SET HEADING OFF
SET FEEDBACK OFF
SET TRIMSPOOL ON

Now call the PL/SQL package from SQL:

SELECT DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT
       ('What is SQL?', 
         JSON(:params)
       ) AS generated_text;

The generated output should be similar to this:

SQL, or Structured Query Language, is a standard language used to manage and query data stored in relational databases.
...

This SQL pattern is useful when you want to integrate text generation into SQL-driven workflows, demos, or application logic.

Increasing the transfer timeout

LLM requests can take longer than embedding requests. This is especially true when the model is loaded for the first time or when the prompt asks for a longer answer.

If the request fails with:

ORA-29276: transfer timeout

increase transfer_timeout in the parameter JSON:  

"transfer_timeout": 120 

The value is specified in seconds. In this example, the database waits up to 120 seconds for the service to return a response.

You can also reduce max_tokens if you want the model to return a shorter answer.

"max_tokens": 128 

In this case we reduce max_tokens from 256 to 128.

Troubleshooting

  • ORA-29273 / ORA-24247: Network ACL missing or incorrect. Verify with SELECT host, lower_port, upper_port, privilege, status FROM user_host_aces; 
  • ORA-29276: Model cold-start or slow inference. Increase transfer_timeout or reduce max_tokens.
  • Other Checks: Hostname correct? Was the container certificate copied to the OS trust store directory, and was the trust store updated successfully? Is port 8443 open? Does the firewall allow traffic? Is the container listening on the expected interface? Is the model available and loaded? Does the container have sufficient CPU/GPU/RAM?  

Summary

In this post, you called the Oracle Private AI Services Container LLM Service from Oracle AI Database 26ai over HTTP/SSL.

You verified that the container was running, copied the container certificate to the database server, added the certificate to the database server’s OS trust store, tested the HTTP/SSL endpoint, checked the available models, stored the API key as a database credential, granted the required network ACL, and generated text from both PL/SQL and SQL using DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT.

The example used the Ministral-3-3B-Reasoning-2512 model and the simple question:

input := 'What is SQL?';

With HTTP/SSL, requests from the database to the Oracle Private AI Services Container LLM Service are encrypted and authenticated, making this the recommended approach for production deployments.

Resources